[英]Conditional Mapping on Relationships
使用實體框架(代碼優先),我試圖映射以下兩個實體之間的條件/過濾關系:
建造
BuildingId
建築名稱
區域
areaID表示
的ParentId
AREANAME
IsSubArea
建築可以有很多區域
區域可以有許多(子) 區域
我想創建建築和區域之間的關系,其中標有'IsSubArea'的區域被過濾掉。 在此上下文中,ParentId將與Building相關 ,否則,ParentId將是另一個Area 。 這將允許我創建具有許多區域的建築物,並且每個區域可以具有許多子區域,從而創建樹形結構。
最接近我發現的解決方案與'軟刪除'功能( 源 )有關:
modelBuilder.Entity<Foo>().Map(m => m.Requires("IsDeleted").HasValue(false));
轉換為適合我的例子:
modelBuilder.Entity<Area>().Map(m => m.Requires("IsSubArea").HasValue(false));
但據我所知,這與建築物的關系無關。
另一種解決方案是在Building上創建一個屬性,該屬性指定用於返回相關區域的查詢定義( 源 ):
public class Building
{
public int BuildingId {get; set;}
public string BuildingName {get; set;}
public IQueryable<Area> BuildingAreas
{
get
{
return from area in areas
where area.IsSubArea == false
and area.ParentId == BuildingId
select area;
//Assume I have a reference to relevant DbSets
}
}
}
這個解決方案可以工作,但不像條件映射那樣優雅。
另一種解決方案是從Area繼承並創建2個子類:
BuildingArea
areaID表示
BuildingId
AREANAME
分區
areaID表示
ParentAreaId
AREANAME
每個都繼承自Area並根據需要設置'IsSubArea'字段。 這個解決方案感覺更整潔,但我不知道如何在Entity Framework中實現它。
有沒有辦法在關系上指定條件映射?
有沒有更好的方法來實現這種結構?
更新1 :找到這個和這個繼承的指南,似乎符合我的要求。 但是,這些教程都沒有定義派生類型之間的關系。 我將在今晚用關於每層結構表(TPH)方法嘗試的內容更新問題。
更新2 :
我將嘗試描述我嘗試基於上面的教程鏈接實現的每層次表(TPH)方法。 請原諒我,如果這有點復雜(也許我在想它)。
楷模
建築類與OP保持一致。
我創建了一個抽象基類,定義了每個派生類型(BuildingArea和SubArea)共有的Area屬性:
public abstract class Area
{
protected Area(bool isSubArea)
{
IsSubArea = isSubArea;
SubAreas = new List<SubArea>();
}
public int AreaId { get; set; }
public int ParentId { get; set; }
public string AreaName { get; set; }
public bool IsSubArea { get; private set; } //note the private set
public virtual ICollection<SubArea> SubAreas { get; set; }
}
然后我有2個派生類型繼承自Area :
public class BuildingArea : Area
{
public BuildingArea () : base(false)
{}
public virtual Building ParentBuilding { get; set; }
}
public class SubArea : Area
{
public SubArea(): base(true)
{}
// This is of type `Area` because parent could be either `BuildingArea` or `SubArea`
public virtual Area Parent { get; set; }
}
然后我有以下2個EntityTypeConfigurations:
public class BuildingAreaMap : EntityTypeConfiguration<BuildingArea>
{
public BuildingAreaMap ()
{
// Primary Key
HasKey(t => t.AreaId);
// Properties
Property(t => t.AreaName)
.IsRequired()
.HasMaxLength(256);
// Table & Column Mappings
ToTable("Areas");
Property(t => t.AreaId).HasColumnName("AreaId");
Property(t => t.ParentId).HasColumnName("ParentId");
Property(t => t.AreaName).HasColumnName("AreaName");
Property(t => t.IsSubArea).HasColumnName("IsSubArea");
// This is the discriminator column
Map(m => m.Requires("IsSubArea").HasValue(false));
HasRequired(a => a.Site).WithMany(s => s.SiteAreas).HasForeignKey(k => k.ParentId);
}
public class SubAreaMap : EntityTypeConfiguration<SubArea>
{
public SubAreaMap()
{
// Primary Key
HasKey(t => t.AreaId);
// Properties
Property(t => t.AreaName)
.IsRequired()
.HasMaxLength(256);
// Table & Column Mappings
ToTable("AssetHealthAreas");
Property(t => t.AreaId).HasColumnName("AreaId");
Property(t => t.ParentId).HasColumnName("ParentId");
Property(t => t.AreaName).HasColumnName("AreaName");
Property(t => t.IsSubArea).HasColumnName("IsSubArea");
// This is the discriminator column
Map(m => m.Requires("IsSubArea").HasValue(true));
HasRequired(a => a.Parent).WithMany(s => s.SubAreas).HasForeignKey(k => k.ParentId);
}
}
此代碼構建成功,但我收到以下運行時錯誤:
Map was called more than once for type 'SiteArea' and at least one of the calls didn't specify the target table name.
但我正在指定目標表名稱(每個EntityTypeConfiguration類中一次)。 所以我刪除了SubArea
的EntityTypeConfiguration但是我得到了同樣的錯誤。
其中一個教程將映射拉出EntityTypeConfiguration類,並將其放入OnModelCreating
處理程序中,如下所示:
modelBuilder.Entity<Area>()
.Map<BuildingArea>(m => m.Requires("IsSubArea").HasValue(false))
.Map<SubArea>(m => m.Requires("IsSubArea").HasValue(true));
這也給了我同樣的錯誤。
如果我從等式中刪除關系,我會得到關於ParentId
屬性的不同錯誤:
The foreign key component 'ParentId' is not a declared property on type 'SiteArea'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property.
更新3
我試圖創建的模型的圖像......
更新4
我將嘗試簡化我的模型以匹配以下內容。 如果下面的解決方案有效,我將需要更多的業務邏輯來導航樹,但它應該是可管理的。
對於創建TPH類時的錯誤:我認為這是因為您不應該將鑒別器列作為類中的屬性。
從基類中刪除屬性IsSubArea。
創建新實例時,EF應自動檢測類型並相應地填充IsSubArea。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.