2017-06-06 10 views
2

私はそれが動作このように属性を追加しようとするでしょう場合、私は次のモデルでEFコアDbのを持っており、1 EFコアは、関連するエンティティを追加します(一般的なリポジトリ)

多くの関係に
public class AttributeType 
{ 
    public int AttributeTypeId { get; set; } 
    public string Name { get; set; } 

    public List<Attribute> AttributeList { get; set; } 
} 

public class Attribute 
{ 
    public int AttributeId { get; set; } 
    public string Name { get; set; } 

    public int AttributeTypeId { get; set; } 
    public AttributeType AttributeType { get; set; } 
} 

using (var db = new SampleDbContext()) 
      { 
       var attributeType = db.AttributeTypes.FirstOrDefault(); 

       Attribute attribute = new Attribute 
       { 
        Name = "bbb", 
        AttributeTypeId = attributeType.AttributeTypeId, 
        AttributeType = attributeType 
       }; 
       var item = db.Attributes.Add(attribute); 
       db.SaveChanges(); 
      } 

(リアルにとattributeTypeは、テキストボックスからコンボボックスや名前から来るが、今みましょうジュースは、コードをシンプルに)

が、私は、ジェネリックメソッドを使用しようとすると、のような以下 コード、

 AttributeType attributeType; 

       using (var db = new SampleDbContext()) 
       { 
        attributeType = db.AttributeTypes.FirstOrDefault(); 
       } 

       Attribute attribute = new Attribute 
       { 
        Name = "eee", 
        AttributeType = attributeType, 
        AttributeTypeId = attributeType.AttributeTypeId 
       }; 

       DbService.Insert(attribute); 

public static bool Insert<T>(T item) where T : class 
     { 
      try 
      { 
       using (var db = new SampleDbContext()) 
       { 
        db.Add(item); 
        db.SaveChanges(); 
       } 
       return true; 
      } 
      catch (Exception exception) 
      { 
       Debug.WriteLine($"DbService Insert Exception: {exception}"); 
       return false; 
      } 

を仕事と私は

例外がスローされた次の例外を取得しません: 'Microsoft.EntityFrameworkCore.DbUpdateException' をMicrosoft.EntityFrameworkCore.dll DbService挿入例外で:Microsoft.EntityFrameworkCoreを。 DbUpdateException:エントリの更新中にエラーが発生しました。詳細については、内部例外を参照してください。 ---> Microsoft.Data.Sqlite.SqliteException:SQLiteエラー19: 'UNIQUE制約に失敗しました:AttributeTypes.AttributeTypeId'。 Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteでMicrosoft.Data.Sqlite.Interop.MarshalEx.ThrowExceptionForRC Microsoft.Data.Sqlite.SqliteCommand.ExecuteReaderで(のInt32 RC、Sqlite3Handle DB) (たCommandBehavior挙動) で(IRelationalConnection Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteでMicrosoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection接続) での接続、文字列executeMethod、IReadOnlyDictionary 2 parameterValues, Boolean closeConnection) at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary 2 parameterValues) ---内部例外スタックトレースの終わり--- ( IRelationalConnection connection) at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(Tuple 2 parameters) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IReadOnlyList 1 entriesToSave)UwpSamples.Services.DbService.InsertでMicrosoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(ブールacceptAllChangesOnSuccess)Microsoft.EntityFrameworkCore.DbContext.SaveChangesで (ブールacceptAllChangesOnSuccess) [T](Tアイテム)

しかし、それは動作しますが、次のコードのように、私はAttributeTypeでは通過しないか、私がnullに設定した場合:

AttributeType attributeType; 

     using (var db = new SampleDbContext()) 
     { 
      attributeType = db.AttributeTypes.FirstOrDefault(); 
     } 

     Attribute attribute = new Attribute 
     { 
      Name = "ddd", 
      AttributeType = null, 
      AttributeTypeId = attributeType.AttributeTypeId 
     }; 

     DbService.Insert(attribute); 

-

AttributeType attributeType; 

     using (var db = new SampleDbContext()) 
     { 
      attributeType = db.AttributeTypes.FirstOrDefault(); 
     } 

     Attribute attribute = new Attribute 
     { 
      Name = "ddd", 
      AttributeTypeId = attributeType.AttributeTypeId 
     }; 

     DbService.Insert(attribute); 

ありがとう

+1

私は混乱しています - 質問の最後の2つのコードブロックは、あなたの失敗したコードブロックとまったく同じですが、そのような場合には機能すると言いますか? –

+1

私はそれがEFがアイテムがどこに行くと思われるのか分からないという事実と関係していると考えています。 'List <>'型を 'ICollection <>'に変更し、そのプロパティを 'virtual'にすることをお勧めします。これにより、EFは 'ICollection <>'の実装として 'HashSet <>'型を使用し、子要素の '親' IDを追跡できます。ただし、これはEFコアで変更されている可能性があります。 –

+1

EFで汎用リポジトリを使用しないでください。関連エンティティ(単純またはコレクションのいずれか)を含むエンティティにはうまく適合しません。例えば、 'Add'メソッドはエンティティ**と**すべての関連データを追加しようとします。 –

答えて

2

2つの別々のコンテキストをインスタンス化しています。AttributeTypeを取得するリポジトリ内の2番目のコンテキストと、挿入を実行するリポジトリ内の2番目のコンテキストは、エンティティをトラバースし、AttributeTypeが新規であり、それを挿入しようとします。リクエストごとに1つのContextを使用することをお勧めします(これはWebリクエストの背後にあると仮定します)。エンティティに変更を加えないようにする回避策がありますが、毎回回避策を繰り返す必要があり、それぞれのモデルに非常に特化しています。

通常、リクエストごとにコンテキストを取得するには、ContainerまたはIoCフレームワークを使用するか、リポジトリのコンストラクタでコンテキストを渡します。これにより、異なるリポジトリ間で複数のコールを行うことができ、コール間で変更の追跡が機能します。また、異なるリポジトリへの呼び出しでトランザクションスコープを開くシナリオも簡単になります。

1

失敗によると、attributeType.AttributeTypeIdの値は既にDBに存在しています。この価値が何であるか、それが本当にユニークであるかを確認できますか? この値はプライマリキーとして使用するので一意でなければならないと思います。

値を設定しないか、または明示的にnullに設定すると、DBによってIDが自動的に生成され、その理由が説明されます。

希望します。

関連する問題