【问题标题】:Entity Framework constrains on navigation properties实体框架对导航属性的约束
【发布时间】:2012-07-19 20:17:59
【问题描述】:

我想限制导航属性返回的模型。例如,我使用AuditInfo 模型来记录模型的活动。删除模型后,将设置 DeletedByDeleted 属性。但是,由于没有真正从数据库中“删除”任何内容,因此这些模型仍将填充到其他模型引用的导航属性中。

AuditInfo 类

public class AuditInfo
{
    [Key]
    public int AuditInfoID { get; set; }

    //Other attributes

    public string DeletedBy { get; set; }

    public DateTime? Deleted { get; set; }
}

具有导航属性的类

public class BlogPost
{
    //Other attributes

    //Only return Comment where Comment.AuditInfo.Deleted is NULL
    public virtual IList<Comment> Comments { get; set; }
}

正在审核的类

public class Comment
{
    //Other attributes

    public int AuditInfoID { get; set; }
}

我将如何设置约束以使 BlogPost.Comments 中只有未删除的 cmets(Comment.AuditInfo.Deleted 为 NULL)?

【问题讨论】:

  • 如何填充 BlogPost.Comments?您不能通过检查 BlogPost.Comments.AuditInfo.Deleted = false 来填充 BlogPost.Comments 吗?
  • 它是使用实体框架填充的。由于每个评论都有一个与 BlogPost 关联的外键,因此框架将自动检测一对多关系并填充导航属性。

标签: c# .net sql sql-server entity-framework


【解决方案1】:

(我假设您使用的是 EF Code-First,因为 [Key] 属性。)

加载导航属性和相关实体的方法有多种,您可以为其中一些方式应用过滤器,但不是全部:

  • 延迟加载:

    你的导航属性必须是virtual,这样延迟加载才能工作:

    public virtual IList<Comment> Comments { get; set; }
    

    加载父节点:

    var blogPost = context.BlogPosts.Find(1);
    foreach (var comment in blogPost.Comments) // lazy loading triggered here
    {
    }
    

    您不能在此处应用过滤器。延迟加载将始终加载给定博客文章的所有个 cmets。

  • 渴望加载:

    var blogPost = context.BlogPosts.Include(b => b.Comments)
        .SingleOrDefault(b => b.Id == 1);
    

    您不能在Include 中应用过滤器。急切加载将始终加载给定博客文章的所有 cmets。

  • 显式加载:

    加载父节点:

    var blogPost = context.BlogPosts.Find(1);
    

    您现在可以在加载 cmets 时应用过滤器:

    context.Entry(blogPost).Collection(b => b.Comments).Query()
        .Where(c => !c.AuditInfo.Deleted.HasValue)
        .Load();
    
  • 投影:

    您可以在投影属性中应用过滤器:

    var blogPost = context.BlogPosts
        .Where(b => b.Id == 1)
        .Select(b => new
        {
            BlogPost = b,
            Comments = b.Comments.Where(c => !c.AuditInfo.Deleted.HasValue)
        })
        .SingleOrDefault();
    

不可能在模型定义中应用某种全局过滤策略,以便此过滤器自动应用于上述所有方法,而无需在显式加载和投影中明确指定它例子。 (我认为您已经想到了这样一个全局模型定义,但这是不可能的。)

【讨论】:

    【解决方案2】:

    可能给实体类添加一个自定义属性,它会使用导航属性但过滤它并返回过滤后的数据?

    【讨论】:

    • 我想这样做,但由于属性是一个列表,因此删除的实体将被序列化为模型,然后被过滤掉。我想在数据库查询期间过滤掉它们。
    • 比maby存储过程对你有帮助吗?
    【解决方案3】:

    将实体映射到过滤掉已删除条目的 SQL 视图。

    【讨论】:

    • 这应该是领域模型的职责,而不是视图的职责。
    • 我指的是 SQL 视图,而不是 MVC 视图。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-29
    • 2016-05-29
    • 1970-01-01
    相关资源
    最近更新 更多