简体   繁体   English

LinQ OrderBy匿名值

[英]LinQ OrderBy anonymous value

Following code is not working: 以下代码不起作用:

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

Error: 错误:

Method 'Int32 GetNumberOfWinsByUser(Int32)' has no supported translation to SQL. 方法'Int32 GetNumberOfWinsByUser(Int32)'不支持SQL转换。

I know that SqlFactory.GetNumberOfWinsByUser(user.Id) returns a good value. 我知道SqlFactory.GetNumberOfWinsByUser(user.Id)返回一个好的值。 Can anyone help me on this? 谁可以帮我这个事? Thanks in advance. 提前致谢。

The answer is in the error. 答案出在错误中。 You are obviously using a linq providor such as entity framework that translates your linq into SQL. 显然,您正在使用linq提供程序,例如将您的linq转换为SQL的实体框架。 It can't translate the method SqlFactory.GetNumberOfWinsByUser(user.Id) into a SQL statement. 它无法将方法SqlFactory.GetNumberOfWinsByUser(user.Id)转换为SQL语句。 If you want to use it you will have to do something like : 如果要使用它,则必须执行以下操作:

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

That will force it to fetch the data into memory first and then apply the transform in your select statement. 这将迫使它先将数据提取到内存中,然后在您的select语句中应用转换。

I suspect that the above is very inefficient but that is just a guess. 我怀疑上面的方法效率很低,但这只是一个猜测。

There is a way to do this kind of embedding of functions into Linq2SQL queries, provided your function ( GetNumberOfWinsByUser() in your case) can itself be written as Expression<Func<>> type where the expression can be converted to SQL by the provider 只要您可以将函数(您的情况下为GetNumberOfWinsByUser() )本身编写为Expression<Func<>>类型,就可以通过这种方式将函数嵌入到Linq2SQL查询中,其中提供程序可以将表达式转换为SQL

This was devised by Tomáš Petříček and described on his blog: 这是由TomášPetříček设计的,并在他的博客中进行了描述:

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

It explains how you can defined an expression: 它说明了如何定义表达式:

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

and then embed that into a Linq to SQL query: 然后将其嵌入到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) };

Using an extension method ToExpandable() that he created (the code is available for download). 使用他创建的扩展方法ToExpandable() (可下载代码)。

This allows the entire query to be parsed into SQL and executed on the DB server without having to materialise any partial results sets into memory. 这允许将整个查询解析为SQL并在DB服务器上执行,而不必将任何部分结果集具体化到内存中。 It should be pretty efficient and can be made to handle very complex queries. 它应该非常有效,并且可以处理非常复杂的查询。 I generally found that encapsulating the logic into expressions liek this led to simple code with good re-usability. 我通常发现将逻辑封装到表达式中可以使代码简单且具有良好的可重用性。

I used this extensively in a project and it works very well. 我在项目中广泛使用了它,并且效果很好。 You need to have a good grasp of expressions though. 但是,您需要对表达式有很好的了解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM