C# Where子句后跟返回相同值的FirstOrDefault
我有一个类,它的函数如下:C# Where子句后跟返回相同值的FirstOrDefault,c#,entity-framework,sql-server-2012,C#,Entity Framework,Sql Server 2012,我有一个类,它的函数如下: public string Code { get; set; } public Dal.Foo GetFoo(Dal.MyContext ctx) { var obj = ctx.Foos.Where(f => f.Code == this.Code).FirstOrDefault(); return obj; } using (var ctx = new Dal.MyContext()) { var curr = parameter
public string Code { get; set; }
public Dal.Foo GetFoo(Dal.MyContext ctx)
{
var obj = ctx.Foos.Where(f => f.Code == this.Code).FirstOrDefault();
return obj;
}
using (var ctx = new Dal.MyContext())
{
var curr = parameters.Current.GetFoo(ctx);
var target = parameters.Target.GetFoo(ctx);
// ...
}
现在这个通常很好用。但是,我在另一个类中调用了另一个函数,如下所示:
public string Code { get; set; }
public Dal.Foo GetFoo(Dal.MyContext ctx)
{
var obj = ctx.Foos.Where(f => f.Code == this.Code).FirstOrDefault();
return obj;
}
using (var ctx = new Dal.MyContext())
{
var curr = parameters.Current.GetFoo(ctx);
var target = parameters.Target.GetFoo(ctx);
// ...
}
问题是,Current
和Target
绝对是不同的对象,它们的code
值肯定不同,但当我执行此代码时,我的curr
和Target
的结果是相同的对象curr==target
返回它实际上不应该返回的true
。我甚至查看了从GetFoo
方法生成的SQL,它使用不同的参数正确地调用数据库,并且在SQLServerManagementStudio中执行这些命令会返回两个预期的不同结果。我可以通过不给他们相同的上下文来解决这个问题(即使用带有新的MyContext
的块将第二个调用放入它自己的),但这确实不必要
这是怎么回事
编辑:不确定这是否相关,但我应该指出,我实际上是在访问SQL server上的一个视图,而不是一个表。尽管如此,它仍然在生成看起来正确的SQL,并为Where
子句传入正确的参数
另一编辑:
我试着在得到obj的那行之后添加这个:
System.Diagnostics.Debug.Assert(obj.Code == this.Code);
它在第一次调用时传递,在第二次调用时失败。这似乎是不可能的。实体框架上下文是一个,即它在数据库中保留每个实体的单个副本。即使从数据库中重新获取对象,EF也不会修改本地副本中的值。我认为这是因为它会干扰更改跟踪,并且可能会覆盖同时进行的客户端更改
因此,根据设计,curr==target
和code
始终是从数据库中获取的第一个值,除非在客户端代码中对其进行了修改(在这种情况下,curr
和target
显然都具有修改后的值)。好的-我想我找到了问题所在@GertArnold的回答帮助我找到了原因。问题是,无论出于何种原因,当我将视图导入实体框架时,EF决定使用数据库中的另外两个(且不相关)字段来构造键,而不是code
(实际上是键)。我在edmx
文件中将Entity Key
设置为True
,现在它按预期工作
我猜是因为,就EF而言,我没有更改主键,返回相同的对象是可以的,即使它实际上与Where
标准不匹配。它生成的整个SQL都是可怕的误导和混淆,因为我猜它根本就没有实际执行过。据我所知,您正在访问相同上下文ctx
的相同对象Foos
,与Current
和Target
无关。为什么它会与自身不同?@Thaoden,注意他是通过this.code
进行过滤的,它将为不同的实例保存不同的值class@GiorgiNakeuri我的bad@MattBurland,在调试模式下,当您在var obj=ctx.Foos.Where(f=>f.code==this.code).FirstOrDefault()上有断点时代码>那里一切正常吗?你看到不同的代码了吗?您是否在返回线上看到不同的返回对象?也许你最好发布一下你是如何创建你的类的?同样第二次失败
是否可以添加引发的异常?是哪个EF版本?您尝试从LINQ查询中删除<代码>这个代码<代码>,并使用具有这个代码的值的本地变量吗?如果我们考虑简单的控制台应用程序,它只创建上下文,然后从具有不同ID的T上下文中选择2个命令,你想说这两个对象都是相同的吗?我不怀疑这与标识映射有关,但我不能在同一上下文上进行两次调用,将不同的值传递给where子句并获得两个不同的对象,这一点毫无意义。在第二种情况下,返回的对象在检索时甚至不满足Where
子句。@MattBurland你说得对。那没有道理。通过您的发现curr==target,我得出结论,不同的参数确实产生了相同的结果(这毕竟是可能的)。如果EF没有合适的视图主键,也就是由保证唯一的字段组合组成的键,则可能会出现这种问题。看起来问题在于EF认为键实际应该是什么,而不是它应该是什么。我投了你一票,因为你对身份地图的评论确实为我指明了思考身份地图用作钥匙的方向。我仍然不确定它对我是否真的有意义,因为Where
子句显然没有得到满足,但将code
标记为EntityKey
似乎确实解决了这个特殊问题。啊,很高兴你找到了它@格塔诺尔:我会尽我所能(除非我忘记,我可能会忘记)。