0

この問題は、stackoverflowで何度も議論されていますが、ジェネリックリポジトリパターンを使用してどのように解決されたかについての回答は見つかりませんでした。 すべての答えはDBContextを直接使用しています。ジェネリックリポジトリパターンでは、DBContextに直接アクセスすることはできません。また、Unity for IOCを使用しています。Entity Framework:汎用リポジトリパターンを使用して子を削除するにはどうすればよいですか?

ここに問題があります:私は親と親に子コレクションがあります。私は親にいくつかのプロパティを設定しており、コレクションから子を削除しています。外部キープロパティの 一つ以上が非NULL可能であるため、関係を変更することができませんでした:私はSaveChanges()を呼び出すときしかし、私はエラー

が取得操作に失敗しました。リレーションシップに が変更された場合、関連する外部キープロパティはNULL値に設定された です。外部キーがNULL値をサポートしていない場合は、 新しい関係を定義する必要があります。外部キーのプロパティは に別のNULL以外の値を割り当てる必要があります。または、関連しないオブジェクトは を削除する必要があります。

これで、EFがレコードを削除するのではなく、FKをnullに設定しようとしている理由がわかりません。 FKをヌルに設定し、DBに孤立レコードを保持するようにしましょう。

どのように私はこの問題をリポジトリパターンを使って解決しますか?リポジトリから新しいメソッドを公開する必要がありますか?

エンティティ

public class parent 
    { 
     public int ParentID {get;set;} //Primary Key 

     public string ParentName {get;set} 

     public ICollection<Child> Children {get;set} 
    } 

    public class Child 
    { 
     public int ChildID {get;set;} //Primary Key 

     public string ChildName {get;set;} 

     public int ParentID {get;set;} //Foreign Key 
    } 

サービス

public class MyService 
    { 
     private IGenericRepository _repository; 

     public MyService(IGenericRepository repository) 
     { 
      _repository = repository; 
     } 

     public void UpdateParent(int parentID,string parentName, int[] sourceChildIDs) 
     { 
      var p = _repository.GetQuery<Parent>() 
       .Include(x => x.Children) 
       .Where(x => x.ParentID == parentID) 
       .SingleOrDefault(); 

      p.ParentName = parentName; 

      var childrenToDetete = new List<Child>(); 
      foreach (var child in p.Children) 
      { 
       if (!sourceChildIDs.Contains(child.ChildID)) 
       { 
        childrenToDetete.Add(child); 
       } 
      } 

      foreach (var child in childrenToDetete) 
      { 
       p.Children.Remove(child); 
      }    

      _repository.SaveChanges(); // i get error here 
     } 
    } 

あなたは番目の子供を削除しているリポジトリ

public class GenericRepository : IGenericRepository 
    { 

     private DbContext _dbContext;   


     public GenericRepository(DbContext dbContext) 
     { 
      if (dbContext == null) 
      { 
       throw new ArgumentNullException("dbContext"); 
      } 

      _dbContext = dbContext; 
     } 


     public TEntity Create<TEntity>() where TEntity : class 
     { 
      return _dbContext.Set<TEntity>().Create<TEntity>(); 
     } 

     public TEntity Add<TEntity>(TEntity entity) where TEntity : class 
     { 
      if (entity == null) 
      { 
       throw new ArgumentNullException("entity"); 
      } 

      return _dbContext.Set<TEntity>().Add(entity); 
     } 

     public IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class 
     { 
      return _dbContext.Set<TEntity>(); 
     } 

     public IQueryable<TEntity> GetQuery<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class 
     { 
      return GetQuery<TEntity>().Where(predicate); 
     }  

     public void Delete<TEntity>(TEntity entity) where TEntity : class 
     { 
      if (entity == null) 
      { 
       throw new ArgumentNullException("entity"); 
      } 

      _dbContext.Set<TEntity>().Remove(entity); 
     } 

     public void Delete<TEntity>(Expression<Func<TEntity, bool>> criteria) where TEntity : class 
     { 
      IEnumerable<TEntity> records = GetQuery<TEntity>(criteria); 

      foreach (TEntity record in records) 
      { 
       Delete<TEntity>(record); 
      } 
     } 

     public void Update<TEntity>(TEntity entity) where TEntity : class 
     { 
      if (entity == null) 
      { 
       throw new ArgumentNullException("entity"); 
      } 

      _dbContext.Entry(entity).State = EntityState.Modified; 
     } 

     public int SaveChanges() 
     { 
      return _dbContext.SaveChanges(); 
     }  
    } 

答えて

0

e親であるが、データベースからではない。補足として、より簡潔な方法でこれを行うことができます:

foreach (var child in p.Children 
         .Where(child => !sourceChildIDs.Contains(child.ChildID)) 
         .ToList()) 
{ 
    p.Children.Remove(child); 
} 

しかし、これは親と子の間の関連付けを破るだけです。 EFは注意の面で間違っており、子どもの外部キー参照のみを削除したいと考えていますが、子どもを完全に削除することはしません。

だから、あなたがところで

var delIds = p.Children.Where(child => !sourceChildIDs.Contains(child.ChildID)) 
         .Select(c => c.ChildID).ToList(); 
_repository.Delete<Child>(c => delIds.Contains(c.ChildID)); 

により、前の文に置き換えることによって、データベースから子どもを削除する必要があり、これはかなり珍しい、一般的なリポジトリの実装です。通常、汎用リポジトリは1つのタイプに対してインスタンス化される。すなわち、定義はGenericRepository<T>となる。これらのリポジトリのインスタンスは、一般的に1つのコンテキストインスタンスを共有し、変更を保存する1つの作業単位で協力します。

+0

私はまだdelid – LP13

+0

を計算する必要が推測一行を忘れ、私はどのようにあなたがMyService' 'に' 'GenericRepository を注入しようとしている、種類ごとに' GenericRepository を '実装する場合。) –

+0

感謝を。このサービスにはいくつかのメソッドがあり、どのエンティティにもクエリーできる必要があります。 – LP13

関連する問題