min*_*ods 9 linq entity-framework include dbcontext
看起来实体框架(来自NuGet的最新版本)在为导航属性构建连接时可能忽略HasRequired配置,而不是定义的第一个.
例如,给定具有以下配置的POCO对象(Person):
var person = modelBuilder.Entity<Person>();
person.ToTable("The_Peoples");
person.HasKey(i => i.Id);
person.Property(i => i.Id).HasColumnName("the_people_id");
person.HasRequired(i => i.Address)
.WithMany()
.Map(map => map.MapKey("address_id"));
person.HasRequired(i => i.WorkPlace)
.WithMany()
.Map(map => map.MapKey("work_place_id"));
Run Code Online (Sandbox Code Playgroud)
我正在尝试使用以下查询加载人员列表:
myContext.Set<People>()
.Include(o => o.Address)
.Include(o => o.WorkPlace);
Run Code Online (Sandbox Code Playgroud)
实体框架生成以下查询:
FROM [dbo].[The_Peoples] AS [Extent1]
INNER JOIN [dbo].[The_Addresses] AS [Extent2] ON [Extent1].[address_id] = [Extent2].[address_id]
LEFT OUTER JOIN [dbo].[The_Work_Places] AS [Extent3] ON [Extent1].[work_place_id] = [Extent3].[work_place_id]
Run Code Online (Sandbox Code Playgroud)
请注意,*The_Addresses*表的连接是内连接(如预期的那样),但是,*The_Work_Places*的后续连接是外连接.鉴于Address和WorkPlace属性都标记为必需,我希望两个连接都是内连接.我还尝试使用Required属性标记Address和WorkPlace属性,但这没有任何效果.
这是一个错误还是我可能错误配置了什么?建议?
你的模型配置是正确的,我认为这不是一个错误,但它是设计行为,但我不知道究竟是什么设计.我也在这样的查询中看到过SQL.只有几点评论:
您看到的查询并非特定于EF 4.2.EF 4.1和EF 4.0也会出现这种情况.但不适用于EF 1(.NET 3.5).在EF 1中,每个Include,也是第一个,已经映射到a LEFT OUTER JOIN,也用于所需的关系.
我认为不能说使用一个INNER JOIN"正确"的所需导航属性LEFT OUTER JOIN是错误的.鉴于数据库中的约束正确表示模型中的关系,从映射视点来看,使用什么并不重要.对于必需的导航属性,数据库中的FK列不能为空,并且数据库中必须有一个约束,强制FK引用目标表中的现有行.如果是这种情况,JOIN无论您使用INNER JOIN或是,都必须返回一行LEFT OUTER JOIN.
如果模型和数据库关于关系"不同步"会发生什么?在两种情况下基本上都是无意义的:如果你使用a LEFT OUTER JOIN并且FK NULL在DB中或引用不存在的行,你将得到一个导航属性所在的实体null,违反了属性所需的模型定义.使用的INNER JOIN是不是更好:你会得到任何单位所有,查询结果至少是错了,因为用的结果LEFT OUTER JOIN,如果不是更糟.
因此,我认为.NET 4中使用INNER JOINs 的变化Include并不是因为EF 1中的SQL错误,而是创建更好,性能更高的SQL.这一变化实际上引入了一个重大变化,一些查询现在返回其他结果,而不是在EF 1中:http://thedatafarm.com/blog/data-access/ef4-breaking-change-ef4-inner-joins-affect-渴望加载一对多一对多/
我的理解是,这已得到修复,原因是INNER JOIN在很多情况下已经为EF 4中的急切加载引入了.(也许在这个阶段(EF 4的beta/release候选者)你的查询将有两个INNER JOINs .)EF团队对该问题的回复:http://connect.microsoft.com/VisualStudio/feedback/details/534675/ef4-include-method-returns-different-results-than-ef1-include(粗体突出显示)从我):
我们正在修复.net 4 RTM的问题.这是一次意想不到的突破性变化.我们没有进行预期的更改,其中Include生成的每个左外连接都成为.Net 4中的内连接.而是优化查看了EF元数据中的约束并尝试转换那些可以安全转换的左外连接基于约束的内连接.我们在这里我们在此基础上产生了更积极的转换比限制暗示什么约束推理代码中的错误.我们缩减了优化,以便我们将左外连接转换为内连接仅在我们绝对确定我们可以根据约束进行的地方.我们认为我们可以在未来进一步改进这种优化.与RC和Beta 2相比,您将在RTM中开始查看更多左外连接,但在大多数情况下,需要返回正确的结果.
因此,EF 4的最终版本显然重新引入了一些LEFT OUTER JOINs(与beta/release候选者相比),以避免像这样的突破性变化.
对不起,这是一个历史故事,而不是一个真正的解释为什么你得到一个INNER JOIN然后一个LEFT OUTER JOIN.如上所述,以这种方式编写查询并没有错 - 因为使用两个INNER JOIN或两个LEFT OUTER JOINs 并不是错误的.我想只有EF团队才能解释为什么你的查询产生了特定的SQL.
我建议 - 如果你没有遇到严重的性能问题 - 不要担心SQL(因为你得到的结果是正确的毕竟),并继续进行.不喜欢EF创建的SQL,最终会编写大量功能和更改请求,或者编写大量原始SQL查询或放弃EF.
| 归档时间: |
|
| 查看次数: |
1604 次 |
| 最近记录: |