public partial class MyDbContext : DbContext
{
public MyDbContext()
: base("name=Model1")
{
}
public virtual DbSet<User> Users { get; set; }
public virtual DbSet<UserGroup> UserGroups { get; set; }
public virtual DbSet<UserGroupMember> UserGroupMembers { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) { }
}
[Table("gnr.UserGroup")]
public partial class UserGroup
{
public UserGroup()
{
ChildUserGroups = new HashSet<UserGroupMember>();
UserGroupMembers = new HashSet<UserGroupMember>();
}
public long ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
[InverseProperty("ChildUserGroup")]
public virtual ICollection<UserGroupMember> ChildUserGroupMembers { get; set; }
[InverseProperty("UserGroup")]
public virtual ICollection<UserGroupMember> UserGroupMembers { get; set; }
}
[Table("gnr.UserGroupMember")]
public partial class UserGroupMember
{
public long ID { get; set; }
public long? UserID { get; set; }
public virtual User User { get; set; }
[ForeignKey("UserGroup")]
public long UserGroupID { get; set; }
public virtual UserGroup UserGroup { get; set; }
[ForeignKey("ChildUserGroup")]
public long? ChildUserGroupID { get; set; }
public virtual UserGroup ChildUserGroup { get; set; }
}
[Table("gnr.User")]
public partial class User
{
public User()
{
UserGroupMembers = new HashSet<UserGroupMember>();
}
public long ID { get; set; }
public string Username { get; set; }
public string MobileNumber { get; set; }
public virtual ICollection<UserGroupMember> UserGroupMembers { get; set; }
}
static void Main(string[] args)
{
WorkNotCorrectly();
Console.WriteLine("Done");
Console.ReadLine();
}
private static void WorkNotCorrectly()
{
using (var db = new MyDbContext())
{
var ug = new UserGroup { Title = "It's a new UserGroup 1" };
var cugm = new UserGroupMember { ChildUserGroupID = 1 };
ug.ChildUserGroupMembers.Add(cugm);
// After This Line
db.UserGroups.Add(ug);
MyDbContext设置&#39; ChildUserGroup&#39; &#39; cugm&#39;的财产反对&#39; ug&#39;
但预期的行为是设置&#39; UserGroup&#39; &#39; cugm&#39;的财产反对&#39; ug&#39;
&#39;微克&#39;对象Json:
{
"ID": 0,
"Title": "It's a new UserGroup 1",
"Description": null,
"ChildUserGroupMembers": [
{
"ID": 0,
"UserID": null,
"User": null,
"UserGroupID": 0,
"UserGroup": null,
"ChildUserGroup": HERE IS THE PROBLEM => The MyDbContext sets the 'ChildUserGroup' property instead of 'UserGroup' property,
"ChildUserGroupID": 1
}
],
"UserGroupMembers": []
}
SaveChanges:
db.SaveChanges();
}
}
&#39;微克&#39;对象到SaveChanges之后的Json:
{
"ID": 2,
"Title": "It's a new UserGroup 1",
"Description": null,
"ChildUserGroupMembers": [
{
"ID": 1,
"UserID": null,
"User": null,
"UserGroupID": 2,
"ChildUserGroupID": 2 WHAT???? IT IS CHANGED TO 2 ( THE NEW UserGroup THAT IS GENERATED),
"ChildUserGroup": HERE IS THE PROBLEM => The MyDbContext sets the 'ChildUserGroup' property instead of 'UserGroup' property
}
],
????? WHAT IS THIS??? WHY UserGroupMembers PROPERTY IS FILLED
"UserGroupMembers": [
{
"ID": 1,
"UserID": null,
"User": null,
"UserGroupID": 2,
"ChildUserGroupID": 2
}
]
}
预期的行为和结果是:
{
"ID": 2,
"Title": "It's a new UserGroup 1",
"Description": null,
"ChildUserGroupMembers": [
{
"ID": 1,
"UserID": null,
"User": null,
"UserGroupID": 2,
"UserGroup": 'The ug object with ID of 2 ',
"ChildUserGroupID": 1
}
]
}
Result in SSMS and the relationship diagram
似乎EF混淆了识别正确的FK,插入物体后必须自己填充的那个和我填充的那个?? !!
更新 这是实体之间的关系:
UserGroupMember是UserGroup和User
每个用户都可以是1 ... * UserGroup
每个UserGroup可以有1 ... * User as member
(直到这里它像一个普通的桥表来表示多对多的关系)
4. 每个UserGroup可以有1 ... * ChildUserGroup作为成员
(这意味着UserGroup可以将User或ChildUserGroup作为成员,例如“Windows的用户和组”)
此致。
答案 0 :(得分:0)
这里的主要问题是,您的代码设置的导航属性不如您期望的那样。
首先,您使用InverseProperty
属性来定义您的关系。
UserGroup.ChildUserGroupMembers
&amp; UserGroupMember.ChildUserGroup
与外键属性ChildUserGroupID
UserGroup.UserGroupMembers
&amp; UserGroupMember.UserGroup
与外键属性UserGroupID
在EF中定义关系时,有3个组件,主要依赖于导航,依赖于主导航&amp;外国财产。设定其中任何一个的价值也会决定其他人。如果设置任何导航,则外键属性将设置为与主键属性具有相同的值。如果导航已经加载到内存中,也会填充导航。
当SSMS输出显示时,您的UserGroup表中已有ID = 1的数据。 现在在你的代码中,
UserGroup
ug
。UserGroupMember
cugm
。cugm.ChildUserGroupID
= 1的值。实体具有cugm.ChildUserGroup
导航(与ChildUserGroupID
fk相关联)的关系应该具有UserGroup
ID = 1分配给它。由于它未加载到内存中,因此该导航将保持为空。同样,如果内存中加载ID = 1的UserGroup
,则UserGroup.ChildUserGroupMembers
集合会向其添加cugm
。cugm
添加到ug.ChildUserGroupMembers
集合中。这意味着FK属性cugm.ChildUserGroupID
应该取ug.ID
的值。反向导航的cugm.ChildUserGroup
应指向ug
。从那时起EF不在图片中,在添加实体之前不会发生上述变化。ug
添加到UserGroups
数据库集,以便EF开始跟踪实体及其子项。由于ug.ChildUserGroupMembers
集合中添加了cugm
,因此EF会将cugm.ChildUserGroup
设置为ug
。 ug
对象仍有临时密钥,因此EF不会将ug.ID
复制到cugm.ChildUserGroupID
这就是你获得第一个JSON的方式。它已设置ChildUserGroup
,因为您设置了它的反向导航。
致电SaveChanges后,
EF会将实体ug
保存到数据库。由于您的数据库已经具有ID = 1的实体,因此它获得的下一个ID为2.由于ug.ID
不再是临时值,cugm.ChildUserGroupID
将获取其值并更改为2
。< / p>
现在根据您的SSMS数据,
你想要创建新的UserGroup
对象 - ug
,保存后会得到ID = 2。您想要创建新的UserGroupMember
对象 - cugm
,它将获得ID = 1(带有标识列的第一行。)cugm.UserGroupId
= 2因此cugm.UserGroup
导航应设置为{ {1}}&amp; ug
= 1。
这就是代码应该是什么样的
cugm.ChildUserGroupID
上面的代码将在您的数据库中生成您想要的精确记录。
var ug = new UserGroup { Title = "It's a new UserGroup 1" };
var cugm = new UserGroupMember { ChildUserGroupID = 1 };
ug.UserGroupMembers.Add(cugm); // You want to set UserGroupID = 2 so cugm should be added to its corresponding inverse navigation
db.UserGroups.Add(ug);
db.SaveChanges();
对象的JSON输出如下(在你的问题中也是不正确的)
ug