提问人:user1209216 提问时间:9/17/2012 最后编辑:halferuser1209216 更新时间:8/26/2023 访问量:35067
实体框架 - 按名称获取实体 [duplicate]
Entity framework - get entity by name [duplicate]
问:
我有以下代码(示例):
public dynamic GetData(string name)
{
using(var ctx = GetObjectContext())
{
switch (name)
{
case "entity1":
return ctx.entity1.ToList();
case "entity2":
return ctx.entity2.ToList();
......
default:
return null;
}
}
}
我想避免在此示例中切换。如何按名称找到所需的实体类,调用 ToList() 方法并返回数据?我可以使用反射来做到这一点吗?
答:
您可以使用反射来执行此操作,但是您还需要使用泛型,因为 ToList() 方法返回的列表类型对于每个实体类型都不同。
您可以通过反射访问属性 getter,如下所示:
var enumerable = typeof([ClassNameOfContext]).GetProperty(name).GetValue(ctx, null);
Whereas 是 ctx 作为其实例的类的名称。这在您的代码中并不明显,但您知道:-)[ClassNameOfContext]
问题是这将是一个并且必须被强制转换为您正在访问的实体类型。换句话说,这取决于您传递的名称。如果使用泛型来确定类型,则将能够正确转换对象,而不必返回偶数。enumerable
object
IEnumerable<EntityType>
EntityType
dynamic
public TEntity Get<TEntity>(string name)
{
...
并从上面转换线条:
var enumerable = (IEnumerable<TEntity>)(typeof([ClassNameOfContext]).GetProperty(name).GetValue(ctx, null));
return enumerable.ToList();
给你!
附录:可以想象,您也可以去掉字符串参数 - 应尽可能避免在字符串中使用类型或属性的名称,因为它不是类型安全的。编译器无法识别它,并且 IDE 功能(如重构)不会考虑它。这里的问题是,属性名称通常是实体类型名称的复数形式。但是,您可以使用反射来查找其类型与 TEntity
匹配的属性。我把它作为一个练习:-)
评论
dynamic
<TEntity>
GetData<Rabbit>("Rabbits")
TEntity
你可以像这样使用代码
private IEnumerable<TEntity> GetList<TEntity>(string connectionString, Func<object, T> caster)
{
using (var ctx = new DbContext(connectionString))
{
var setMethod = ctx.GetType().GetMethod("Set").MakeGenericMethod(typeof(T));
var querable = ((DbSet<object>)setMethod
.Invoke(this, null))
.AsNoTracking()
.AsQueryable();
return querable
.Select(x => caster(x))
.ToList();
}
}
像这样调用:
var branchList = GetList<Branch>("connectionStringName", x => (Branch)x);
您可以删除 .AsNoTracking() 并删除 .ToList(),那么你将得到纯 IQueryable,你可以进一步查询。
我创建了一种方法来包含所有相关实体,并借助@chiccodoro的出色答案。
使用具有 7 个导航属性的实体“Product”
public static IQueryable<T> IncludeAllEntities<T>(this DbSet<T> entity, DataContext context) where T : class
{
var queryable = entity.AsQueryable();
var type = typeof(T);
var entityType= context.Model.FindEntityType(type);
var navs = entityType?.GetNavigations();
if (navs == null)
{
return null;
}
List<string> navNames = new List<string>();
foreach (var nav in navs)
{
navNames.Add(nav.Name);
}
try
{
var agg = navNames.Aggregate(queryable, (acc, name) => acc.Include(name));
return agg;
}
catch (Exception ex)
{
throw;
}
}
我正在获取实体的类型以获取导航属性,然后将每个实体的名称添加到字符串列表中,然后聚合列表以包含每个实体。
然后我们可以像这样使用这个扩展方法:
var record = await _context.Products
.IncludeAllEntities(_context)
.FirstOrDefaultAsync(x => x.Id == key);
评论