2016-11-09 6 views
0

EntityFrameworkとドメインモデルを使用して既存のユーザーを新しいデータで更新する際の質問があります。実際にはもっと問題に似ています。EntityFrameworkがエンティティに新しいデータを保存しない

OrderOrderEntityに変換した後、UserEntityに追加してデータベースに保存すると、指定した注文は保存されません。

だから私たちはここにIUserModelを持っている:

public interface IUser 
{ 
    int ID { get; } 
    List<IOrder> Orders { get; } 
} 

そして、ここでエンティティUserEntity

public class UserEntity 
{ 
    int ID { get; set; } 
    public List<OrderEntity> Orders { get; set; } 
} 

私たちはここPersistenceServiceサービスと呼ばれています:データベース内

public async Task<bool> UpdateInformation(IUser user) 
{ 
    using (var databaseContext = new DatabaseContext()) 
    { 
     var userEntity = await database.Users.Include(u => u.Orders) 
          .FirstOrDefaultAsync(x => x.ID == user.ID); 

     userEntity.Orders = user.Orders.ToEntity(); // Extension (convert to entity)   
     databaseContext.Entry(userEntity).State 
         = EntityState.Modified; // Do we need this? 
     databaseContext.Entry(userEntity.Orders).State 
         = EntityState.Modified; // Do we need this? 

     await databaseContext.SaveChangesAsync(); 
    } 
} 

テーブル次のようになります。

Orders          User 
--------         -------- 
int ID          int ID 
Money Price 
int UserId -- foreign key to user that owns this order  

編集:いくつかの時点で ユーザーは、我々がこれを行う呼び出す順序を作成したい場合:

public async void AddNewOrder(IOrder order) 
{ 
    IUser user = GetActiveUser(); // This just return an IUser 
    var persistenceService = GetPersistenceService(); // returns instance of persistence service 

    user.Orders.Add(order); 
    await persistenceService.UpdateInformation(user); 
} 

編集2016年9月11日:より多くのデバッグ後 を、それが見えます

await persistenceService.UpdateInformation(user); 

シンクを実行するコードを変更しても、これは変更されません。ロンリー的にも。だから、スレッドの問題はありません。

+0

このメソッドはどのように呼び出していますか? SaveChangesAsyncが機能するための時間を与える必要があります。あなたはUpdateInformation()を試しましたか?GetAwaiter()。GetResult()? –

+0

DavidGによると、単に注文を更新してユーザーと関連付けるのではないようだ。 –

+0

申し訳ありませんが、@ RicardoPeresも役立ちませんが、注文がどのようにユーザに追加されたかを示す編集を行ったので、同期作業を行うことで問題は解決されません。 – Nicholas

答えて

1

あなたはこの文で注文リストをオーバーライドしている:

userEntity.Orders = user.Orders.ToEntity(); // Extension (convert to entity) 

私はそれがものを台無しにするものだと確信しています。行を次のように変更した場合:

userEntity.Orders.AddRange(user.Orders.ToEntity()); 

私はそれが動作するはずだと思います。しかし、これは常に新しいものとしてすべての注文を顧客に追加します。これが必要でない場合は、AddとRemoveの組み合わせを使用してOrdersコレクションを追加するのではなく、Ordersコレクションを更新できます。しかし、何かを保存するかどうかだけをテストするためには、今のところAddRange()を使用することができます。

エンティティの状態を設定しないでください(接続していない場合)。したがって、これらの行を削除してください

 databaseContext.Entry(userEntity).State 
        = EntityState.Modified; // Do we need this? 
    databaseContext.Entry(userEntity.Orders).State 
        = EntityState.Modified; // Do we need this? 
+0

私はそうは思わない、これはすでにオーダーのエントリーを複製しているのだろうか? – Nicholas

+0

その場合、単純なAddRangeでは不十分で、いくらか複雑な同期メカニズムが必要になるかもしれませんが、Ordersプロパティを上書きすることが問題の原因になっていると思います。新しい値を追加し、既存の値を更新し、削除された値を削除するだけです。私はそれがうまくいくとはかなり確信しています。最初にAddRangeを実行すると重複が発生しますが、Ordersがまったく保存されているかどうかを確認する簡単な方法です。 – Robba

+0

ちょっと@Robba、私はあなたの解決策を試みたが、どちらも助けにはなりませんでした。 問題は、databaseContext.SaveChanges()です。決して返さない – Nicholas

0

問題は、ユーザーを更新することは役に立ちません。ユーザーIMOへの参照を含むOrdersを強制的に更新する必要があります。それらを追加せずに、DbEntryに状態を設定して更新を強制します。

+0

こんにちは、あなたの答えをありがとう。私はもう少しデバッグし、行のように見えるdatabaseContext.SaveChanges()は返さない(非同期でも同期でもない) – Nicholas

+0

トランザクションのデッドロックになるか? –

+0

ctx.Database.Log + = Console.WriteLineを追加してSQLを監視できませんか? –

関連する問題