0

我在让实体框架正确保存收益返回的结果时遇到问题。为了说明问题,我创建了两组方法,一组返回一个实体,另一组使用 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 引发违反主键约束“PK_dbo.UserProfiles”的异常。另一个观察结果 - 如果我初始化一个 List 并返回它而不是 yield return 那么它就可以工作。

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 中的收益回报不起作用有何看法?谢谢

4

1 回答 1

1

发生的事情是因为您实际上并没有具体化列表,所以您正在创建 2 个 UserProfile 对象。如果您在此行上放置断点,您可以看到这一点:

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

您会注意到它被调用了两次——因此 jList 函数不是获取为 uList 创建的原始 UserProfile,而是获取一个的UserProfile 对象。现在,虽然它们具有相同的 Guid,但它们在技术上并不相等,因为它们是引用类型并且它们没有指向同一个地方。然后 ChangeTracker 将看到它们不相等并尝试在数据库中创建 2 个对象,一个用于 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 关键字如何工作的更多信息,请参见此处此处此处

于 2012-09-17T04:14:14.800 回答