簡體   English   中英

關系的條件映射

[英]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

我試圖創建的模型的圖像......

ERD

更新4

我將嘗試簡化我的模型以匹配以下內容。 如果下面的解決方案有效,我將需要更多的業務邏輯來導航樹,但它應該是可管理的。

ERD2

對於創建TPH類時的錯誤:我認為這是因為您不應該將鑒別器列作為類中的屬性。

從基類中刪除屬性IsSubArea。

創建新實例時,EF應自動檢測類型並相應地填充IsSubArea。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM