ASP.NET EF6 查询模型
Posted
技术标签:
【中文标题】ASP.NET EF6 查询模型【英文标题】:ASP.NET EF6 Query Model 【发布时间】:2015-02-27 05:46:27 【问题描述】:我有以下型号。每个模块都有一个嵌套的模块类型的子集合。每个模块还有一个权限集合。
[DataContract(IsReference = true)]
public class Module
[Key]
[DataMember]
public Guid ModuleId get; set;
[Required]
[StringLength(100)]
[DataMember]
public string Title get; set;
[StringLength(100)]
[DataMember]
public string Description get; set;
[StringLength(50)]
[DataMember]
public string Icon get; set;
[Required]
[RegularExpression(@"[^\s]+")]
[StringLength(50)]
[DataMember]
public string Route get; set;
[DataMember]
public ICollection<Permission> Permissions get; set;
[DataMember]
public Guid? ParentModuleId get; set;
[ForeignKey("ParentModuleId")]
[DataMember]
public virtual ICollection<Module> Children get; set;
[DataContract(IsReference = true)]
public class Permission
[Key]
[DataMember]
public Guid PermissionId get; set;
[Required]
[StringLength(100)]
[DataMember]
public string Role get; set;
[DataMember]
public Guid ModuleId get; set;
[ForeignKey("ModuleId")]
[DataMember]
public Module Module get; set;
我有一个如下所示的 Query All 函数,它将正确返回所有根及其子项。
public override IQueryable<Module> All()
return this.Context.Set<Module>().Include(c => c.Children).Where(p => p.ParentModuleId == null);
现在,我想返回相同的根列表及其具有“用户”权限的子节点。我该怎么做呢。这就是我到目前为止所拥有的。这是正确的做法吗?请帮忙。
return this.Context.Set<Module>().Include(c => c.Children).Where(p => p.ParentModuleId == null).Include(p => p.Permissions).Where(s => s.Permissions.Any(r=>r.Role=="User"));
顺便说一句,我不知道如何正确使用这些函数,例如 include、where、any、select many 函数。对此的任何教程或书籍表示赞赏。我找不到任何关于此的好的教程,因为我不知道要搜索什么关键字。这是 EF 还是 LINQ。
【问题讨论】:
您的代码在我看来是正确的,有问题吗?虽然,它只会检查根模块的权限集,而不是它的子模块。 我还要补充一点,懒加载默认是开启的,也就是说你不需要使用.Include
(除非你特意禁用了懒加载),可以访问navigational属性直接和 EF 将延迟加载它。
问题出在孩子身上,它没有检查孩子的权限。我该怎么做?
我认为您正在寻找“过滤包含”(这是不可能的):***.com/a/16801205/861716
只是为了确认:显然孩子不会拥有父母没有的权限,对吧?
【参考方案1】:
Include
方法告诉 Entity Framework 在它进入数据库以带回记录时填充特定的导航属性(即它急切加载数据而不是利用延迟加载,这需要 EF 返回数据库稍后)。它不做任何类型的过滤。所有这些都由“Where”方法完成。
要对所有孩子进行您要求的那种过滤,您必须做以下两件事之一:
1) 在 SQL 中创建一个公共表表达式,它将递归地获取特定模块的所有子项,将该 CTE 放置在 SQL 视图中,将 EF 实体映射到该视图,然后查询该视图,包括 @ 987654322@ 到Permissions
表只获取那些拥有您正在寻找的权限的人。
2) 要在没有 T-SQL 乐趣的情况下执行此操作,只需在 Module
类上创建一个递归函数,并在其上使用 [NotMapped]
属性,该函数将遍历所有子级并仅返回具有您正在寻找的权限(注意:这将需要比第一个更多的资源,并且在您的应用程序中会更慢,因为这将主要是 LINQ to Objects 查询而不是 LINQ to Entities)。
类似这样的:
[NotMapped]
public List<Module> GrabModulesWithPermission(string permission)
var toReturn = new List<Module>();
if (this.Children != null && this.Children.Any(c => c.Permissions.Any(r => r.Role == permission))
toReturn.AddRange(this.Children.Where(c => c.Permissions.Any(r => r.Role == permission).SelectMany(c => c.GrabModulesWithPermission(permission)));
toReturn.Add(this);
return toReturn;
就教程而言,我强烈建议您查看 Pluralsight。 EF 上有许多视频,其中包括一些由 Microsoft 的 EF MVP Julie Lerman 制作的视频。
【讨论】:
以上是关于ASP.NET EF6 查询模型的主要内容,如果未能解决你的问题,请参考以下文章
面向具有 EF6 和 Identity 的完整框架的 ASP.NET Core