简体   繁体   English

实体框架多对多关系表创建“向后”

[英]Entity framework many-to-many relation table created “backwards”

I'm having an issue with EF6 and many-to-many relations. 我遇到了EF6和多对多关系的问题。 I have a following setup: 我有以下设置:

public class Foo
{
    public int Id { get; set; }
    public virtual ICollection<Bar> Bars { get; set; }
    public virtual ICollection<SubBar> SubBars { get; set; }

    public Foo()
    {
        Bars = new HashSet<Bar>();
        SubBars = new HashSet<SubBar>();
    }
}

public class Bar
{
    public int Id { get; set; }
    public virtual ICollection<Foo> Foos { get; set; }

    public Bar()
    {
        Foos = new HashSet<Foo>();
    }
}

public class SubBar
{
    public int Id { get; set; }
    public virtual ICollection<Foo> Foos { get; set; }

    public SubBar()
    {
        Foos = new HashSet<Foo>();
    }
}

The relation between Foo and Bar works properly, and there is a table called BarFoos in the DB. FooBar之间的关系正常工作,DB中有一个名为BarFoos的表。 However the relation between Foo and SubBar is reversed. 然而, FooSubBar之间的关系是相反的。 There is a table in the DB called FooSubBars which basically holds the correct relations, but eager loading, like SubBar.AsQueryable().Include(sb => sb.Foos) returns an EntityCommandExecutionException with a message Invalid object name dbo.SubBarFoos . 数据库中有一个名为FooSubBars的表,它基本上保持正确的关系,但是像SubBar.AsQueryable().Include(sb => sb.Foos)一样急切加载SubBar.AsQueryable().Include(sb => sb.Foos)返回一个EntityCommandExecutionException其中包含一个消息Invalid object name dbo.SubBarFoos

Question is: How do I reverse the relation table name to allow eager loading? 问题是:如何反转关系表名称以允许急切加载?
--Edit-- - 编辑 -
DB creation in the migration is as follows: 迁移中的数据库创建如下:

CreateTable(
            "dbo.BarFoos",
            c => new
                {
                    Bar_Id = c.Int(nullable: false),
                    Foo_Id = c.Int(nullable: false),
                })
            .PrimaryKey(t => new { t.Bar_Id, t.Foo_Id })
            .ForeignKey("dbo.Bars", t => t.Bar_Id, cascadeDelete: true)
            .ForeignKey("dbo.Foos", t => t.Foo_Id, cascadeDelete: true)
            .Index(t => t.Bar_Id)
            .Index(t => t.Foo_Id);

CreateTable(
            "dbo.FooSubBars",
            c => new
                {
                    Foo_Id = c.Int(nullable: false),
                    SubBar_Id = c.Int(nullable: false),
                })
            .PrimaryKey(t => new { t.Foo_Id, t.SubBar_Id })
            .ForeignKey("dbo.Foos", t => t.Foo_Id, cascadeDelete: true)
            .ForeignKey("dbo.SubBars", t => t.SubBar_Id, cascadeDelete: true)
            .Index(t => t.Foo_Id)
            .Index(t => t.SubBar_Id);

Would replacing the table name in the migration be sufficient? 在迁移中替换表名是否足够?

You can ensure the table name is generated as "FooBars" if you override the OnModelCreating method on your DbContext as follows: 如果您在DbContext上覆盖OnModelCreating方法,则可以确保将表名生成为“FooBars”,如下所示:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<Foo>().HasMany(f => f.Bars).WithMany(b => b.Foos)
            .Map(m => 
                m.ToTable("FooBars")
                // Optionally specify the key column names...
                .MapLeftKey("FooId") 
                .MapRightKey("BarId")
            );

    modelBuilder.Entity<Foo>().HasMany(f => f.SubBars).WithMany(sb => sb.Foos).Map(m => m.ToTable("FooSubBars"));
}

Which will produce this in the migration: 这将在迁移中产生这种情况:

        CreateTable(
            "dbo.FooBar",
            c => new
                {
                    FooId = c.Int(nullable: false),
                    BarId = c.Int(nullable: false),
                })
            .PrimaryKey(t => new { t.FooId, t.BarId })
            .ForeignKey("dbo.Foos", t => t.FooId, cascadeDelete: true)
            .ForeignKey("dbo.Bars", t => t.BarId, cascadeDelete: true)
            .Index(t => t.FooId)
            .Index(t => t.BarId);

        CreateTable(
            "dbo.FooSubBar",
            c => new
                {
                    Foo_Id = c.Int(nullable: false),
                    SubBar_Id = c.Int(nullable: false),
                })
            .PrimaryKey(t => new { t.Foo_Id, t.SubBar_Id })
            .ForeignKey("dbo.Foos", t => t.Foo_Id, cascadeDelete: true)
            .ForeignKey("dbo.SubBars", t => t.SubBar_Id, cascadeDelete: true)
            .Index(t => t.Foo_Id)
            .Index(t => t.SubBar_Id);

I also tried eager loading the Foos when querying SubBars on the DbContext with don't get any errors: 我也尝试在DbContext上查询SubBars时急切加载Foos,不要出现任何错误:

var context = new FooBarContext();

var subBars = from sb in context.SubBars.Include(i => i.Foos)
              select sb;

I was able to reverse the naming by checking here 我可以通过在这里查看来反转命名

https://msdn.microsoft.com/en-us/library/jj591620(v=vs.113).aspx https://msdn.microsoft.com/en-us/library/jj591620(v=vs.113).aspx

So long as both Entity1 and Entity2 have navagational properties to eachother, then the following works. 只要Entity1和Entity2都具有彼此的导航属性,那么以下工作。

            modelBuilder.Entity<Order>()
                .HasMany(t => t.Products)
                .WithMany(t => t.Orders);

which produces 哪个产生

            CreateTable(
            "dbo.OrderProducts",
            c => new
                {
                    Order_OrderID = c.Int(nullable: false),
                    Product_ID = c.Int(nullable: false),
                })
            .PrimaryKey(t => new { t.Order_OrderID, t.Product_ID })
            .ForeignKey("dbo.Orders", t => t.Order_OrderID, cascadeDelete: true)
            .ForeignKey("dbo.Products", t => t.Product_ID, cascadeDelete: true)
            .Index(t => t.Order_OrderID)
            .Index(t => t.Product_ID);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM