レコードが追加または更新されたトランザクションのリストの入力パラメーターを受け入れるメソッドがあります。
リストをループして、変更されたものと、次を使用して追加されたウィッシュを検出します。context.Entry(item).State = System.Data.EntityState.Modified; 各トランザクションの状態を設定します。
私が抱えている問題は、トランザクションの入力パラメータリストをループしているときにトランザクションオブジェクトがTransactionTypeと関係があるためです。データベースに同じトランザクションIDを持つトランザクションが複数ある場合、次のエラーが発生します。
同じキーを持つオブジェクトは、ObjectStateManagerにすでに存在します。ObjectStateManagerは、同じキーを持つ複数のオブジェクトを追跡できません。
- ちなみに私はEF5とCodeFirstを使用しています。
問題の方法は次のとおりです。
public TransactionList SaveTransactions(Transaction[] transactions)
{
try
{
using (EntityContext context = new EntityContext())
{
foreach (var item in transactions)
{
if (item.TransactionId > 0)
context.Entry(item).State = System.Data.EntityState.Modified;
else
context.Entry(item).State = System.Data.EntityState.Added;
}
context.SaveChanges();
}
return GetLatestTransactions();
}
## UPDATE ## 各アイテムのTransactionTypeをnullに設定すると、エラーは発生せず、残りのトランザクションフィールドは正常に更新されます。つまり、TransAmount、Dateなどです。問題は、TransTypeをnullに設定すると、トランザクションのタイプを変更できなくなることです。
using (EntityContext context = new EntityContext())
{
foreach (var item in transactions)
{
//set the fk to null
item.TransactionType = null;
if (item.TransactionId > 0)
{
context.Entry(item).State = System.Data.EntityState.Modified;
}
else
context.Entry(item).State = System.Data.EntityState.Added;
}
context.SaveChanges();
}
##更新2## これが機能する別の方法を見つけましたが、それでも私にとっては理想的ではありません。アイテムごとに1つのトランザクションを取得してから、値を設定します。.Singleは反復ごとにラウンドトリップを実行するため、このソリューションは好きではありません。
foreach (var item in transactions)
{
var or = context.Transaction
.Include(t => t.Category)
.Include(t => t.TransactionReasonType)
.Include(t => t.TransactionType)
.Single(t => t.TransactionId == item.TransactionId);
if (item.TransactionId > 0)
{
context.Entry(or).CurrentValues.SetValues(item);
context.Entry(or).State = System.Data.EntityState.Modified;
}