2

我有一个方法,它接受一个输入参数,用于添加或更新记录的交易列表。

我遍历列表以发现哪些被修改并使用以下命令添加了whish:context.Entry(item).State = System.Data.EntityState.Modified; 设置每个事务的状态。

我遇到的问题是因为事务对象与 TransactionType 有关系,而我循环遍历事务的输入参数列表,如果数据库中有多个具有相同事务 id 的事务,我会收到以下错误:

ObjectStateManager 中已存在具有相同键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象。

  • 顺便说一句,我使用的是 EF5 和 Code First。

关注的方法是:

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();
}

## UPDATE 2 ## 我刚刚找到了另一种可行的方法,但仍然不是我的理想选择。我得到每个项目的单笔交易,然后设置值。我不喜欢这种解决方案,因为 .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;
  }
4

2 回答 2

1

我的问题的解决方案是将添加与更新分开。对于更新,从数据库中获取每一行,将原始值设置为新值。对于添加,只需将新值添加到上下文中。

foreach (var item in transactions)
{
  if (item.TransactionId > 0) //Update
  {
    var original = context.Transaction.Where(
                            t => t.TransactionId == item.TransactionId)
                          .FirstOrDefault();

    original.TransactionType = context.TypeTransaction.Single(
                           p => p.TypeTransactionId == item.TransactionType.TypeTransactionId);

    context.Entry(original).CurrentValues.SetValues(item);
  }
  else //Insert
  {    
    item.TransactionType = context.TypeTransaction.Single(
                           p => p.TypeTransactionId == item.TransactionType.TypeTransactionId);

    context.Transaction.Add(item);
  }
}

context.SaveChanges();
于 2013-02-12T07:39:07.250 回答
0

解决此问题的另一种方法:

foreach (var item in updated)
{
   var original = db.MyEntities.Find(item.Id);
   db.Entry(original).CurrentValues.SetValues(item);
}
db.SaveChanges();
于 2013-08-16T19:11:34.310 回答