我首先在ASP.NET Web API中使用EF6代码。
假设有两个模型类
public class RawMaterial {
public int ID { get; set; }
public string Name { get; set; }
}
public class Furniture {
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<RawMaterial> RawMaterials { get; set; }
}
的DbContext
public class FurnitureContext : DbContext {
public DbSet<RawMaterial> RawMaterials { get; set; }
public DbSet<Furniture> Furnitures { get; set; }
}
在初始化类中,
protected override void Seed (FurnitureContext context) {
var glass = new RawMaterial { Name = "glass" };
var wood = new RawMaterial { Name = "wood" };
var paint = new RawMaterial { Name = "paint" };
context.RawMaterials.AddRange(new RawMaterial[] { glass, wood, paint });
var chair = new Furniture {
Name = "chair",
RawMaterials = new RawMaterial[] { wood, paint }
};
var coffeeTable = new Furniture {
Name = "coffee table",
RawMaterials = new RawMaterial[] { wood, glass }
};
context.Furnitures.AddRange(new Furnitures[] { chair, coffeeTable });
context.SaveChanges();
}
我遇到了运行时错误抱怨“无法从固定大小的数组中删除某个项目”。很明显,该程序试图在将木材添加到coffeeTable之前从椅子上移除木材。所以我将初始化更改为使用Lists,如
var chair = new Furniture {
Name = "chair",
RawMaterials = new List<RawMaterial> { wood, paint }
};
在那之后,我可以清楚地看到木材确实是从家具的RawMaterials中移除的。
我也尝试通过
从上下文中选择木材var chair = new Furniture {
Name = "chair",
RawMaterials = new RawMaterial[] {
context.RawMaterials.Where(r => r.Name == wood.Name).FirstOrDefault()
}
};
结果仍然相同。
所以我的问题是:我如何添加测试数据,以便木材和咖啡桌上都有木材?我知道这通常不是多少对多关系的定义,因为RawMaterial不知道家具。或者我应该用另一种方式定义模型?
谢谢。
编辑: 我检查SQL Server对象资源管理器中的数据库表,而RawMaterial的SQL是
CREATE TABLE [dbo].[RawMaterials] (
[ID] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (MAX) NULL,
[Furniture_ID] INT NULL,
CONSTRAINT [PK_dbo.RawMaterials] PRIMARY KEY CLUSTERED ([ID] ASC),
CONSTRAINT [FK_dbo.RawMaterials_dbo.Furnitures_Furniture_ID] FOREIGN KEY ([Furniture_ID]) REFERENCES [dbo].[Furnitures] ([ID])
);
GO
CREATE NONCLUSTERED INDEX [IX_Furniture_ID]
ON [dbo].[RawMaterials]([Furniture_ID] ASC);
家具的SQL是
CREATE TABLE [dbo].[Furnitures] (
[ID] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (MAX) NULL,
CONSTRAINT [PK_dbo.Furnitures] PRIMARY KEY CLUSTERED ([ID] ASC)
);
所以基本上实体框架并不是按照我需要的方式创建数据库。这就是为什么我不能在椅子和咖啡桌上添加木材的原因。我该如何修改实体模型?
答案 0 :(得分:1)
我非常专注于您报告的错误,我忘了查看映射。但是,一旦我这样做,它突然变得简单。正确指出它是一个多对多关联,但它没有像一个那样映射。这是您正确映射的方式:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Furniture>()
.HasMany(f => f.RawMaterials)
.WithMany()
.Map(m => m.MapLeftKey("FurnitureId")
.MapRightKey("RawMaterialId")
.ToTable("FurnitureRawMaterial"));
}
这会创建一个连接两个实体的联结表FurnitureRawMaterial
。
我仍然觉得奇怪的是,我可以在没有得到异常的情况下运行你的代码(并且没有得到第二个&#34; wood&#34;我后来注意到的关联)。我想知道它是否是.Net 4.5.2问题。
答案 1 :(得分:0)
根据您的描述,Furniture和RawMaterial之间的关系看起来像很多对很多而不是一对多。一个家具可以有许多原材料,同时原材料可以属于多个家具。
无论如何,回到你的问题,展示&#39; wood&#39;两次,将Seed方法更改为:
var chair = new Furniture
{
Name = "chair",
RawMaterials = new List<RawMaterial>
{
new RawMaterial {
Name = "paint",
FurnitureId = 1
},
new RawMaterial {
Name = "wood",
FurnitureId = 1
},
}
};
var coffeeTable = new Furniture
{
Name = "coffee table",
RawMaterials = new List<RawMaterial>
{
new RawMaterial {
Name = "glass",
FurnitureId = 2
},
new RawMaterial {
Name = "wood",
FurnitureId = 2
},
}
};
context.Furnitures.AddRange(new Furniture[] { chair, coffeeTable });
context.SaveChanges();
不管这样做,它会显示重复的名称&#34; wood&#34;,在您的MAterial表中显示不同的ID