【问题标题】:Entity Framework 5.0 SaveChanges of Complex objectsEntity Framework 5.0 复杂对象的 SaveChanges
【发布时间】:2013-02-09 11:35:46
【问题描述】:

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

我循环遍历列表以发现哪些已修改并使用以下命令添加: 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();
            }

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

【问题讨论】:

  • 如果来源有重复,你应该先解决这个问题。
  • 复制只在外键上。即两个不同的事务可能具有相同的事务类型。我不会在我的参数或数据库中多次拥有相同的事务密钥。

标签: c# ef-code-first entity-framework-5


【解决方案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();

【讨论】:

    【解决方案2】:

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

    foreach (var item in updated)
    {
       var original = db.MyEntities.Find(item.Id);
       db.Entry(original).CurrentValues.SetValues(item);
    }
    db.SaveChanges();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-26
      • 1970-01-01
      • 2012-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-10
      相关资源
      最近更新 更多