在 NHibernate 中,有一个 where
映射允许您在属性映射上指定一个条件,该条件会影响它从数据库中提取的方式。例如,如果我想实现软删除并从集合中排除所有已删除的项目,我可以这样映射它:
FluentNHibernate
// in class ParentMap : ClassMap
HasMany(x => x.Children).Where("IsDeleted = 0");
Hbm.xml
<class name="Parent" table="[Parents]">
<bag cascade="all" lazy="true" name="Children" where="IsDeleted = 0">
<!-- rest of map here -->
</bag>
</class>
Entity Framework 6 中有类似的东西吗?
我找到的最接近的是一个名为 EntityFramework.Filters 的库,它允许您为属性添加全局过滤器,但当该属性是一个集合时它似乎不起作用。
为了更好地说明为什么需要这样的映射,假设我有一个类,其中包含具有递归子实体关系的对象集合(即,相同类型的对象集合)。它们遵循以下基本结构:
public class ReportOutline
{
public long Id { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public virtual ICollection<OutlineItem> OutlineItems { get; set; }
}
public class OutlineItem
{
public long Id { get; set; }
public string Name { get; set; }
public long ReportOutlineId { get; set; }
public long? ParentOutlineItemId { get; set; }
public virtual ReportOutline ReportOutline { get; set; }
public virtual OutlineItem ParentOutlineItem { get; set; }
public virtual ICollection<OutlineItem> OutlineItems { get; set; }
}
这些是用 EF fluent API 映射的,如下所示:
modelBuilder.Entity<ReportOutline>()
.HasKey(o => o.Id)
.HasMany(o => o.OutlineItems)
.WithRequired(i => i.ReportOutline)
.HasForeignKey(i => i.OutlineId);
modelBuilder.Entity<OutlineItem>()
.HasKey(p => p.Id)
.HasMany(p => p.OutlineItems)
.WithOptional(c => c.ParentOutlineItem)
.HasForeignKey(c => c.ParentOutlineItemId);
这产生了正确的数据库结构,我的记录看起来很好。下面是 OutlineItems
表在 ReportOutline
上有两个项目的示例,如果一个表有两个子项目(总共四个):
Id Name ReportOutlineId ParentOutlineItemId
1 Introduction 1 NULL
2 Pets 1 NULL
3 Cats 1 2
4 Dogs 1 2
当 ReportOutline
通过 DbContext
加载时,但是,由于 ReportOutlineId
与大纲的 Id
匹配, ReportOutline.OutlineItems
正在填充所有四个项目。这导致子项出现在父项和主大纲本身的下方:
Title: My Report
Author: valverij
I. Introduction (Id: 1)
II. Pets (Id: 2)
A. Cats (Id: 3)
B. Dogs (Id: 4)
III. Cats (Id: 3) <--- Duplicated
IV. Dogs (Id: 4) <--- Duplicated
现在,如果我将 NHibernate 与 FluentNhibernate 一起使用,我可以在实体映射上指定一个 where
条件,这样 ReportOutline.OutlineItems
只有 拉取父项:
// in ReportOutlineMap
HasMany(x => x.OutlineItems).Where("ParentOutlineItemId IS NULL");
否则,我将不得不记住仅通过显式处理OutlineItem
集合的预写查询访问ReportOutline
对象.
最佳答案
您可以将“RootOutlineItems”属性添加到为您过滤的 ReportOutline 类,然后在您只需要第一级时调用它:
public class ReportOutline
{
public long Id { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public virtual ICollection<OutlineItem> OutlineItems { get; set; }
public ICollection<OutlineItem> RootOutlineItems {
get {
return OutlineItems.Where(p=> p.ParentOutlineItem == null);
}
}
}
另一种选择是使 OutlineItem 的 ReportOutline 可为空,并且只设置 ReportOutline 或 ParentOutlineItem 属性,但这有点不确定,而且如果您需要导航树永远想要所有的元素。
关于c# - 在 Entity Framework 6 中为子集合的映射添加条件,类似于 NHibernate 的 "where",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27324004/