c# - 希望将实体作为通用类型传递并提取通用功能
问题描述
我有一个如下所示的实体结构,我在这里所做的是基于输入找到主实体,然后通过导航属性找到子实体,然后从不同位置的子表中删除子实体
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; }
}
以下是删除该子实体的代码
方法一:
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; }
.....
.....
}
我正在寻找一种通用方法,我们可以将实体作为泛型类型传递并进行删除,有人可以告诉我如何实现这一点吗?
提前谢谢了!!
解决方案
然后通过导航属性找到子实体
您无需手动执行此操作,EF Core 可以使用加载相关数据的可用方法为您执行此操作- 急切、显式或惰性。在这种特殊情况下,预加载可能是最合适的,因为它允许您将前两个步骤(查找主实体和关联的子实体)与单个数据库请求结合在一起。
无论您选择哪种查找子实体的方法,所讨论的方法的概括都是提供导航属性访问器表达式 ( Expression<Func<TParent, TChild>>
),这足以执行当前代码的等效操作。
例如,假设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);
}
}
但是现在可以很容易地看出您并不真的需要父实体,因此可以将实现简化(也变得更高效)如下(相同的方法签名):
var child = db.Set<TParent>()
.Where(p => p.Id == parentId)
.Select(childReference) // <--
.FirstOrDefault();
if (child != null)
db.Remove(child);
在这两种情况下,这 3 个电话都是
if (requestInput.RequestType == RequestAction.EDIT)
RemoveChild(dbContext, requestInput.DataId, (GlazingOrGasMaterial m) => m.{NavigationProperty});
m.{NavigationProperty}
分别m.GlazingGasMaterial
在哪里m.GlazingComplexMaterial
和m.GlazingSimpleMaterial
推荐阅读
- c# - 关于顺序攻击/提前完成顺序的问题
- perl - 从奇点配方问题构建
- java - 如何将变量从一个类传递到另一个类?
- spring-boot - Spring Boot & RabbitMQ:如何检测应用程序何时重新连接到代理
- python-3.x - 没有名为“cv2”的模块:环境问题?
- outlook - 如何从 Applescript 访问未发送的 Outlook 邮件的收件人列表
- java - java.lang.NullPointer 异常 (TestNG)
- arrays - Java中的二进制字符串到字节数组
- php - 如何根据关系对标题进行排序
- python - 使用 Python 和 Selenium 在 XPath 中跟随兄弟姐妹