2017-09-19 30 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"); 
      }); 
    } 
相关问题