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 查询模型的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET MVC Core/6:EF 6 脚手架错误

如何在 asp.net 5 项目中启用迁移(EF6)?

面向具有 EF6 和 Identity 的完整框架的 ASP.NET Core

如何使用 MVC3 ASP.NET 4.5 和 EF6 基于实体属性注释对 TextBoxFor 进行舍入

如何使用 ASP.NET Core 设置 EF6 迁移

基于 jQuery 的专业 ASP.NET WebForms/MVC 控件库!