C# 如何调用IDBSet<;T>;。使用反射的FirstOrDefault(谓词)?
给定一个IDbSet,其中Person包含一个“Id”属性,我如何一般地执行以下命令:C# 如何调用IDBSet<;T>;。使用反射的FirstOrDefault(谓词)?,c#,entity-framework,reflection,C#,Entity Framework,Reflection,给定一个IDbSet,其中Person包含一个“Id”属性,我如何一般地执行以下命令: var p = PersonDbSet.FirstOrDefault(i=>i.Id = 3); 我可以构建谓词,并获得对FirstOrDefault扩展方法的引用,但我似乎无法将其全部放在一起: 首先是谓词 ParameterExpression parameter = Expression.Parameter(entityType, "Id"); MemberExpression property
var p = PersonDbSet.FirstOrDefault(i=>i.Id = 3);
我可以构建谓词,并获得对FirstOrDefault扩展方法的引用,但我似乎无法将其全部放在一起:
首先是谓词
ParameterExpression parameter = Expression.Parameter(entityType, "Id");
MemberExpression property = Expression.Property(parameter, 3);
ConstantExpression rightSide = Expression.Constant(refId);
BinaryExpression operation = Expression.Equal(property, rightSide);
Type delegateType = typeof (Func<,>).MakeGenericType(entityType, typeof (bool));
LambdaExpression predicate = Expression.Lambda(delegateType, operation, parameter);
最后尝试执行该方法:
object retVal = genericMethod.Invoke(null, new object[] {dbSet, predicate});
MethodInfo genericMethod = method.MakeGenericMethod(entityType);
object retVal = genericMethod.Invoke(dbSet, new object[] {expr});
使用此消息引发ArgumentException:
“无法将'System.Reflection.RuntimePropertyInfo'类型的对象转换为'System.Linq.IQuerable'1[Person]类型。”
有什么想法吗?您必须制作该方法的通用版本:
object retVal = genericMethod.Invoke(null, new object[] {dbSet, predicate});
MethodInfo genericMethod = method.MakeGenericMethod(entityType);
object retVal = genericMethod.Invoke(dbSet, new object[] {expr});
顺便说一句,您是否应该尝试从
System.Linq.Queryable
获取方法System.Linq.Enumerable
是关于Linq to对象的,看起来您正在尝试调用数据库。我解决了这个问题。。我反射数据上下文以获取dbset,并返回属性信息而不是属性值
上面的代码现在非常有效。。谢谢大家的帮助 我也有同样的问题。这个代码也适用于我。希望这能帮助你
public async Task<Unit> Handle(UpdateCustomCommand<TType> request, CancellationToken cancellationToken)
{
//TODO: set access based on user credentials
var contextCollectionProp = _context.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.FirstOrDefault(e => e.PropertyType == typeof(DbSet<TType>));
if (contextCollectionProp == null)
{
throw new UnSupportedCustomEntityTypeException(typeof(TType), "DB Contexts doesn't contains collection for this type.");
}
var firstOrDefaultMethod = typeof(System.Linq.Queryable).GetMethods(BindingFlags.Static | BindingFlags.Public)
.FirstOrDefault(m => m.Name == "FirstOrDefault" && m.GetParameters().Count() == 2);
if (firstOrDefaultMethod == null)
{
throw new UnSupportedCustomEntityTypeException(typeof(TType), "Cannot find \"Syste.Linq.FirstOrDefault\" method.");
}
Expression<Func<TType, bool>> expr = e => request.Id.Equals(e.ID);
firstOrDefaultMethod = firstOrDefaultMethod.MakeGenericMethod(typeof(TType));
TType item = firstOrDefaultMethod.Invoke(null, new[] { contextCollectionProp.GetValue(_context), expr }) as TType;
if (item == null)
{
throw new NotFoundException(nameof(TType), request.Id);
}
//TODO: use any mapper instead of following code
item.Code = request.Code;
item.Description = request.Description;
await _context.SaveChangesAsync(cancellationToken);
return Unit.Value;
}
公共异步任务句柄(UpdateCustomCommand请求、CancellationToken CancellationToken)
{
//TODO:根据用户凭据设置访问权限
var contextCollectionProp=\u context.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.FirstOrDefault(e=>e.PropertyType==typeof(DbSet));
if(contextCollectionProp==null)
{
抛出新的不受支持的CustomEntityTypeException(typeof(TType),“DB上下文不包含此类型的集合。”);
}
var firstOrDefaultMethod=typeof(System.Linq.Queryable).GetMethods(BindingFlags.Static | BindingFlags.Public)
.FirstOrDefault(m=>m.Name==“FirstOrDefault”&&m.GetParameters().Count()==2);
if(firstOrDefaultMethod==null)
{
抛出新的不受支持的CustomEntityTypeException(typeof(TType),“找不到\”Syste.Linq.FirstOrDefault \“方法”);
}
表达式expr=e=>request.Id.Equals(e.Id);
firstOrDefaultMethod=firstOrDefaultMethod.MakeGenericMethod(typeof(TType));
TType item=firstOrDefaultMethod.Invoke(null,new[]{contextCollectionProp.GetValue(_context),expr})作为TType;
如果(项==null)
{
抛出新的NotFoundException(nameof(TType),request.Id);
}
//TODO:使用任何映射器而不是以下代码
item.Code=请求.Code;
item.Description=请求.Description;
wait_context.saveChangesSync(cancellationToken);
返回单位值;
}
您可能想从可查询
类中使用FirstOrDefault
,因为使用可枚举。FirstOrDefault
将获取所有记录并在内存中筛选它们。感谢您捕获到这一点。。我已经更新了代码示例以反映其当前状态,包括扩展方法类型的更改,以及调用返回的错误消息。感谢您的关注!我已经更新了问题以反映当前代码状态和异常消息。请添加解决方案的简短说明,这不需要解析相当大的代码段。