更新多对多关系既不是完全代码也不是数据库

时间:2017-09-19 20:27:34

标签: entity-framework asp.net-mvc-4 ef-database-first

我似乎在努力完成命名惯例和理解的结合。

我继承了一个数据库,正在构建一个MVC站点,我无法让“数据库优先”工作流程很好地发挥作用。最后,我手动构建了我的上下文类,并且一直在愉快地工作。

我现在处于这样一种情况:我无法添加与其他几个现有实体(多对多)有关系的实体。

我的数据库看起来(简化了这个问题),如下所示:

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

我的上下文包含一个允许我获取所有ListItem的属性:

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

如果我使用一些LINQ,我会执行以下操作,并返回项目,并且满足多对多关系,并在Option中获得ListItem列表:

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

实际上,我必须手动构建数据库中的交叉引用表,这是我在尝试运行上述查询时所做的,而我告诉我的例外情况我没有名为dbo.OptionListItems的对象。所以我认为我们都很好。

现在我需要创建一个新的ListItem并将其链接到一个或多个现有的 Option,我不知所措。

一旦我单独创建了新的ListItem,并尝试调用listItem.Options.Add(...)它失败了,但如果我尝试获取对特定{{{}的引用,我也会得到完全相同的异常。 1}}并尝试Option

这个错误很有趣,与我的名字相反:

option.ListItems.Add(...)

我怀疑在我的上下文中构建一个类型和一个属性以直接访问交叉引用表是违反EF的一小部分:

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

但我对于建立新关系的模式感到困惑。

2 个答案:

答案 0 :(得分: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;}
}

这应该以声明方式创建完整的关系

答案 1 :(得分:0)

感谢史蒂夫格林指出我正确的方向。 我所拥有的表是按惯例创建的,当我用WorkItem查询.Include(p => p.Options)时工作,但是如果您尝试进行更新,则约定似乎会中断。我不确定为什么,但在查询时,映射表的构造似乎是<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");
            });
    }