C# 希望将实体作为泛型类型传递并提取通用功能

C# 希望将实体作为泛型类型传递并提取通用功能,c#,.net,linq,generics,entity-framework-core,C#,.net,Linq,Generics,Entity Framework Core,我有一个如下所示的实体结构,我在这里所做的是基于输入查找主实体,然后通过导航属性查找子实体,然后从不同位置的子表中删除子实体 public class GlazingOrGasMaterial : AEIMasterBase { [ForeignKey("SourceOfData"), GraphQLIgnore] public Guid? SourceOfDataId { get; set; } public virtual CodeStandard

我有一个如下所示的实体结构,我在这里所做的是基于输入查找主实体,然后通过导航属性查找子实体,然后从不同位置的子表中删除子实体

public class GlazingOrGasMaterial : AEIMasterBase
{
    [ForeignKey("SourceOfData"), GraphQLIgnore]
    public Guid? SourceOfDataId { get; set; }
    public virtual CodeStandardGuideline SourceOfData { get; set; }
    [ForeignKey("GlazingComplexMaterial"), GraphQLIgnore]
    public Guid? GlazingComplexMaterialId { get; set; }
    [ForeignKey("GlazingSimpleMaterial"), GraphQLIgnore]
    public Guid? GlazingSimpleMaterialId { get; set; }
    [ForeignKey("GlazingGasMaterial"), GraphQLIgnore]
    public Guid? GlazingGasMaterialId { get; set; }
    public virtual GlazingComplexMaterial GlazingComplexMaterial { get; set; }
    public virtual GlazingSimpleMaterial GlazingSimpleMaterial { get; set; }
    public virtual GlazingGasMaterial GlazingGasMaterial { get; set; }
}
下面是删除该子实体的代码

方法1:

   if(requestInput.RequestType == RequestAction.EDIT)
    {
        var existingGlazingOrGasMaterial = dbContext.GlazingOrGasMaterials.Find(requestInput.DataId);
        if(existingGlazingOrGasMaterial != default)
        {
            var existingGasMaterial = dbContext.GlazingGasMaterials.SingleOrDefault(gasMaterial => gasMaterial.Id == existingGlazingOrGasMaterial.GlazingGasMaterialId);
            if(existingGasMaterial != default)
            {
                dbContext.GlazingGasMaterials.Remove(existingGasMaterial);
            }
        }
    }
    if (requestInput.RequestType == RequestAction.EDIT)
    {
        var existingGlazingOrGasMaterial = dbContext.GlazingOrGasMaterials.Find(requestInput.DataId);
        if (existingGlazingOrGasMaterial != default)
        {
            var existingComplexMaterial = dbContext.GlazingComplexMaterials.SingleOrDefault(complexMaterial => complexMaterial.Id == existingGlazingOrGasMaterial.GlazingComplexMaterialId);
            if (existingComplexMaterial != default)
            {
                dbContext.GlazingComplexMaterials.Remove(existingComplexMaterial);
            }
        }
    }
    if (requestInput.RequestType == RequestAction.EDIT)
    {
        var existingGlazingOrGasMaterial = dbContext.GlazingOrGasMaterials.Find(requestInput.DataId);
        if (existingGlazingOrGasMaterial != default)
        {
            var existingSimpleMaterial = dbContext.GlazingSimpleMaterials.SingleOrDefault(simpleMaterial => simpleMaterial.Id == existingGlazingOrGasMaterial.GlazingSimpleMaterialId);
            if (existingSimpleMaterial != default)
            {
                dbContext.GlazingSimpleMaterials.Remove(existingSimpleMaterial);
            }
        }
    }
下面是我删除该子实体的代码

方法2:

   if(requestInput.RequestType == RequestAction.EDIT)
    {
        var existingGlazingOrGasMaterial = dbContext.GlazingOrGasMaterials.Find(requestInput.DataId);
        if(existingGlazingOrGasMaterial != default)
        {
            var existingGasMaterial = dbContext.GlazingGasMaterials.SingleOrDefault(gasMaterial => gasMaterial.Id == existingGlazingOrGasMaterial.GlazingGasMaterialId);
            if(existingGasMaterial != default)
            {
                dbContext.GlazingGasMaterials.Remove(existingGasMaterial);
            }
        }
    }
    if (requestInput.RequestType == RequestAction.EDIT)
    {
        var existingGlazingOrGasMaterial = dbContext.GlazingOrGasMaterials.Find(requestInput.DataId);
        if (existingGlazingOrGasMaterial != default)
        {
            var existingComplexMaterial = dbContext.GlazingComplexMaterials.SingleOrDefault(complexMaterial => complexMaterial.Id == existingGlazingOrGasMaterial.GlazingComplexMaterialId);
            if (existingComplexMaterial != default)
            {
                dbContext.GlazingComplexMaterials.Remove(existingComplexMaterial);
            }
        }
    }
    if (requestInput.RequestType == RequestAction.EDIT)
    {
        var existingGlazingOrGasMaterial = dbContext.GlazingOrGasMaterials.Find(requestInput.DataId);
        if (existingGlazingOrGasMaterial != default)
        {
            var existingSimpleMaterial = dbContext.GlazingSimpleMaterials.SingleOrDefault(simpleMaterial => simpleMaterial.Id == existingGlazingOrGasMaterial.GlazingSimpleMaterialId);
            if (existingSimpleMaterial != default)
            {
                dbContext.GlazingSimpleMaterials.Remove(existingSimpleMaterial);
            }
        }
    }
方法3:

   if(requestInput.RequestType == RequestAction.EDIT)
    {
        var existingGlazingOrGasMaterial = dbContext.GlazingOrGasMaterials.Find(requestInput.DataId);
        if(existingGlazingOrGasMaterial != default)
        {
            var existingGasMaterial = dbContext.GlazingGasMaterials.SingleOrDefault(gasMaterial => gasMaterial.Id == existingGlazingOrGasMaterial.GlazingGasMaterialId);
            if(existingGasMaterial != default)
            {
                dbContext.GlazingGasMaterials.Remove(existingGasMaterial);
            }
        }
    }
    if (requestInput.RequestType == RequestAction.EDIT)
    {
        var existingGlazingOrGasMaterial = dbContext.GlazingOrGasMaterials.Find(requestInput.DataId);
        if (existingGlazingOrGasMaterial != default)
        {
            var existingComplexMaterial = dbContext.GlazingComplexMaterials.SingleOrDefault(complexMaterial => complexMaterial.Id == existingGlazingOrGasMaterial.GlazingComplexMaterialId);
            if (existingComplexMaterial != default)
            {
                dbContext.GlazingComplexMaterials.Remove(existingComplexMaterial);
            }
        }
    }
    if (requestInput.RequestType == RequestAction.EDIT)
    {
        var existingGlazingOrGasMaterial = dbContext.GlazingOrGasMaterials.Find(requestInput.DataId);
        if (existingGlazingOrGasMaterial != default)
        {
            var existingSimpleMaterial = dbContext.GlazingSimpleMaterials.SingleOrDefault(simpleMaterial => simpleMaterial.Id == existingGlazingOrGasMaterial.GlazingSimpleMaterialId);
            if (existingSimpleMaterial != default)
            {
                dbContext.GlazingSimpleMaterials.Remove(existingSimpleMaterial);
            }
        }
    }
下面是子实体的结构

public class GlazingSimpleMaterial 
{
    public Guid Id { get; set; }
    .....
    .....
}
public class GlazingComplexMaterial 
{
    public Guid Id { get; set; }
    .....
    .....
}
public class GlazingGasMaterial 
{
    public Guid Id { get; set; }
    .....
    .....
}
我正在寻找一种常见的方法,我们可以将实体作为泛型类型传递并进行删除,有人能告诉我如何实现这一点吗


非常感谢

首先,让我们加快查询速度

if (requestInput.RequestType == RequestAction.EDIT)
{
    var query = 
       from m in dbContext.GlazingOrGasMaterials
       join gasMaterial in dbContext.GlazingGasMaterials on m.GlazingGasMaterialId equals gasMaterial.Id
       where m.Id == requestInput.DataId
       select gasMaterial;

    var existingGasMaterial = query.FirstOrDefault();

    if (existingGasMaterial != default)
    {
        dbContext.GlazingGasMaterials.Remove(existingGasMaterial);
    }
}

如果要盲目删除某些内容,则不需要首先从数据库中加载它

dbContext.GlazingGasMaterials.Remove(
新型玻璃钢材料{
Id=现有GlazingGorgasMaterial.GlazingGasMaterialId
});
假设您的类型实现了一个公共接口来定义它们的主键,那么您可以对上述内容进行概括

publicstaticvoidremove(这个DbContext上下文,Guid Id),其中T:IPrimaryKey,new()=>
dbContext.Set.Remove(
新T{
Id=Id
});
尽管这并没有使代码简化那么多

然后通过导航属性查找子实体

您不需要手动执行此操作,EF Core可以使用可用的方法为您执行此操作-eager、explicit或lazy。在这种特殊情况下,急切加载可能是最合适的,因为它允许您将前两个步骤(查找主实体和关联的子实体)与单个数据库请求结合在一起

无论您选择何种方法来查找子实体,所讨论的方法的泛化将是提供导航属性访问器表达式(
expression
),这将足以执行当前代码的等效操作

例如,假设
GlazingOrGasMaterial.Id
属性类型为
Guid
,并且来自
AEIMasterBase
类,则主体可以概括为

public static void RemoveChild<TParent, TChild>(
    DbContext db,
    Guid parentId,
    Expression<Func<TParent, TChild>> childReference // <--
)
    where TParent : AEIMasterBase
    where TChild : class
{
    var parent = db.Set<TParent>()
        .Include(childReference) // <--
        .FirstOrDefault(p => p.Id == parentId);
    if (parent != null)
    {
        var child = db.Entry(parent)
            .Reference(childReference) // <--
            .CurrentValue;
        if (child != null)
            db.Remove(child);
    }
}

其中,
m.{NavigationProperty}
分别是
m.GlazingAsMaterial
m.GlazingComplexMaterial
m.GlazingSimpleMaterial
GlazingGorgasMaterial
GlazingComplexMaterial,GlazingSimplexMaterial,GlazingAsMaterial
之间的关系是什么。对于您的型号,我了解到,玻璃钢材质可以有无、一种、两种或三种类型
GlazingComplexMaterial、GlazingSimpleMaterial、glazinggasmmaterial
。这是否正确?解决方案将比您的代码更复杂。我认为这是浪费时间。无论如何,试着在一个查询中找到子实体,我看不出发送两个查询的原因。@RodRamírez我确实在每个子实体到父实体之间有一对一的关系entity@SvyatoslavDanyliv你能告诉我正确的方向吗?发一个查询来找到这个孩子entity@IvanStoev,我没有看到有问题的导航属性。我只删除了一个子实体。