通过实体框架保存收益回报中的更改



我在获取实体框架以正确保存收益回报的结果时遇到了一个问题。为了说明这个问题,我创建了两组方法,一组返回实体,另一组使用yield return返回IEnumerable。日志引用UserProfile。

第1组:

public static UserProfile CreateUser()
{
return new UserProfile() { 
UserId = Guid.Parse("60a3987c-0aa6-4a93-  a5d2-68c51122858b"), 
UserName = "jason"
};
}
public static Journal CreateJournal(UserProfile userProfile)
{
return new Journal() { UserProfile = userProfile };
}

第2组:

public static IEnumerable<UserProfile> CreateUsers()
{
yield return new UserProfile() { 
UserId = 
Guid.Parse("02cd1e9f-5947-4b08-9616-5b4f4033d074"), 
UserName = "john"
};
}
public static IEnumerable<Journal> CreateJournals(UserProfile userProfile)
{
yield return new Journal() { UserProfile = userProfile };
}

TestSet1和TestSet2分别保存来自Set1和Set2的结果。TestSet1可以工作,但TestSet2抛出违反PRIMARY KEY约束"PK_dbo.UserProfiles"的异常。另一个观察结果是,如果我初始化一个List并返回它而不是返回,那么它就可以工作。

public static void TestSet1()
{
var u = CreateUser();
var j = CreateJournal(u);
_db.UserProfiles.Add(u);
_db.Journals.Add(j);
_db.Commit();
}
public static void TestSet2()
{
var uList = CreateUsers();
var jList = CreateJournals(uList.ElementAt(0));
_db.UserProfiles.Add(uList.ElementAt(0));
_db.Journals.Add(jList.ElementAt(0));
_db.Commit();
}

你对为什么Set2的收益率不起作用有什么看法?感谢

由于您实际上并没有具体化列表,因此您正在创建2个UserProfile对象。如果你把一个断点放在这行上,你可以看到这一点:

yield return new UserProfile() { UserId = Guid.Parse("02cd1e9f-5947-4b08-9616-5b4f4033d074"), UserName = "john"};

您会注意到它被调用了两次,所以jList函数没有得到为uList创建的原始UserProfile,而是得到了一个新的UserProfile对象。现在,虽然它们有相同的Guid,但在技术上并不相等,因为它们是引用类型,并且不指向同一个地方。然后,ChangeTracker会发现它们不相等,并尝试在数据库中创建两个对象,一个用于UserProfiles.Add(),然后第二个附加到您的jList,具有相同的Guid,这就是您得到错误的原因。

您可以通过在Test2函数中对CreateUsers调用ToList()来修复代码,将列表具体化到内存中,以便所有内容都匹配。

public static void TestSet2()
{
var uList = CreateUsers().ToList();
var jList = CreateJournals(uList.ElementAt(0));
_db.UserProfiles.Add(uList.ElementAt(0));
_db.Journals.Add(jList.ElementAt(0));
_db.Commit();
}

更多关于yield关键字如何工作的信息,从这里,这里和这里

相关内容

  • 没有找到相关文章

最新更新