使用 EF Core 在通用存储库中包含所有使用反射的导航属性
Include all navigation properties using Reflection in generic repository using EF Core
我正在为 EF Core 项目创建一个通用存储库,以避免必须为所有模型编写 CRUD。我遇到的一个主要障碍是未加载导航属性,因为 Core 尚不支持延迟加载并且通用 class 显然无法定义 .Include 语句 class 特定属性。
我正在尝试为我的 Get 方法执行类似的操作以动态包含所有属性:
public virtual T Get(Guid itemId, bool eager = false)
{
IQueryable<T> querySet = _context.Set<T>();
if (eager)
{
foreach (PropertyInfo p in typeof(T).GetProperties())
{
querySet = querySet.Include(p.Name);
}
}
return querySet.SingleOrDefault(i => i.EntityId == itemId);
}
但是当包含不是导航属性的属性时会引发错误。
我发现这个答案大致相同,但它适用于 EF 5,并且涉及 EF 核心中不存在的方法:
EF5 How to get list of navigation properties for a domain object
是否可以在 EF Core 中完成同样的事情?
在 EF Core 中使用元数据比在以前的 EF 版本中容易得多。 DbContext
class provides Model
属性 提供对
的访问
The metadata about the shape of entities, the relationships between them, and how they map to the database.
执行您要求的代码可能是这样的:
public virtual IQueryable<T> Query(bool eager = false)
{
var query = _context.Set<T>().AsQueryable();
if (eager)
{
var navigations = _context.Model.FindEntityType(typeof(T))
.GetDerivedTypesInclusive()
.SelectMany(type => type.GetNavigations())
.Distinct();
foreach (var property in navigations)
query = query.Include(property.Name);
}
return query;
}
public virtual T Get(Guid itemId, bool eager = false)
{
return Query(eager).SingleOrDefault(i => i.EntityId == itemId);
}
请注意,虽然这符合您的要求,但它是非常有限的通用方法,因为它只急于加载实体的直接导航属性,即不处理使用 ThenInclude
加载嵌套导航属性。
private List<PropertyInfo> GetNavigationProperties<T>(GesFormaContext _gesFormaContext)
{
List<PropertyInfo> propertyInfos = new List<PropertyInfo>();
_gesFormaContext.Model.GetEntityTypes().Select(x => x.GetNavigations()).ToList().ForEach(entityTypes =>
{
entityTypes.ToList().ForEach(property =>
{
propertyInfos.AddRange(typeof(T).GetProperties().Where(x => x.PropertyType == property.PropertyInfo.PropertyType).ToList());
});
});
return propertyInfos;
}
我正在为 EF Core 项目创建一个通用存储库,以避免必须为所有模型编写 CRUD。我遇到的一个主要障碍是未加载导航属性,因为 Core 尚不支持延迟加载并且通用 class 显然无法定义 .Include 语句 class 特定属性。
我正在尝试为我的 Get 方法执行类似的操作以动态包含所有属性:
public virtual T Get(Guid itemId, bool eager = false)
{
IQueryable<T> querySet = _context.Set<T>();
if (eager)
{
foreach (PropertyInfo p in typeof(T).GetProperties())
{
querySet = querySet.Include(p.Name);
}
}
return querySet.SingleOrDefault(i => i.EntityId == itemId);
}
但是当包含不是导航属性的属性时会引发错误。
我发现这个答案大致相同,但它适用于 EF 5,并且涉及 EF 核心中不存在的方法:
EF5 How to get list of navigation properties for a domain object
是否可以在 EF Core 中完成同样的事情?
在 EF Core 中使用元数据比在以前的 EF 版本中容易得多。 DbContext
class provides Model
属性 提供对
The metadata about the shape of entities, the relationships between them, and how they map to the database.
执行您要求的代码可能是这样的:
public virtual IQueryable<T> Query(bool eager = false)
{
var query = _context.Set<T>().AsQueryable();
if (eager)
{
var navigations = _context.Model.FindEntityType(typeof(T))
.GetDerivedTypesInclusive()
.SelectMany(type => type.GetNavigations())
.Distinct();
foreach (var property in navigations)
query = query.Include(property.Name);
}
return query;
}
public virtual T Get(Guid itemId, bool eager = false)
{
return Query(eager).SingleOrDefault(i => i.EntityId == itemId);
}
请注意,虽然这符合您的要求,但它是非常有限的通用方法,因为它只急于加载实体的直接导航属性,即不处理使用 ThenInclude
加载嵌套导航属性。
private List<PropertyInfo> GetNavigationProperties<T>(GesFormaContext _gesFormaContext)
{
List<PropertyInfo> propertyInfos = new List<PropertyInfo>();
_gesFormaContext.Model.GetEntityTypes().Select(x => x.GetNavigations()).ToList().ForEach(entityTypes =>
{
entityTypes.ToList().ForEach(property =>
{
propertyInfos.AddRange(typeof(T).GetProperties().Where(x => x.PropertyType == property.PropertyInfo.PropertyType).ToList());
});
});
return propertyInfos;
}