Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何调用IDBSet<;T>;。使用反射的FirstOrDefault(谓词)?_C#_Entity Framework_Reflection - Fatal编程技术网

C# 如何调用IDBSet<;T>;。使用反射的FirstOrDefault(谓词)?

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

给定一个IDbSet,其中Person包含一个“Id”属性,我如何一般地执行以下命令:

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
将获取所有记录并在内存中筛选它们。感谢您捕获到这一点。。我已经更新了代码示例以反映其当前状态,包括扩展方法类型的更改,以及调用返回的错误消息。感谢您的关注!我已经更新了问题以反映当前代码状态和异常消息。请添加解决方案的简短说明,这不需要解析相当大的代码段。