按 ICollection 属性 排序,使用动态 Linq 库的名称作为字符串
Ordering by ICollection property using its name as string with Dynamic Linq Library
我几乎搜索了所有我能找到的问题、博客或文档来帮助我找到这个问题的答案。一些实际上帮助我更接近它,但我还没有解决它,因为大多数要么已经过时,要么没有真正满足我的需要。不要费心告诉我有关表达式的信息,因为如果我走更长的路,我就不会使用这个库了。
我的项目目标是通过使用通用方法,仅使用 tables/columns 名称字符串和用于过滤的值来提供过滤和排序。长话短说,我有两个表,1对n的关系,基本上是这样连接的,我想按客户的名字订购:
public partial class Transactions{
public ICollection<Customer> customer { get; set; };
}
public partial class Customer{
public string name { get; set; };
}
到目前为止,除了弄清楚如何正确构建 OrderBy 字符串之外,我还有很多我需要实现的目标,以某种方式我会使用单个 ICollection 结果。
到目前为止我所拥有的大致如下(抱歉我的文档过于冗长):
using System.Linq.Dynamic;
using System.Reflection;
namespace com.betha.common
{
public class Filter
{
/// <summary>
/// Dictionary of codenames and column names populated by a different, specific class (properties.Add("customer", "tb_customer.name"))
/// </summary>
public Dictionary<string, string> properties;
public Filter(Dictionary<string, string> properties)
{
this.properties = properties;
}
/// <summary>
/// Generic method designed to filter and order using just lists of column names and values
/// </summary>
/// <typeparam name="T">Type of the first IQueryable</typeparam>
/// <typeparam name="T2">Type of the second IQueryable</typeparam>
/// <param name="query">IQueryable containing the results from the parent table (context.table1).AsQueryable();</param>
/// <param name="query2">IQueryable containing a single result from a descendant table (context.table2.Select(t2 => t2.field).FirstOrDefault()).AsQueryable();</param>
/// <param name="prop">Property codename that if used, matches a properties codename Key</param>
/// <param name="descend">Condition for ascending or descending results</param>
/// <returns>Ordered and/or filtered IQueryable</returns>
public IQueryable<T> FilterandOrder<T, T2>(IQueryable<T> query, IQueryable<T2> query2, string prop = null, string descend = null)
{
if (!String.IsNullOrEmpty(prop))
{
foreach (KeyValuePair<string, string> item in properties)
{
if (prop == item.Key)
{
prop = item.Value;
}
}
T2 subprop = query2.FirstOrDefault();
if (prop.Contains("."))
{
switch (prop.Split('.'))
{
default:
PropertyInfo property = subprop.GetType().GetProperty(prop.Split('.')[1]);
ParameterInfo[] index = property.GetIndexParameters();
object value = subprop.GetType().GetProperty(prop.Split('.')[1]).GetValue(subprop, index);
//This is the main issue, I have pretty much everything I should need, but I can't imagine how to write this OrderBy string properly.
//If I were to do it without the library: table.OrderBy(t => t.table2.Select(t2 => t2.field).FirstOrDefault());
//Without ordering by an ICollection property, like in the else below, string should look like: "field".
//Or in case of a 1 to 1 relationship, "table2.field".
query = DynamicQueryable.OrderBy(query, prop + (descend == "dec" ? " descending" : ""), value);
break;
}
}
else
{
query = DynamicQueryable.OrderBy(query, prop + (descend == "dec" ? " descending" : ""));
}
}
return query;
}
}
}
您可以用支持的函数替换 t => t.table2.Select(t2 => t2.field).FirstOrDefault()
,Min()
:
OrderBy("table2.Min(field)");
我几乎搜索了所有我能找到的问题、博客或文档来帮助我找到这个问题的答案。一些实际上帮助我更接近它,但我还没有解决它,因为大多数要么已经过时,要么没有真正满足我的需要。不要费心告诉我有关表达式的信息,因为如果我走更长的路,我就不会使用这个库了。
我的项目目标是通过使用通用方法,仅使用 tables/columns 名称字符串和用于过滤的值来提供过滤和排序。长话短说,我有两个表,1对n的关系,基本上是这样连接的,我想按客户的名字订购:
public partial class Transactions{
public ICollection<Customer> customer { get; set; };
}
public partial class Customer{
public string name { get; set; };
}
到目前为止,除了弄清楚如何正确构建 OrderBy 字符串之外,我还有很多我需要实现的目标,以某种方式我会使用单个 ICollection 结果。
到目前为止我所拥有的大致如下(抱歉我的文档过于冗长):
using System.Linq.Dynamic;
using System.Reflection;
namespace com.betha.common
{
public class Filter
{
/// <summary>
/// Dictionary of codenames and column names populated by a different, specific class (properties.Add("customer", "tb_customer.name"))
/// </summary>
public Dictionary<string, string> properties;
public Filter(Dictionary<string, string> properties)
{
this.properties = properties;
}
/// <summary>
/// Generic method designed to filter and order using just lists of column names and values
/// </summary>
/// <typeparam name="T">Type of the first IQueryable</typeparam>
/// <typeparam name="T2">Type of the second IQueryable</typeparam>
/// <param name="query">IQueryable containing the results from the parent table (context.table1).AsQueryable();</param>
/// <param name="query2">IQueryable containing a single result from a descendant table (context.table2.Select(t2 => t2.field).FirstOrDefault()).AsQueryable();</param>
/// <param name="prop">Property codename that if used, matches a properties codename Key</param>
/// <param name="descend">Condition for ascending or descending results</param>
/// <returns>Ordered and/or filtered IQueryable</returns>
public IQueryable<T> FilterandOrder<T, T2>(IQueryable<T> query, IQueryable<T2> query2, string prop = null, string descend = null)
{
if (!String.IsNullOrEmpty(prop))
{
foreach (KeyValuePair<string, string> item in properties)
{
if (prop == item.Key)
{
prop = item.Value;
}
}
T2 subprop = query2.FirstOrDefault();
if (prop.Contains("."))
{
switch (prop.Split('.'))
{
default:
PropertyInfo property = subprop.GetType().GetProperty(prop.Split('.')[1]);
ParameterInfo[] index = property.GetIndexParameters();
object value = subprop.GetType().GetProperty(prop.Split('.')[1]).GetValue(subprop, index);
//This is the main issue, I have pretty much everything I should need, but I can't imagine how to write this OrderBy string properly.
//If I were to do it without the library: table.OrderBy(t => t.table2.Select(t2 => t2.field).FirstOrDefault());
//Without ordering by an ICollection property, like in the else below, string should look like: "field".
//Or in case of a 1 to 1 relationship, "table2.field".
query = DynamicQueryable.OrderBy(query, prop + (descend == "dec" ? " descending" : ""), value);
break;
}
}
else
{
query = DynamicQueryable.OrderBy(query, prop + (descend == "dec" ? " descending" : ""));
}
}
return query;
}
}
}
您可以用支持的函数替换 t => t.table2.Select(t2 => t2.field).FirstOrDefault()
,Min()
:
OrderBy("table2.Min(field)");