2017-09-19 22 views
1

我似乎正在努力結合使用命名約定和理解。更新一個多對多的關係既不完全代碼也不是數據庫優先

我已經繼承了一個數據庫,並且正在構建一個MVC網站,我無法讓「數據庫優先」工作流程很好地發揮作用。最後,我手動構建了我的上下文類,並且一直在愉快地工作。

我現在處於一種情況,我無法添加一個實體與幾個其他現有實體(多對多)的關係。

我的數據庫的外觀(簡化了這個問題),像這樣:

ListItem  Option  OptionListItems 
======  ======  =============== 
Id   Id   ListItem_Id 
Name   Name   Option_Id 

我的上下文包含的屬性,讓我把所有我listItems中的:

public virtual DbSet<ListItem> ListItems { get; set; } 

如果我使用一些LINQ,我做了類似以下內容的項目並返回並滿足多對多關係,並在ListItem內獲得Option的列表:

var item = _context.ListItems 
.Where(p => p.Id == id) 
.Include(p => p.Options) 
.SingleOrDefault(); 

事實上,我不得不手動構建數據庫中的交叉引用表,我嘗試運行上述查詢時發生的異常以及例外情況我告訴我,我沒有名爲dbo.OptionListItems的對象。所以我認爲我們都很好。

現在我需要創建一個新的ListItem並將其鏈接到一個或多個現有的Option而我不知所措。

一旦我已經建立了我孤立新ListItem,並試圖調用listItem.Options.Add(...)失敗了,但我也得到完全相同的異常,如果我嘗試得到一個特定的Option參考,並嘗試做option.ListItems.Add(...)

的錯誤是一種有趣的是相反的表名我有什麼:

{"Invalid object name 'dbo.ListItemOptions'."} 

我懷疑它違背了EF的糧食的基礎上我的上下文的類型和屬性直接訪問這樣的交叉參考表:

public virtual DbSet<OptionListItem> OptionListItems { get; set; } 

但我完全被模式創建新的關係困惑。

+0

不知道你如何撕毀了DB頭的東西,但在代碼首先,如果你需要控制多到很多,你需要流利的地圖類似的代碼[這裏](HTTP://www.entityframeworktutorial .net/code-first/configure-many-to-many-relationship-in-code-first.aspx)(接近底部)。 –

+0

是的,這是一個奇怪的情況。我有一個數據庫和一些手動創建的POCO,所以最重要的是我已經手動添加了兩個位,而不是依靠腳手架或遷移。 在我嘗試創建映射之前(我看過那篇文章,但並不確定這是最好的方法),那麼使用什麼樣的明智模式?我是否正確地將我的'ListItem'和'.Add'ing加入到選項集合中 - 並且因此應該使用它的映射? – Neil

回答

0

我們有這個(多對多)聲明式工作。僞代碼:

public class ListItem 
{ 

    public ListItem() 
    { 
     this.RelatedOptions = new HashSet<OptionListItems>(); 
    } 

    [Key] 
    public int Id {get; set;} 
    public string Name {get; set;} 
    public virtual ICollection<OptionListItems> RelatedOptions {get; set;} 
} 

public class Option 
{ 
    public Ortion() 
    { 
     this.RelatedItems = new HashSet<OptionListItems>(); 
    } 

    [Key] 
    public int Id {get; set;} 
    public string Name {get; set;} 
    public virtual ICollection<OptionListItems> RelatedItems {get; set;} 
} 


public class OptionListItems 
{ 
    [Key] 
    public int Id {get; set;} 

    [Column("ListItemId", Order = 1)] 
    [ForeignKey("ParentListItem")] 
    public int ListItemId {get; set;} 

    [Column("OptionId", Order = 2)] 
    [ForeignKey("ParentOption")] 
    public int OptionId {get; set;} 

    public virtual ListItem ParentListItem {get; set;} 
    public virtual Option ParentOption {get; set;} 
} 

這應該創建一個完整的關係聲明

+0

謝謝 - 我已經有了一個非常相似的模型,但這篇文章至少幫助我驗證了它。 – Neil

0

幸得史蒂夫格林指着我在正確的方向。 我有的表是按照慣例創建的,當我用.Include(p => p.Options)查詢WorkItem時工作正常,但是如果您嘗試進行更新,約定似乎會失效。我不確定爲什麼,但查詢時映射表的構建似乎爲<Entity1>+<Entity2>+s,但更新時爲<Entity2>+<Entity1>+s ...

好消息,通過使用fluentAPI,我創建了實體之間的特定映射並強​​制交叉引用表以及查詢和更新作品!

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<ListItem>() 
      .HasMany<Option>(s => s.Options) 
      .WithMany(c => c.ListItems) 
      .Map(cs => 
      { 
       cs.MapLeftKey("ListItem_Id"); 
       cs.MapRightKey("Option_Id"); 
       cs.ToTable("OptionListItems"); 
      }); 
    } 
相關問題