2014-02-05 63 views
0

我剛剛從代碼優先的場景中講解自己的實體框架(6)。我的問題是我不明白如何正確地指示EF可以在其他實體之間共享某些實體。如何在代碼優先的情況下共享EF6對象

這是一個非常簡單的三層樹狀結構。類A對象擁有一流B對象,擁有或引用,類C對象:

public class A 
{ 
    [Key] 
    public string Id { get; set; } 

    public ICollection<B> Bees { get; set; } 

    public override string ToString() { return Id; } 
} 

public class B 
{ 
    [Key] 
    public string Id { get; set; } 

    public ICollection<C> Cees { get; set; } 

    public override string ToString() { return Id; } 
} 

public class C 
{ 
    [Key] 
    public string Id { get; set; } 

    public override string ToString() { return Id; } 
} 

我現在創造一個單一的A對象擁有5個B對象,反過來,集合的場景五個C對象。這裏的的DbContext我用:

public class Context : DbContext 
{ 
    public DbSet<A> As { get; set; } 

    public DbSet<C> Cs { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     // SHOULD I INSTRUCT EF HOW TO HANDLE THIS HERE? 
     base.OnModelCreating(modelBuilder); 
    } 

    public Context(string nameOrConnectionString) 
     : base(nameOrConnectionString) 
    { 
    } 
} 

下面是一些簡單的代碼來設置此方案:

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     var context = new Context(@"Data Source=(localdb)\v11.0; Initial Catalog=TestEF6.Collections; Integrated Security=true"); 
     var sharedCees = createCees("A1.B1", 5, context); 
     context.As.Add(new A { Id = "A1", Bees = createBees("A1", 5, sharedCees) }); 
     context.SaveChanges(); 
    } 

    private static ICollection<B> createBees(string aId, int count, ICollection<C> cees = null) 
    { 
     var list = new List<B>(); 
     for (var i = 0; i < count; i++) 
     { 
      var id = aId + ".B" + (i + 1); 
      list.Add(new B { Id = id, Cees = cees ?? createCees(id, count) }); 
     } 
     return list; 
    } 

    private static ICollection<C> createCees(string bId, int count, Context saveInContext = null) 
    { 
     var list = new List<C>(); 
     for (var i = 0; i < count; i++) 
     { 
      var id = bId + ".C" + (i+1); 
      var c = new C {Id = id}; 
      list.Add(c); 
      if (saveInContext != null) 
       saveInContext.Cs.Add(c); 
     } 
     if (saveInContext != null) 
      saveInContext.SaveChanges(); 
     return list; 
    } 
} 

由於EF創建數據庫(「TestEF6.SharedEntities」),它假定A -> B,以及B -> C是一對多的關係,子實體是由其主實體完全擁有和控制的組件。

那麼,如何讓EF「看到」C的實例可以由B的實例共享?

誠實地說,我要求快速入門EF。我意識到我可以通過網絡挖掘並找出這一點,但如果任何人都可以指出我在正確的方向,我將非常感激。

乾杯

+1

你所描述的B和C之間的多到5月聯想當你說多BS可以具有相同的C也說C可以有多個基站。所以C應該有一個Bs和EF的集合,它們將通過數據庫中的聯結表BC進行建模。 –

+0

謝謝,格特。這使我確實走上了正確的軌道。請看我的下一個答案(我需要添加一些代碼)... –

回答

0

格特通過暗示我的集合屬性添加到C類設置跟蹤我。事實上,這足以讓EF/CF自動識別BC之間的多對多關係。但是,先用代碼優先考慮的一點是要設計一個類的領域模型,然後讓EF持久化它們,而不必通過持久性信息使其停滯不前。

我沒有註釋Key屬性,甚至Required的問題。這種信息在領域模型中確實有意義。它們可以被域代碼使用,但即使它們不是它們可以增加代碼的清晰度。但是,添加不具備其他功能的屬性,而不是其他功能,而不是EF的自動魔法提示,似乎不是一個非常優雅的解決方案。

所以我嘗試了更多流利的API,並意識到我錯過了.WithMany()的無參數超載。我正在尋找一種通用的形式,這將有可能指定其他類型的多對多關係。在我看來,我會寫:modelBuilder.Entity<B>.HasMany(b => b.Cees).WithMany<B>()。事實證明,WithMany()的無參數過載符合此確切目的,因爲在此方案中的類型C已由第一個HasMany()部分指定。

因此,要總結,EF將識別類BC之間的許多一對多的關係,而不需要「垃圾」的C CLAS與類型B項目額外的泛型集合。所以,這是我們如何描述兩個類之間的許多一對多relationsship,而不必在所有觸摸域類:

public class Context : DbContext 
{ 
    public DbSet<A> As { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<B>().HasMany(b => b.Cees).WithMany(); // <-- THE SOLUTION 
     base.OnModelCreating(modelBuilder); 
    } 

    public Context(string nameOrConnectionString) 
     : base(nameOrConnectionString) 
    { 
    } 
} 

我意識到這是很基本的東西,任何人經驗豐富的EF但我將繼續並將其標記爲答案,以便其他人可以在未來節省一些時間查找此信息。

感謝

相關問題