Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.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# IQueryable<;T>;。OrderBy<;T、 对象>;抛出:无法对类型';System.Int16';输入';System.Object';_C#_Linq_Entity Framework_Generics - Fatal编程技术网

C# IQueryable<;T>;。OrderBy<;T、 对象>;抛出:无法对类型';System.Int16';输入';System.Object';

C# IQueryable<;T>;。OrderBy<;T、 对象>;抛出:无法对类型';System.Int16';输入';System.Object';,c#,linq,entity-framework,generics,C#,Linq,Entity Framework,Generics,我们正在使用一个GenericCriteria类,该类用于查询IQueryable,而无需直接访问它。基本上,查询构建在“业务”层,并传递到“数据访问”层。为了防止重复,它需要尽可能通用 下面是GenericCriteria类的简化版本: public class GenericCriteria<T> { public Expression<Func<T, bool>> Where { get; set; } public Expression

我们正在使用一个GenericCriteria类,该类用于查询IQueryable,而无需直接访问它。基本上,查询构建在“业务”层,并传递到“数据访问”层。为了防止重复,它需要尽可能通用

下面是GenericCriteria类的简化版本:

public class GenericCriteria<T>
{
    public Expression<Func<T, bool>> Where { get; set; }
    public Expression<Func<T, object>> OrderBy { get; set; }
}
所以我现在想弄清楚的是如何让GenericCriteria类接受某种类型的泛型OrderBy构造,这样EF就可以完成它的任务了

我应该找什么

更新:

如果不清楚,我宁愿避免:

public class GenericCriteria<T, TKey>
{
    public Expression<Func<T, bool>> Where { get; set; }
    public Expression<Func<T, TKey>> OrderBy { get; set; }
}
公共类通用标准
{
公共表达式,其中{get;set;}
公共表达式OrderBy{get;set;}
}

因为类的用户可能并不总是想要订购,所以需要一个类型似乎有点脏。

我将重写以下条件

public class GenericCriteria<T>
{
     public List<Func<IQueryable<T>,IQueryable<T>>> 
          List { get; private set;}

     public GenericCriteria<T>(){
         List = new List<Func<IQueryable<T>,IQueryable<T>>>();
     }

}
公共类通用标准
{
公开名单
列表{get;private set;}
公共通用标准(){
列表=新列表();
}
}
决心

public static IQueryable<T> ResolveCriteria<T>(this IQueryable<T> 
       query, GenericCriteria<T> criteria)
{
    foreach(var exp in criteria.List){
       query = exp(query);
    }
    return query;
}
公共静态IQueryable ResolveCriteria(此IQueryable
查询,一般条件(标准)
{
foreach(criteria.List中的var exp){
query=exp(查询);
}
返回查询;
}
用法

var-criteria=新的GenericCriteria();
添加(q=>q.Where(c=>c.Age>20));
criteria.List.Add(q=>q.OrderBy(c=>c.Age));
var persons=Data.Instance.GetPersons(标准);

由于您不希望
GenericCriteria
有两个类型参数,而
OrderBy
坚持使用两个类型参数,因此最好的方法可能是在
ResolveCriteria
中执行一些脏活,如下所示:

public static IQueryable<T> ResolveCriteria<T>(this IQueryable<T> query, GenericCriteria<T> criteria)
{
  query = query.Where(criteria.Where);

  var t = criteria.OrderBy;
  var b = t.Body;
  if (b.NodeType == ExpressionType.Convert &&
      ((UnaryExpression)b).Type == typeof(Object)) {
    // Handle simple types, such as short, int, long, etc.
    var bb = ((UnaryExpression)b).Operand;
    var tt = Expression.Lambda(bb, t.Parameters);
    if (bb.Type == typeof(short))
      query = query.OrderBy((Expression<Func<T, short>>)tt);
    else if (bb.Type == typeof(int))
      query = query.OrderBy((Expression<Func<T, int>>)tt);
    else if (...)
      ...
  } else
    // Handle non-simple types, such as string.
    query = query.OrderBy(t);

  return query;
}
公共静态IQueryable ResolveCriteria(此IQueryable查询,GenericCriteria)
{
query=query.Where(criteria.Where);
var t=criteria.OrderBy;
var b=t.体;
if(b.NodeType==ExpressionType.Convert&&
((一元表达式)b).Type==typeof(对象)){
//处理简单类型,如short、int、long等。
var bb=((一元表达式)b).操作数;
var tt=表达式λ(bb,t.参数);
if(bb.Type==typeof(short))
query=query.OrderBy((表达式)tt);
else if(bb.Type==typeof(int))
query=query.OrderBy((表达式)tt);
否则如果(…)
...
}否则
//处理非简单类型,例如字符串。
query=query.OrderBy(t);
返回查询;
}

对于每个简单类型,您都需要一个“else-if”;幸运的是,数量不多。有关简单类型的列表,请参阅。

为什么您的orderBy接口属性不是泛型的?您是否有一个初始化/填充条件的示例?是否可以使用
dynamic
关键字?通过创建表达式,可以重写orderBy表达式以将强制类型转换为正确的类型访客,但这不是小事。我从来都不理解在堆栈中隐藏iQueryTables的驱动力,你只需要编写大量代码就可以得到一个残缺版本的Linqt。在.net中有一个名为ExpressionVisitor的基类,你可以继承它,它可以解析和重写表达式。您可以让它按表达式的顺序进行迭代,获得最终属性(可以按嵌套属性进行排序),确定其类型,然后将强制转换放入它生成的新表达式中,然后在OrderBy中使用它。这里有一个介绍,谢谢。我一直在玩弄这个想法(使用Func作为参数)。这种方法的缺点是,我需要引用实体框架,以便在System.Data.Entity中使用扩展方法“Include”。这不是最糟糕的问题,但更愿意避免。
public class GenericCriteria<T, TKey>
{
    public Expression<Func<T, bool>> Where { get; set; }
    public Expression<Func<T, TKey>> OrderBy { get; set; }
}
public class GenericCriteria<T>
{
     public List<Func<IQueryable<T>,IQueryable<T>>> 
          List { get; private set;}

     public GenericCriteria<T>(){
         List = new List<Func<IQueryable<T>,IQueryable<T>>>();
     }

}
public static IQueryable<T> ResolveCriteria<T>(this IQueryable<T> 
       query, GenericCriteria<T> criteria)
{
    foreach(var exp in criteria.List){
       query = exp(query);
    }
    return query;
}
var criteria = new GenericCriteria<Person>();
criteria.List.Add( q => q.Where( c => c.Age > 20) );
criteria.List.Add( q => q.OrderBy( c => c.Age ));

var persons = Data.Instance.GetPersons(criteria);
public static IQueryable<T> ResolveCriteria<T>(this IQueryable<T> query, GenericCriteria<T> criteria)
{
  query = query.Where(criteria.Where);

  var t = criteria.OrderBy;
  var b = t.Body;
  if (b.NodeType == ExpressionType.Convert &&
      ((UnaryExpression)b).Type == typeof(Object)) {
    // Handle simple types, such as short, int, long, etc.
    var bb = ((UnaryExpression)b).Operand;
    var tt = Expression.Lambda(bb, t.Parameters);
    if (bb.Type == typeof(short))
      query = query.OrderBy((Expression<Func<T, short>>)tt);
    else if (bb.Type == typeof(int))
      query = query.OrderBy((Expression<Func<T, int>>)tt);
    else if (...)
      ...
  } else
    // Handle non-simple types, such as string.
    query = query.OrderBy(t);

  return query;
}