2013-02-09 3 views
2

J'ai une méthode qui accepte un paramètre d'entrée pour une liste de transactions avec des enregistrements ajoutés ou mis à jour.Entity Framework 5.0 SaveChanges d'objets complexes

Je parcours la liste pour découvrir laquelle est modifiée et quelle est ajoutée en utilisant: context.Entry (item) .State = System.Data.EntityState.Modified; pour définir l'état de chaque transaction. Le problème que j'ai est parce que l'objet de transaction a une relation avec TransactionType pendant que je boucle la liste des transactions, s'il y a plus d'une transaction avec le même identificateur de transaction dans la base de données j'obtiens l'erreur suivante:

An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.

  • Par la façon dont je me sers EF5 et premier code.

La méthode préoccupation est:

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

## ACTUALISATION ## si je mets le TransactionType pour chaque élément à null, je reçois l'habitude de toute erreur et le reste des champs de transaction sera mis à jour bien. c'est-à-dire TransAmount, Date, etc. Le problème est qu'en réglant le TransType à null je ne serai jamais capable de changer le type de ma transaction.

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 ## Je viens de découvrir une autre façon que cela fonctionnerait, mais est toujours pas l'idéal pour moi. Je reçois la transaction unique par article, puis définissez les valeurs. Je n'aime pas cette solution puisque .Single fera un aller-retour pour chaque itération.

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

Si la source a Doublons vous devez résoudre ce problème en premier. –

+0

La duplication est uniquement sur la clé étrangère. c'est-à-dire que deux transactions différentes peuvent avoir le même TransactionType. Je n'aurai pas la même clé de transaction plus d'une fois dans mon param ou db. –

Répondre

1

La solution à mon problème était de séparer l'ajout de la mise à jour. Pour la mise à jour, récupérez chaque ligne de la base de données pour définir les valeurs d'origine avec les nouvelles. Pour ajouter il suffit d'ajouter les nouvelles valeurs au contexte.

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

Une autre façon de contourner ce problème:

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