Entity framework 多对多关系 table 已创建 "backwards"
Entity framework many-to-many relation table created "backwards"
我遇到了 EF6 和多对多关系的问题。我有以下设置:
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>();
}
}
Foo
和Bar
之间的关系正常,数据库中有一个名为BarFoos
的table。然而 Foo
和 SubBar
之间的关系是相反的。数据库中有一个名为 FooSubBars
的 table,它基本上保持正确的关系,但急切加载,例如 SubBar.AsQueryable().Include(sb => sb.Foos)
returns 一个 EntityCommandExecutionException
带有一条消息 Invalid object name dbo.SubBarFoos
.
问题是:如何反转关系 table 名称以允许提前加载?
--编辑--
迁移中创建DB如下:
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);
替换迁移中的 table 名称是否足够?
如果您重写 DbContext 上的 OnModelCreating 方法,则可以确保 table 名称生成为 "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"));
}
这将在迁移中产生:
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);
我还尝试在 DbContext 上查询 SubBars 时预先加载 Foos,但没有收到任何错误:
var context = new FooBarContext();
var subBars = from sb in context.SubBars.Include(i => i.Foos)
select sb;
我可以通过检查这里来反转命名
https://msdn.microsoft.com/en-us/library/jj591620(v=vs.113).aspx
只要 Entity1 和 Entity2 都具有彼此的导航属性,那么下面的工作就可以了。
modelBuilder.Entity<Order>()
.HasMany(t => t.Products)
.WithMany(t => t.Orders);
产生
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);
我遇到了 EF6 和多对多关系的问题。我有以下设置:
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>();
}
}
Foo
和Bar
之间的关系正常,数据库中有一个名为BarFoos
的table。然而 Foo
和 SubBar
之间的关系是相反的。数据库中有一个名为 FooSubBars
的 table,它基本上保持正确的关系,但急切加载,例如 SubBar.AsQueryable().Include(sb => sb.Foos)
returns 一个 EntityCommandExecutionException
带有一条消息 Invalid object name dbo.SubBarFoos
.
问题是:如何反转关系 table 名称以允许提前加载?
--编辑--
迁移中创建DB如下:
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);
替换迁移中的 table 名称是否足够?
如果您重写 DbContext 上的 OnModelCreating 方法,则可以确保 table 名称生成为 "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"));
}
这将在迁移中产生:
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);
我还尝试在 DbContext 上查询 SubBars 时预先加载 Foos,但没有收到任何错误:
var context = new FooBarContext();
var subBars = from sb in context.SubBars.Include(i => i.Foos)
select sb;
我可以通过检查这里来反转命名
https://msdn.microsoft.com/en-us/library/jj591620(v=vs.113).aspx
只要 Entity1 和 Entity2 都具有彼此的导航属性,那么下面的工作就可以了。
modelBuilder.Entity<Order>()
.HasMany(t => t.Products)
.WithMany(t => t.Orders);
产生
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);