实体框架5.0复杂对象的SaveChanges

时间:2013-02-09 11:35:46

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

我有一个方法接受带有添加或更新记录的事务列表的输入参数。

我遍历列表以发现修改了哪个并使用以下方法添加了whish: context.Entry(item).State = System.Data.EntityState.Modified; 设置每笔交易的状态。

我遇到的问题是因为事务对象与TransactionType有关系,而我遍历事务的输入参数列表,如果在数据库中有多个具有相同事务ID的事务,则会出现以下错误:< / p>

  

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

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

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

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