LinQ OrderBy匿名值

时间:2013-03-05 14:10:30

标签: c# linq sql-order-by

以下代码无效:

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)会返回一个好的值。谁可以帮我这个事?提前谢谢。

2 个答案:

答案 0 :(得分:2)

答案是在错误中。您显然正在使用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语句中应用转换。

我怀疑上述效率非常低,但这只是猜测。

答案 1 :(得分:0)

有一种方法可以将这种函数嵌入到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服务器上执行,而无需将任何部分结果集实现到内存中。它应该非常高效,可以处理非常复杂的查询。我通常发现将逻辑封装到表达式中会导致简单的代码具有良好的可重用性。

我在一个项目中广泛使用它,它运作良好。你需要很好地掌握表达方式。