下面是我的模型:
public class TMUrl
{
//many other properties
//only property with type Keyword
public List<Keyword> Keywords{get;set;}
}
public class Keyword
{
//many other properties
//only property with type TMUrl
public List<TMUrl> Urls{get;set;}
}
所以很明显,无论是实体有许多一对多的关系。 我选择了流畅的API来讲述这个关系即实体框架
modelBuilder.Entity<TMUrl>
.HasMany(s => s.Keywords)
.WithMany(s => s.URLs).Map(s =>
{
s.MapLeftKey("KeywordId");
s.MapRightKey("UrlId");
s.ToTable("KeywordUrlMapping");
});
但是当我做
url.Keywords.Add(dbKey); //where url is object of TMUrl,
//dbKey is an existing/new object of Keyword
db.SaveChanges();
我得到异常
An error occurred while saving entities that do not expose foreign key
properties for their relationships....
的InnerException:
The INSERT statement conflicted with the FOREIGN KEY constraint
"KeywordMaster_Keyword". The conflict occurred in database "DbName",
table "dbo.KeywordMaster", column 'Id'.The statement has been terminated.
但是当我从阿瑟赛德藏汉添加配置,一切工作正常。 即
modelBuilder.Entity<KeyWord>
.HasMany(s => s.URLs)
.WithMany(s => s.Keywords)
.Map(s =>
{
s.MapLeftKey("KeywordId");
s.MapRightKey("UrlId");
s.ToTable("KeywordUrlMapping");
});
为什么?。 为什么我已经从两个实体,在那里我读过添加配置在这里和其他许多地方,配置实体应该做的一个。
什么情况下,我应该都关系中所涉及的实体添加配置?
我需要了解这一点。 为什么。 请帮忙。
术语Left
和Right
的MapLeftKey
和MapRightKey
在许多一对多映射用流利的API可能被误解,我想你的问题是由这种误解造成的。
有人可能会认为,这意味着他们描述的“左”,在许多一对多连接表“正确”的列。 这实际上的情况下,如果你让EF代码首先创建数据库和连接表根据您的流利的映射。
但是,当你创建一个映射到一个现有的数据库,它并不一定如此。
要使用的原型许多一对多的例子来说明这个User
- Role
模型假设你有一个现有的数据库Users
, Roles
和RoleUsers
表:
现在,要映射这个表架构以一个简单的模型:
public class User
{
public User()
{
Roles = new List<Role>();
}
public int UserId { get; set; }
public string UserName { get; set; }
public ICollection<Role> Roles { get; set; }
}
public class Role
{
public int RoleId { get; set; }
public string RoleName { get; set; }
}
而你添加对的流利映射Users
实体(你必须做这种方式,因为按照惯例,上述模型是一个一对多的,你不能从一开始Role
的实体侧,因为它没有Users
集合):
modelBuilder.Entity<User>()
.HasMany(u => u.Roles)
.WithMany()
.Map(m =>
{
m.MapLeftKey("RoleId"); // because it is the "left" column, isn't it?
m.MapRightKey("UserId"); // because it is the "right" column, isn't it?
m.ToTable("RoleUsers");
});
这种映射是错误的,如果你试图把“安娜”到角色“营销” ......
var anna = ctx.Users.Find(1);
var marketing = ctx.Roles.Find(2);
anna.Roles.Add(marketing);
ctx.SaveChanges();
... SaveChanges
将抛出正是你所具有的异常。 当你捕获与发送SQL命令的原因变得清晰SaveChanges
:
exec sp_executesql N'insert [dbo].[RoleUsers]([RoleId], [UserId])
values (@0, @1)
',N'@0 int,@1 int',@0=1,@1=2
因此,EF想在这里插入一行到连接表RoleUsers
与RoleId
的1
和UserId
的2
这是造成违反外键约束,因为有没有用户UserId
2
的Users
表。
换言之,上述的映射已配置的列RoleId
作为外键表Users
和列UserId
作为外键表Roles
。 为了纠正我们在连接表中的使用“左”列名的映射MapRightKey
和“右”列MapLeftKey
:
m.MapLeftKey("UserId");
m.MapRightKey("RoleId");
其实在看智能感知的描述使得它更清楚什么是“左”和“右”的真正含义:
MapLeftKey
配置列(个),左外键的名称。 左外键代表的的hasMany调用指定的导航属性。
MapRightKey
配置列(个),右外键的名称。 右外键代表在WithMany调用指定的导航属性。
所以,“左”和“右”指的是其中的实体出现在流利的映射的顺序,不要在连接表中的列顺序。 在表中的顺序其实没关系,你可以改变它不会破坏任何东西,因为INSERT
通过EF发送是一种“扩展” INSERT
还包含列名称而不是只值。
也许MapFirstEntityKey
和MapSecondEntityKey
本来这些方法名的少误导性的选择-或者MapSourceEntityKey
和MapTargetEntityKey
。
这是一个很长的帖子约两个单词。
如果我的猜测是正确的,那有什么用你的问题都没有,那么我会说,你的第一个映射是不正确的,你只需要在第二和正确的映射。
文章来源: How to define Many-to-Many relationship through Fluent API Entity Framework?