Lambda 不能进行 Int16 比较吗?

lambda expression我的 C# (.NET 4.7.1) 代码中有以下内容:

DataRow[] skmRows = dtSKM.AsEnumerable().Where(x =>
   x.Field<int>("NDRAWING1").Equals(NDRAWING1) &&
   x.Field<Int16>("NDRAWING2").Equals(NDRAWING2)
   ).ToArray();

一切都会编译,并且在运行时不会引发异常。问题是上面的 lambda 表达式应该得到结果,但事实并非如此。我停在断点处并验证DataRows应该已经发生匹配。

然后我将这个表达式复制到Immediate窗口中VS2017并运行它——它确实获得了匹配的数据行。啥??

然后我就想知道这一点Int16。MSSQL 中的相关列是 a SMALLINT,它映射到 C# 中的 INT16。为了好玩,我将 sql server 中的数据类型从smallint更改为int,并因此更改了我的lambda:

DataRow[] skmRows = dtSKM.AsEnumerable().Where(x =>
   x.Field<int>("NDRAWING1").Equals(NDRAWING1) &&
   x.Field<int>("NDRAWING2").Equals(NDRAWING2)
   ).ToArray();

...它成功了!(我按预期得到了匹配的行。)

这让我得出结论,.NET 中存在一个错误,运行时无法正确评估 Int16 与smallint sql server 列值的比较。

除了bug还有解释吗?我猜这对任何人来说都应该很容易重现。启动一个 lambda 来匹配 MSSQL 中的 SMALLINT 列,看看会发生什么。


慕尼黑5688855
浏览 82回答 1
1回答

沧海一幻觉

确实,smallint映射到int16又名Short。您可以在adonet 服务器数据类型映射处验证它。至于发生了什么,请检查 int16 equals 的文档:“如果 obj 是 Int16 的实例并且等于该实例的值,则为 true;否则为 false。” 。变量NDRAWING2也需要是int16 。在Javascript中,有运算符“===”来表示值和类型必须相同。通过正确的抽象,使用 Microsoft.EntityFrameworkCore.InMemory 2.2.6 和 NUnit 3.2,我将:在内存数据库上下文中创建添加上下文到服务使用服务添加一些数据并将它们存储到数据库验证它在新上下文中是否有一些数据使用服务查找我想要的数据验证它确实找到了数据代码示例:class Program{    static void Main(string[] args)    {        var options = new DbContextOptionsBuilder<DtSkmContext>()            .UseInMemoryDatabase(databaseName: "Add_writes_to_database")            .Options;        using (var context = new DtSkmContext(options))        {            var service = new DtSkmService(context);            service.Add(3, 7);            context.SaveChanges();        }        using (var context = new DtSkmContext(options))        {            Assert.That(context.DtSkm.Count(), Is.EqualTo(1));            var service = new DtSkmService(context);            var result = service.Find(3, 7);            Assert.That(result, Is.Not.Null);        }    }}服务public class DtSkmService{    private DtSkmContext _context;    public DtSkmService(DtSkmContext context)    {        _context = context;    }    public void Add(int ndrawing1, Int16 ndrawing2)    {        var dtSkm = new DtSkmDto { Ndrawing1 = ndrawing1, Ndrawing2 = ndrawing2 };        _context.DtSkm.Add(dtSkm);        _context.SaveChanges();    }    public IEnumerable<DtSkmDto> Find(int first, Int16 second)    {        return _context.DtSkm            .Where(b => b.Ndrawing1.Equals(first) && b.Ndrawing2.Equals(second))            .OrderBy(b => b.Ndrawing1)            .ToList();    }}和 dto 和上下文public class DtSkmDto{    public int Id { get; set; }    [Required]    public int Ndrawing1 { get; set; }    [Required]    public Int16 Ndrawing2 { get; set; }}public class DtSkmContext : DbContext{    public DtSkmContext()    {    }    public DtSkmContext(DbContextOptions<DtSkmContext> options) : base(options)    {    }    public DbSet<DtSkmDto> DtSkm { get; set; }}虽然这使用 EF core 和内存数据库,但它展示了一种实现方法。根据您的情况,您可以进行一些小的更改:var data = dtSKM.AsEnumerable().ToList();DataRow[] skmRows = data.Where(x =>   x.Field<int>("NDRAWING1").Equals(NDRAWING1) &&   x.Field<Int16>("NDRAWING2").Equals(NDRAWING2)   ).ToArray();您可以使用调试器验证数据实例类型/值。你的假设之一不成立,它不是“.NET 中的错误”。
打开App,查看更多内容
随时随地看视频慕课网APP