【问题标题】:Entity Framework (Or Just Enumerable): Sort parent based on child collection property using reflection实体框架(或只是可枚举):使用反射根据子集合属性对父对象进行排序
【发布时间】:2014-05-22 19:45:17
【问题描述】:

我几乎一整天都在尝试使用反射根据 CHILD 集合属性对 PARENT 进行排序。

PS:我的子集合属性启用了延迟加载。

但现在,我被困住了。这是我到目前为止所取得的成就:

var query = myIQueryAbleVariable;

var collectionName = "MyCollectionName";
var collectionType = typeof (TEntity).GetProperty(collectionName).PropertyType;
var collectionItemType = collectionType.GetGenericArguments()[0];

var propertyName = "CollectionPropertyName";
var propertyInfo = collectionItemType.GetProperty(propertyName);

// Create a parameter to use for both of the expression bodies.
var parameter = Expression.Parameter(collectionItemType, "x");
Expression columnExpr = Expression.Property(parameter, propertyInfo);
var lambda = Expression.Lambda(columnExpr, parameter);

var selectMethod = typeof(Enumerable)
   .GetMethods(BindingFlags.Static | BindingFlags.Public)
   .FirstOrDefault(
      mi =>
         mi.Name == "Select" &&
         mi.GetParameters()[1].ParameterType.GetGenericArguments().Count() == 2);

// we need to specialize it 
selectMethod = selectMethod.MakeGenericMethod(collectionItemType, lambda.GetType());

query = query.OrderBy(p =>
   selectMethod.Invoke(null,
      new[] { p.GetType().GetProperty(collectionName).GetValue(p), lambda }));

它从数据库中获取数据。但是当它似乎处理 de order by (在内存中处理)时,我得到:

System.ArgumentException: Object of type 'System.Linq.Expressions.Expression`1[System.Func`2[Measure,System.Int32]]' cannot be converted to type 'System.Func`2[Measure,System.Linq.Expressions.Expression`1[System.Func`2[Measure,System.Int32]]]'.
   at System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast)
   at System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
   at System.Reflection.MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig)
   at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at lambda_method(Closure , Measure )
   at System.Linq.EnumerableSorter`2.ComputeKeys(TElement[] elements, Int32 count)
   at System.Linq.EnumerableSorter`1.Sort(TElement[] elements, Int32 count)
   at System.Linq.OrderedEnumerable`1.<GetEnumerator>d__0.MoveNext()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)

【问题讨论】:

  • 您能否提供一个类似于您的动态查询试图构建的静态查询示例?
  • 它完全是动态的。但是让我们尝试一下: var myIQueryAbleVariable= DbContext.Measure.Where(p => p.Market == "MarketGuid") 。考虑 IQueryable 或 IEnumerable 对象很有用。
  • 您的查询包含一个OrderBy 调用和一个Select。我根本看不到Where。我的意思是,您正在尝试构建对OrderBy 的调用,该调用也使用投影。如果您要对一个操作进行静态硬编码,它会是什么样子,当然要意识到对于您的项目,您需要能够动态地构造该查询。
  • 我假设 query 是一个来自 LINQ to Entities 的 IQueryable。这意味着您不能使用Invoke。您可能想改用this
  • @MarcoAlves 我知道它不起作用。我正在向您解释为什么它不起作用(顺便说一下,这就是为什么我建议先静态创建所有查询,然后再尝试动态创建它们)。您正在尝试根据整数序列进行排序。序列 {1, 7} 或序列 {2,5} 哪个更大?我不知道。 SQL 不知道。您的查询提供者不知道。您是否要根据所有优先级的 sum 进行排序,例如让 {1,7} 更大?

标签: c# .net linq entity-framework linq-to-sql


【解决方案1】:

基于@Servy cmets,我最终使用了IComparer。

【讨论】:

    猜你喜欢
    • 2011-03-29
    • 2019-08-27
    • 1970-01-01
    • 2021-07-16
    • 2017-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    相关资源
    最近更新 更多