0

EntityFrameworkでyieldreturnの結果を適切に保存する際に問題が発生します。2セットのメソッドを作成した問題を説明するために、1つはエンティティを返し、もう1つはyieldreturnを使用して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はPRIMARYKEY制約の違反'PK_dbo.UserProfiles'の例外をスローします。別の観察-私がリストを初期化し、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"};

2回呼び出されることに気付くでしょう。したがって、uList用に作成された元のUserProfileを取得する代わりに、jList関数は新しいUserProfileオブジェクトを取得します。現在、それらは同じGUIDを持っていますが、参照型であり、同じ場所を指していないため、技術的には等しくありません。ChangeTrackerは、それらが等しくないことを確認し、データベースに2つのオブジェクトを作成しようとします。1つはUserProfiles.Add()用で、2つ目は同じGUIDでjListにアタッチされます。これにより、エラーが発生します。 。

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 に答える