我正在使用EF5,并且当关系为1:N时,如果要加载相关实体,请执行以下操作:
使用T-SQL,我可以使用T-SQL从数据库中加载主要实体,如下所示:
select *
from MainEntities
where ...
使用T-SQL加载相关实体
select *
from RelatedEntities
where IDMainEntity IN (---)
此时,EF用相关实体填充主要实体的属性导航。另外,在每个实体的类型的局部属性中,dbContext
我具有每种类型的所有实体。
但是,如果我对N:N关系执行相同的操作,则我没有该关系中间表的实体,当我执行查询时,我在dbContext
每种类型的实体的本地拥有查询,但是属性导航未填充。
我想知道为什么以及是否存在其他选择。
我之所以使用这种方式,是因为我想使用T-SQL创建动态查询。如果我使用急切加载,则动态查询的灵活性不如使用TSQL的灵活性,而且效率较低。如果我使用显式加载,则我要进行N个附加查询,这是主实体结果中的每条记录之一。按照我的方式,我只会附加一个查询,因为我会立即获得所有相关实体。如果我使用延迟加载,则会遇到相同的问题,即N个其他查询。
当关系为N:N时,为什么EF不填充相关属性?
谢谢。
您正在谈论的功能称为“关系跨度”或“关系修正”,实际上-正如您已经注意到的-它不适用于多对多关系。仅当关联的至少一端具有多重性1(或0..1)时才有效,即,它适用于一对多或一对一关系。
关系跨度依赖于具有外键的实体。它具有显式外键属性(外键关联)还是对应的数据库表中只有外键列而模型中没有属性(独立关联)并不重要。在这两种情况下,当实体被加载时,FK值都将被加载到上下文中。基于此外键值,EF可以确定是否将与该FK值具有相同主键值的相关实体附加到上下文,如果是,则它可以“修复关系”,即可以填充导航属性正确。
现在,在多对多关系中,两个相关实体都没有外键。外键为此关系存储在链接表中,并且-您知道-链接表没有相应的模型实体。结果,外键将永远不会被加载,因此上下文无法确定关联的附加实体,也无法修复多对多关系并填充导航集合。
EF会支持您以多对多关系使用填充的导航集合构建正确的对象图的唯一LINQ查询急于加载...
var user = context.Users.Include(u => u.Roles).First();
或延迟加载...
var user = context.Users.First();
var rolesCount = user.Roles.Count();
// Calling Count() or any other method on the Roles collection will fill
// user.Roles via lazy loading (if lazy loading is enabled of course)
...或将结果直接分配给导航集合的显式加载:
var user = context.Users.First();
user.Roles = context.Entry(user).Collection(u => u.Roles).Query().ToList();
加载相关实体的所有其他方式(例如投影,直接SQL语句或显式加载而不分配给导航集合),即使用.Load()
而不是.Query().ToList()
在上面的最后一个代码片段中使用-不会修复该关系,并且会将导航集合留空。
如果您打算主要执行SQL查询而不是LINQ查询,那么我看到的唯一选择是编写自己的关系管理。除了两个相关实体的表之外,您还必须查询链接表。您可能需要一个帮助程序类型(不是实体)和一个包含链接表的两个FK列值的集合,并且可能需要一个帮助程序例程,该例程通过检查您发现的实体的主键值来填充导航集合附加在DbSet<T>.Local
集合中以及FK值在助手集合中。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句