实体框架对导航属性的约束

时间:2012-07-19 20:18:00

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

我想限制由导航属性返回的模型。例如,我使用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中删除未删除的注释(Comment.AuditInfo.Deleted为NULL)?

3 个答案:

答案 0 :(得分:5)

(我假设您使用的是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
    {
    }
    

    您无法在此处应用过滤器。延迟加载将始终加载给定博客帖子的所有评论。

  • 渴望加载:

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

    您无法在Include中应用过滤器。急切加载将始终加载给定博客帖子的所有评论。

  • 明确加载:

    加载父级:

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

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

    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();
    

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

答案 1 :(得分:1)

maby将自定义属性添加到实体类,它将使用导航属性但过滤它并返回过滤后的数据?

答案 2 :(得分:0)

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