LinQ OrderBy anonymous value

本文关键字:value anonymous OrderBy LinQ | 更新日期: 2023-09-27 18:02:13

下面的代码不能运行:

var x = from user in db.tblUsers
        select new
        {
            user.Id,
            user.FirstName,
            user.LastName,
            NumOfWins = SqlFactory.GetNumberOfWinsByUser(user.Id)
        };
TblBindingSource.DataSource = x.OrderByDescending(user => user.NumOfWins);
dataGridView1.DataSource = TblBindingSource.DataSource; //<-- fail here
错误:

方法'Int32 GetNumberOfWinsByUser(Int32)'不支持翻译成SQL

我知道SqlFactory.GetNumberOfWinsByUser(user.Id)返回一个好值。有人能帮我一下吗?

LinQ OrderBy anonymous value

答案在错误中。很明显,您正在使用linq提供程序,例如将linq转换为SQL的实体框架。它不能将SqlFactory.GetNumberOfWinsByUser(user.Id)方法转换为SQL语句。如果你想使用它,你必须这样做:

from user in db.tblUsers.ToList()
          select new { user.Id, user.FirstName, user.LastName, NumOfWins =     SqlFactory.GetNumberOfWinsByUser(user.Id) };

这将强制它首先将数据读取到内存中,然后在select语句中应用转换。

有一种方法可以将这种函数嵌入到Linq2SQL查询中,前提是您的函数(在您的情况下为GetNumberOfWinsByUser())本身可以编写为Expression<Func<>>类型,其中表达式可以由提供者转换为SQL

这是由Tomáš Petříček设计并在他的博客中描述的:

http://tomasp.net/blog/dynamic-linq-queries.aspx

它解释了如何定义表达式:

Expression<Func<Nwind.Product, decimal?>> calcPrice = 
  (p) => p.UnitPrice * 1.19m;

,然后嵌入到Linq to SQL查询中:

var q = 
   from p in db.Products.ToExpandable()  
   where calcPrice.Expand(p) > 30.0m
   select new { 
     p.ProductName, 
     OriginalPrice = p.UnitPrice,
     ShopPrice = calcPrice.Expand(p) };

使用他创建的扩展方法ToExpandable()(可以下载代码)。

这允许整个查询被解析成SQL并在DB服务器上执行,而不必将任何部分结果集具体化到内存中。它应该非常高效,可以处理非常复杂的查询。我通常发现,将逻辑封装到像这样的表达式中可以使代码简单,并且具有良好的可重用性。

我在一个项目中广泛使用它,它工作得很好。但是,您需要很好地掌握表达式。