使用Entity Framework 5时,为什么会这样?
var query = Categories.Select(c => new
{
Products = c.Products.OrderBy(p => p.Name)
});
虽然这不会?
Func<Product, string> selector = p => p.Name;
var query = Categories.Select(c => new
{
Products = c.Products.OrderBy(selector)
});
引发的异常是:用于查询运算符'OrderBy'的不支持的重载。
答案 0 :(得分:6)
query
变量名称暗示您可能正在使用Entity Framework,LINQ to SQL或其他基于IQueryable<T>
的API。您将selector
作为Func
传递。基础查询提供程序无法将Func
转换为SQL(或任何其他语言,无论您使用何种语言)。
将selector
的类型更改为Expression<Func<Product, string>>
(其余的可以保持不变,因为lambda表达式可以解释为委托或表达式树。这就是为什么你可以使用{{1}使用lambdas - 编译器无法判断您是否希望lambda成为委托或表达式树)并查看是否可以解决您的问题。你没有提供足够的信息让我100%肯定,但它应该。接受var
的{{1}}重载应该能够遍历表达式树并将其转换为基础查询。这有点猜测,但我希望它可以帮助你。
答案 1 :(得分:0)
以下是查询正常工作并且不会导致问题的工作示例。为简单起见,我跳过数据库,直接转到内存中的对象,这可能就是为什么它对我有用。我认为Honza是对的,这是与ORM层相关的问题。您可以运行以下示例
这是linqpad的一个例子:
void Main()
{
var Categories = new List<Category>() { new Category { CategoryName = "CatName", Products = new List<Product>() { new Product { Name = "ProductName1" } } } };
Func<Product, string> selector = p => p.Name;
var sb = new StringBuilder();
var query = Categories.Select(c => new
{
Products = c.Products.OrderBy(selector)
});
foreach (var x in query)
{
sb.AppendLine(x.Products.First().Name);
}
Console.WriteLine(sb.ToString());
Console.Read();
}
public class Product
{
public string Name { get; set; }
}
public class Category
{
public string CategoryName { get; set; }
public List<Product> Products { get; set; }
}
//在此定义其他方法和类
以下是visual studio console app的版本:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var Categories = new List<Category>() { new Category { CategoryName = "CatName", Products = new List<Product>() { new Product { Name = "ProductName1" } } } };
Func<Product, string> selector = p => p.Name;
var sb = new StringBuilder();
var query = Categories.Select(c => new
{
Products = c.Products.OrderBy(selector)
});
foreach (var x in query)
{
sb.AppendLine(x.Products.First().Name);
}
Console.WriteLine(sb.ToString());
Console.Read();
}
public class Product
{
public string Name { get; set; }
}
public class Category
{
public string CategoryName { get; set; }
public List<Product> Products { get; set; }
}
}
}
答案 2 :(得分:0)
使selector
成为Expression<Func<Product, string>>
将无法直接生效,因为c.Products
不是IQueryable<T>
而无法编译。它只是一个仅实现IEnumerable<T>
的集合类型。 Enumerable.OrderBy
不接受表达式作为参数,只接受委托。
但EF仍然需要一个表达,而不是代表。诀窍是在导航集合上使用AsQueryable()
:
Expression<Func<Product, string>> selector = p => p.Name;
var query = Categories.Select(c => new
{
Products = c.Products.AsQueryable().OrderBy(selector)
});