C# 使用递归方法的级联删除

C# 使用递归方法的级联删除,c#,sql-server,generics,recursion,ef-power-tools,C#,Sql Server,Generics,Recursion,Ef Power Tools,我需要一种方法来删除其他表中的用户及其所有约束。我知道sql server中有级联删除,但由于某些原因,我不能使用它 假设一个用户有几个订单,每个订单都有一些产品。所以我在方法中发送给用户,它找到订单,在foreach循环中进入该订单,以此类推 所以我要写一个递归的方法来实现这一点;它必须接受一个对象,找到它的所有关系,并经历所有的过程 我首先使用EF power tools反向工程代码从数据库生成这些代码。这是我的班级: public partial class myDbContext: Db

我需要一种方法来删除其他表中的用户及其所有约束。我知道sql server中有级联删除,但由于某些原因,我不能使用它

假设一个用户有几个订单,每个订单都有一些产品。所以我在方法中发送给用户,它找到订单,在foreach循环中进入该订单,以此类推

所以我要写一个递归的方法来实现这一点;它必须接受一个对象,找到它的所有关系,并经历所有的过程

我首先使用EF power tools反向工程代码从数据库生成这些代码。这是我的班级:

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; }
}
使用
collectionType[0]
我看到它是
Orders
,我必须有这样的东西才能查询:

var childType = ctx.Set<collectionType[0]>;
var childType=ctx.Set;
但我找不到合适的演员阵容


如果这是完全错误的,任何提示都可以帮助我找到正确的方向。

这是完全不合适的。当您应该使用这些用户最初映射的关系模型时,您正在以草率的方式执行数据库关系操作

最好将应用程序用作调用存储过程,在该过程中,数据库语言可以映射所涉及的表,并为用户及其对象删除正确的行


与dba和设计这些表的开发人员合作,将数据库操作留给数据库,将框架操作留给框架

我觉得@clifton_h的回答是对的。但是如果您想使用youre方法,可以使用它返回要包含的字符串。使用它查找和删除对象

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

注意打字错误。我把答案写在手机上。

以防有人需要我要找的东西。该类获取一个对象,并查找与
ICollection
类型的所有关系,递归遍历这些关系并删除基本子对象

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

这只是一个本地测试应用程序,我需要删除所有的测试用户和它附带的东西。它并不打算在日常用例中发布和使用。此外,有很多关系和表,我想不出在数据库端实现这一点的方法。
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();
}