如何在EntityFramework中按动态列名排序?

16
我正在尝试让以下代码正常运行,它在使用MSSQL时很好用,但是自从我改用了MySQL就不起作用了。
  records.Content = db.areas
                         .Where(x =>   x.Name.Contains(filter)))
                         .OrderBy("dated desc") 
                         .ToList();

我收到了错误信息:"无法加载一个或多个请求的类型。请检索LoaderExceptions属性以获取更多信息。"

string colName = "datedD" ; 

如何根据colName变量进行排序?


3
我猜你所指的“string version”是所谓的“动态LINQ”(或System.Linq.Dynamic)。请添加 dynamic-linq 标签并相应更新问题。 - Ivan Stoev
@Kas,你能否帮我检查一下我的答案,因为它似乎是这个问题的更好方法;D - S.Serpooshan
尝试使用这个库 Entity Framework Plus Library - Linq-Dynamic。你也可以查看我的答案。 - Ben.S
4个回答

63
在 .Net Core 中,我们可以使用 EF.Property 方法将属性名指定为字符串:
string sortColumn = "Price";

//IQueryable<Product> q = from p in myDbContext.Products select p;
q = q.OrderBy(p => EF.Property<object>(p, sortColumn));

4
应该接受此答案。 - Desolator
如果您没有使用 .Net Core,请查看 @Taher Rahgooy 的答案 这里 - Ben.S

4

试试这个

string filterString = "dated";
bool isAscSorting = false;

Func<dynamic, dynamic> orderingFunction = i =>
                                filterString == "dated" ? i.dated :
                                filterString == "something" ? i.columnx : "";

records.Content = (isAscSorting) ?
                      db.areas
                         .Where(x =>   x.Name.Contains(filter)))
                         .OrderBy(orderingFunction) 
                         .ToList()
                   :
                        db.areas
                         .Where(x =>   x.Name.Contains(filter)))
                         .OrderByDescending(orderingFunction) 
                         .ToList();

有没有可能停止这段代码的重复? db.areas .Where(x => x.Name.Contains(filter))) - Kas
你不能使用这个答案,但是你可以使用动态LINQ。它比较复杂。 - NEER
@Kas,你可以将 db.areas.Where(x => x.Name.Contains(filter)) 的结果放入本地变量 var query = ... 中,然后使用 query = (isAscSorting) ? query.OrderBy(...) : query.OrderByDescending(...) - Evgeny Nozdrev

3

我使用了@NEER和@S.Serpooshan的两种答案的混合来避免使用LINQ查询

IQueryable<area> filteredItems = db.areas.Where(x =>   x.Name.Contains(filter)));
IQueryable<area> orderedItems;
if (IsAscending)
{
    orderedItems = filteredItems.OrderBy(item => typeof(area).GetProperty(colName).GetValue(item).ToString());
}
else
{
    orderedItems = filteredItems.OrderByDescending(item => typeof(area).GetProperty(colName).GetValue(item).ToString());
}

不好的地方在于 - 我的代码将项目比较为字符串。我没有时间使其更加"类型友好",但我相信这是可能的。


1
这是正确的答案。另外,可以使用Item => Item.GetType()代替item => typeof(area)。 - Rouzbeh Zarandi

2

对于动态排序,我发现最方便的方法是:

string propertyNameForOrdering = "UserName";

var list = context.Customers.OrderByDescendingDynamic(x => "x." + propertyNameForOrdering).ToList(); // DESC

var list = context.Customers.OrderByDynamic(x => "x." + propertyNameForOrdering).ToList(); // ASC

Entity Framework Plus Library - Linq-Dynamic

即使是商业用途,该功能也是免费的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接