2017-08-05 10 views
-1

ユーザとそのすべての制約を他のテーブルで削除する方法が必要です。私は、SQL Serverでカスケード削除の知っているが、私はいくつかの理由でこれを使用することはできません。再帰的メソッドを使用したカスケード削除

ユーザーに複数の注文があり、それぞれの注文に商品がいくつかあるとします。私はメソッドのユーザーを送信するので、それは注文を見つけるforeachループでは、そのような順序で行くなど。

私はこれを再帰的に行う方法を書いています。それは物体を受け取り、すべての関係を見つけてそれをすべて通過しなければならない。

私はEFパワーツールをリバースエンジニアのコードを使ってデータベースから生成しています。

public partial class myDbContext: DbContext 
{ 
    ... 

    public DbSet<Users> Users{ get; set; } 
    public DbSet<Orders> Orders{ get; set; } 
    public DbSet<Products> Products{ get; set; } 
    public DbSet<OrderProducts> OrderProducts{ get; set; } 

    ... 
} 
public partial class Users 
{ 
    public int UserID { get; set; } 
    public string Username { get; set; } 
    public virtual ICollection<Orders> Orders{ get; set; } 
} 
public partial class Orders 
{ 
    public int OrderID { get; set; } 
    public virtual Users users { get; set; } 
    public virtual ICollection<OrderProducts> OPs { get; set; } 
} 
public partial class OrderProducts 
{ 
    public int OPID { get; set; } 
    public virtual Orders orders { get; set; } 
    public virtual Product products { get; set; } 
} 

私はユーザーオブジェクト内のすべてのvirtual ICollectionのを見つけることができています。このメソッドを使用して:ここに私のクラスです。私はそれがOrdersであることがわかりcollectionType[0]を使用して

private void DeleteObjectAndChildren(object parent) 
    { 
     using (var ctx = new myDbContext()) 
     { 
      Type t = parent.GetType(); 

      //these are all virtual properties of parent 
      var properties = parent.GetType().GetProperties().Where(p => p.GetGetMethod().IsVirtual); 
      foreach (var p in properties) 
      { 
       var collectionType = p.PropertyType.GetGenericArguments(); 
       //collectionType[0] gives me the T type in ICollection<T> 

       //what to do next? 
      } 
     } 
    } 

、私が照会できるようにするには、このような何かを持っている必要があります。

var childType = ctx.Set<collectionType[0]>; 

を私は右のキャストと全てを取得することはできません。

これが完全に間違っていれば、私は正しい方向に私を得るためにどんなヒントもありがとうと思います。

答えて

0

私が探していた人が必要な場合。このクラスはオブジェクトを取得し、ICollection<T>型のすべての関係を見つけ出し、再帰的にそれをトラバースしてベースの子を削除します。

public class RemoveEntityAndAllRelations 
{ 
    private DbContext _context; 

    public void SetContext(DbContext ctx) 
    { 
     _context = ctx; 
    } 

    public void RemoveChildren(object parent) 
    { 
     Type obj = parent.GetType(); 

     MethodInfo method = typeof(RemoveUserAndAllRelations).GetMethod("GetICollections"); 
     MethodInfo generic = method.MakeGenericMethod(obj); 

     var properties = (PropertyInfo[])generic.Invoke(this, null); 
     if (properties.Any()) 
     { 
      foreach (PropertyInfo propertyInfo in properties) 
      { 
       object child = propertyInfo.GetValue(parent, null); 
       RemoveChildren(child); 
      } 

      try 
      { 
       dynamic dd = parent; 
       _context.Entry(dd[0]).State = EntityState.Deleted; 
       _context.SaveChanges(); 
      } 
      catch (Exception) 
      { 
        //do what you like 
      } 
     } 
     else 
     { 
      try 
      { 
       dynamic dd = parent; 
       _context.Entry(dd[0]).State = EntityState.Deleted; 
       _context.SaveChanges(); 
      } 
      catch (Exception) 
      { 
        //do what you like 
      } 
     } 
    } 
    public PropertyInfo[] GetICollections<TEntity>() where TEntity : class 
    { 
     return typeof(TEntity).GetProperties().Where(m => 
      m.PropertyType.IsGenericType && 
      m.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>) 
     ).ToArray(); 
    } 
} 

とそれだけでローカルテストアプリケーションの

using (var ctx = new myDbContext()) 
{ 
    var user = ctx.Users.FirstOrDefault(x => x.UserID == userId); 
    RemoveEntityAndAllRelations controller = new RemoveUserAndAllRelations(); 

    controller.SetContext(ctx); 
    controller.RemoveChildren(user); 

    ctx.Core_Users.Remove(user); 
    ctx.SaveChanges(); 
} 
0

これは完全に不適切です。これらのユーザーが最初にマップされたリレーショナル・モデルを使用する必要がある場合は、データベースのリレーショナル・オペレーションを巧妙に実行しています。

アプリケーションは、データベース言語が関連するテーブルをマップし、ユーザーとそのオブジェクトの正しい行を削除できるストアドプロシージャを呼び出すことをお勧めします。

dbaおよびこれらのテーブルを使用する開発者と協力して、データベース操作およびデータベース操作をフレームワークに委ねます。

+0

のようにそれを使用し、私はそれに付属するすべてのテストユーザーと物事を削除する必要があります。それは毎日のユースケースで公開され、使用されることを意図していません。また、関係やテーブルがたくさんあり、データベース側でこれを行う方法は考えられません。 –

0

@clifton_hからの回答は私には似ています。しかしyoureメソッドを使いたい場合は、それを使用して文字列を返すことができます。オブジェクトを見つけて削除するための使い方。

var user = users.Include("Orders.OrdersProducts"); 
ctx.Delete(user); 
ctx.SaveChanges(); 

誤字に気をつけてください。私は私の電話で答えを書いた。

関連する問題