1

これは私の最初の投稿です。すべてがうまくいくことを願っています。

ここに私の問題があります: データベースにUserTypesというテーブルがあります。それは持っています:

  1. ID;
  2. IsPrivate;
  3. 親_ID;

該当するのは1枚目と3枚目です。UserTypes_Tという別のテーブルがあります。これには、言語固有のさまざまなタイプの情報が含まれています。フィールドは次のとおりです。

  1. 言語_ID;
  2. UserType_ID;
  3. 名前;

私が達成しようとしているのは、UserTypesテーブルから階層全体を読み込み、それを TreeView に表示することです (これは今のところ関係ありません)。次に、いくつかのユーザー タイプを選択して、個別の編集ボックス (名前) とコンボ ボックス (親) で編集できます。

データベースの変更を永続化しようとするまで、すべてが正常に機能します。EF は、これらのテーブルに対して 2 つのエンティティ クラスを生成してくれました。

ユーザータイプのクラスには次のものがあります。

  1. ID;
  2. IsPrivate;
  3. 親_ID;
  4. 自己参照のナビゲーション プロパティ (0..1)。
  5. 子要素のナビゲーション プロパティ。
  6. UserTypes_T テーブルの別のナビゲーション プロパティ (1..*)。

翻訳された情報のクラスには次のものがあります。

  1. UserType_ID;
  2. 言語_ID;
  3. 名前;
  4. UserTypes テーブルへのナビゲーション プロパティ (*..1)。
  5. Languages テーブルへのナビゲーション プロパティ (*..1)。

以下を使用して必要なデータを取得します。

return context.UserTypes.Include("UserTypes_T").Where(ut => ut.IsPrivate==false).ToList();

私のWCF Webサービスで。問題なく新しいユーザー タイプを追加できますが、古いユーザー タイプを更新しようとすると、奇妙なことが起こります。

ルート要素 (Parent_ID==null) を更新すると、すべてが機能します。Parent_ID!=null の要素を更新すると、次のエラーが発生します。

オブジェクトのキー値が ObjectStateManager 内の別のオブジェクトと競合するため、AcceptChanges を続行できません。

私はインターネット全体を検索し、Diego B Vega (およびその他多数) のブログ投稿を読みましたが、私の問題は異なります。親ユーザー タイプを変更すると、実際にはナビゲーション プロパティではなく、Parent_ID プロパティが変更されます。問題を回避するために、生成されたナビゲーション プロパティではなく、常に ID を使用するようにしています。

私は少し調査を行い、取得したオブジェクトグラフが何であるかを確認しようとしましたが、重複するエンティティがたくさんあることがわかりました:

ルート要素には、その子要素のリストがありました。各子要素には、ルートまたはその親などへの後方参照がありました。想像できるでしょう。ID を使用して必要なデータを取得/設定したため、これらのナビゲーション プロパティを使用していなかったので、それらをモデルから削除しました。具体的には、 UserTypesエンティティ クラスからポイント45を削除しました。次に、各要素を 1 回だけ含むオブジェクト グラフを作成しました。新しいアップデートを試しましたが、同じ問題がありました:

ルート要素は正常に更新されましたが、いくつかの親を持つ要素が同じ例外をスローしました。

UserTypes_Tエンティティ クラスに、ユーザー タイプを指すナビゲーション プロパティがあることがわかったので、それも削除しました。その後、このエラーは消えました。オブジェクト グラフ内のすべてのアイテムは一意でした。しかし、問題は残っていました - ルート要素を問題なく更新できましたが、(除外なしで) 子を更新しようとすると、生成された Model.Context.Extensions クラスで null 参照例外が発生しました:

if (!context.ObjectStateManager.TryGetObjectStateEntry(entityInSet.Item2, out entry))
{
    context.AddObject(entityInSet.Item1, entityInSet.Item2);//here!
}

名前 ( UserTypes_Tにある) のみを更新しようとしましたが、エラーは同じです。

私はアイデアがなく、この問題を 8 時間解決しようとしてきました。誰かが私にアイデアを提供したり、経験を共有したりできれば幸いです。

PS:

子オブジェクトの更新に成功した唯一の方法は、次のコードを使用してデータを取得することでした。

var userTypes = argoContext.UserTypes.Include("UserTypes_T").Where(ut => ut.IsPrivate==false).ToList();
foreach (UserType ut in userTypes)
{
    ut.UserType1 = null;
    ut.UserTypes1 = null;
}
return userTypes;

ここで、UserType1はナビゲーション プロパティで、親ユーザー タイプを指し、UserTypes1はナビゲーション プロパティで、子要素のリストを保持します。ここでの問題は、EF がオブジェクトを「修正」し、Parent_IDnullに変更することでした。もう一度設定すると、EFもUserTypes1を設定します...この動作を停止する方法はありますか?

4

1 に答える 1

1

皆さん、問題が何であるかを見つけました。他の誰かが同じ問題に遭遇した場合は、回答を投稿しています。

問題は、ユーザー タイプ間に循環参照がないかどうかを確認するために、サーバーで検証を行っていたことです。したがって、サーバー上の私のメソッドは次のようになりました。

using (MyEntities context = new MyEntities()) 
{
    string errMsg = MyValidator.ValidateSomething(context.UserTypes,...);
    if (!string.IsNullOrEmpty(errMsg)) throw new FaultException(errMsg);
    //some other code here...
    context.UserTypes.ApplyChanges(_userType);//_userType is the one that is updated
    context.UserTypes.SaveChanges();
}

問題は、検証を行うときにコンテキストが満たされ、変更を保存しようとすると、同じキー値を持つオブジェクトが存在することです。

解決策は簡単です -サーバー上のものを検証するために異なるコンテキストを使用することです:

using (MyEntities validationContext = new MyEntities())
{
    //validation goes here...
}
using (MyEntities context = new MyEntities())
{
    //saving changes and other processing...
}

もう1つは次のとおりです。

using (MyEntities context = new MyEntities())
{
    using (MyEntities validationContext = new MyEntities())
    {
        //validation
    }
    //saving changes and other processing...
}

それでおしまい!誰かの役に立てば幸いです!

于 2011-06-09T06:29:13.143 に答える