我的c#(.NET 4.7.1)代码中包含以下lambda expression
:
DataRow[] skmRows = dtSKM.AsEnumerable().Where(x =>
x.Field<int>("NDRAWING1").Equals(NDRAWING1) &&
x.Field<Int16>("NDRAWING2").Equals(NDRAWING2)
).ToArray();
所有内容都会编译,并且在运行时不会引发任何异常。问题在于上面的lambda表达式应该获得结果-但事实并非如此。我在断点处停下来,并验证了应该发生匹配的DataRows
。
因此,我然后将此表达式复制到Immediate
的{{1}}窗口中并运行它-并且它 DID 获得匹配的DataRows。 WTH ??
所以我想知道VS2017
。 MSSQL中的相关列是Int16
,它映射到C#中的INT16。对于踢,我将sql server中的数据类型从smallint更改为int,从而更改了我的lambda:
SMALLINT
...而且有效!! (我得到了预期的匹配行。)
这使我得出结论,.NET中存在一个错误,在该错误中,运行时无法根据smallint sql服务器列值正确评估Int16比较。
除了 bug 之外,还有其他解释吗?我猜这对任何人来说都应该很容易复制。整理一个lambda,使其与MSSQL中的SMALLINT列匹配,看看会发生什么。
答案 0 :(得分:3)
smallint 确实映射到 int16 ,也称为 short 。您可以在adonet server data type mappings进行验证。至于发生了什么,请检查int16等于= "true if obj is an instance of Int16 and equals the value of this instance; otherwise, 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内核并在内存db中,但它显示了一种实现方法。在您的情况下,您可以进行以下更改:
var data = dtSKM.AsEnumerable().ToList();
DataRow[] skmRows = data.Where(x =>
x.Field<int>("NDRAWING1").Equals(NDRAWING1) &&
x.Field<Int16>("NDRAWING2").Equals(NDRAWING2)
).ToArray();
,您可以使用调试器验证数据实例的类型/值。您的假设之一不成立,也不是“ .NET中的错误”。