2

この質問は多く寄せられているようですが、私が抱えている問題を解決するものはまだ見つかりません。

明らかに、エンティティ フレームワークを使用してレコードの更新を実行しています。ただし、更新が完了すると、保存しようとするたびに次のエラー メッセージが表示されます。

An object with the same key already exists in the objectstatemanager

ZipCodeTerritory最初は、モデル オブジェクトのコピーを含むビューからコレクション オブジェクトを渡していましたzipToUpdate。このオブジェクトを引き出して、代わりに関連するフィールドを送信するだけで、コードを変更しました。ただし、まだ同じエラーが発生します。

また奇妙なのは、このコードを初めて実行したとき、正常に動作することです。その後の試みは、エラーが発生します。

コントローラ

edit 関数を呼び出すメソッドのコードは次のとおりです。

public static string DescriptionOnly(ZipCodeIndex updateZip)
{
    if (!string.IsNullOrWhiteSpace(updateZip.newEffectiveDate) || !string.IsNullOrWhiteSpace(updateZip.newEndDate))
    {
        return "Neither effective or end date can be present if updating Territory Code only; ";
    }

    _updated = 0;

    foreach (var zipCode in updateZip.displayForPaging.Where(x => x.Update))
    {
        ProcessAllChanges(zipCode, updateZip.newTerritory, updateZip.newStateCode, updateZip.newDescription, updateZip.newChannelCode);
    }

    _msg += _updated + " record(s) updated; ";

    return _msg;
}

そして、これが実際に更新を行うメソッドです。

private static void ProcessAllChanges(ZipCodeTerritory zipToUpdate, string newTerritory, string newStateCode, string newDescription, string newChannelCode)
{
    try
    {
        if (!string.IsNullOrWhiteSpace(newTerritory)) zipToUpdate.IndDistrnId = newTerritory;
        if (!string.IsNullOrWhiteSpace(newStateCode)) zipToUpdate.StateCode = newStateCode;
        if (!string.IsNullOrWhiteSpace(newDescription)) zipToUpdate.DrmTerrDesc = newDescription;
        if (!string.IsNullOrWhiteSpace(newChannelCode)) zipToUpdate.ChannelCode = newChannelCode;
        if (zipToUpdate.EndDate == DateTime.MinValue) zipToUpdate.EndDate = DateTime.MaxValue;

        _db.Entry(zipToUpdate).State = EntityState.Modified;
        _db.SaveChanges();
        _updated++;
    }
    catch (DbEntityValidationException dbEx)
    {
        _msg += "Error during update; ";
        EventLog.WriteEntry("Monet", "Error during ProcessAllChanges: " + zipToUpdate.ToString() + " |EX| " + dbEx.Message);
    }
    catch (Exception ex)
    {
        _msg += "Error during update; ";
        EventLog.WriteEntry("Monet", "Error during ProcessAllChanges: " + zipToUpdate.ToString() + " |MESSAGE| " + ex.Message);
    }
}

編集

オブジェクトには、モデル オブジェクトのZipCodeIndexリストが含まれています。ZipCodeTerritoryこれらは linq クエリから取得されるのではなく、単にビューからコントローラーに戻されます。プロセスを開始するコントローラ メソッドのシグネチャは次のとおりです。

[HttpPost]
public ActionResult Update(ZipCodeIndex updateZip, string button)
4

2 に答える 2

0

私がこのタイプの問題に遭遇したとき - 私はこれとまったく同じものを見たことはありませんが、かなりの数が似ています - それは、あるコンテキストでエンティティを取得し、別のコンテキストを使用してエンティティを保存しようとしたか、または何かが原因です。 Entity Framework がそれらを追跡できなくなる原因となっていました - を使用してデータストアからそれらを引き出すと、GetAsNoTrackingこの効果がありますが、明らかにパフォーマンス上の利点を提供するエンティティを変更しないことがわかっている場合.

この結果、EF は、使い慣れたエンティティに変更を加えるのではなく、既に知っているエンティティとほとんど同じ属性を持つ新しいエンティティを保存していると見なします。

あなたのコードからは、正確な解決策はわかりませんが、エンティティを取得している場所に細心の注意を払い、同じコンテキストで変更を保存していることを確認して、トラブルシューティングを開始します。

ZipCodeTerritoryあなたの編集は、新しいオブジェクトをビューからコントローラーに渡していることを示唆しています。これらはおそらくストア内の既存のエントリにマップされるZipCodeTerritoryため、ここで何が起こっているかというと、これらはデータベースから出てきたものではなく、正しいタイプのエンティティであるため、データ コンテキストはそれらを新しいオブジェクトとして認識します。既存のレコードを作成していないため、既存のレコードを更新していることがわからないため、ビューから返されるこれらのオブジェクトへの追跡参照を保持していません。

これにはもっと洗練された解決策があるかもしれません - 私は現在 4.5 で作業しているので、最近の EF の動作は見ていません - しかし、簡単な解決策はZipCodeTerritory、データ ストアから一致するオブジェクトを取得してから更新することです。それらを保存します。この場合、返されるZipCodeTerritoryオブジェクトはデータ転送オブジェクトのように動作するタイプですが、ビューによって作成されたため、ここで混乱を引き起こしています (データストアで発生したデータからではありますが)。あなたのデータ コンテキストは単にそれらを認識しません。

于 2013-10-25T15:06:48.803 に答える