C# LINQ 查询 (MYSQL EF) - 不同记录和最新记录
我有一张桌子,我们称之为记录。包含: ID(整数)| CustID(整数)|时间(日期时间)|数据 (varchar)
我需要每个客户的最新(最新)记录:
SQL
select * from record as i group by i.custid having max(id);
LINQ 版本 1
dgvLatestDistinctRec.DataSource = from g in ee.Records
group g by g.CustID into grp
select grp.LastOrDefault();
这会引发错误:
System.NotSupportedException 未由用户代码 Message=LINQ 处理 实体无法识别方法“Faizan_Kazi_Utils.Record” 最后或默认[记录 ](System.Collections.Generic.IEnumerable`1[Faizan_Kazi_Utils.Record ])'方法,并且该方法不能翻译成store 表达。来源=System.Data.Entity
LINQ 版本 2
var list = (from g in ee.Records
group g by g.CustID into grp
select grp).ToList();
Record[] list2 = (from grp in list
select grp.LastOrDefault()).ToArray();
dgvLatestDistinctRec.DataSource = list2;
这可以工作,但效率很低,因为它将数据库中的所有记录加载到内存中,然后仅提取每个组的最后一个(最新成员)。
是否有任何 LINQ 解决方案可以达到上述 SQL 解决方案的效率和可读性?
I have a table, lets call it Record. Containing:
ID (int) | CustID (int) | Time (datetime) | Data (varchar)
I need the latest (most recent) record for each customer:
SQL
select * from record as i group by i.custid having max(id);
LINQ version 1
dgvLatestDistinctRec.DataSource = from g in ee.Records
group g by g.CustID into grp
select grp.LastOrDefault();
This throws an error:
System.NotSupportedException was unhandled by user code Message=LINQ
to Entities does not recognize the method 'Faizan_Kazi_Utils.Record
LastOrDefault[Record
](System.Collections.Generic.IEnumerable`1[Faizan_Kazi_Utils.Record
])' method, and this method cannot be translated into a store
expression. Source=System.Data.Entity
LINQ version 2
var list = (from g in ee.Records
group g by g.CustID into grp
select grp).ToList();
Record[] list2 = (from grp in list
select grp.LastOrDefault()).ToArray();
dgvLatestDistinctRec.DataSource = list2;
This works, but is inefficient because it loads ALL records from the database into memory and then extracts just the last (most recent member) of each group.
Is there any LINQ solution that approaches the efficiency and readability of the mentioned SQL solution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
更新:
所以我做了一个测试表并写了一个 Linq -> SQL 查询将完全满足您的需要。看看这个,让我知道你的想法。唯一要记住的是,如果此查询是缩放的,我相信它将在 select new 中分组后对每个 CustID 记录运行对数据库的查询。唯一可以确定的方法是在运行查询以获取信息时运行 SQL Tracer。http://www.foliotek.com/devblog/tuning-sql-server-for-programmers/
原文:
你能做这样的事情吗?
from g in ee.Records where g.CustID == (from x in ee.Records where (g.CustID == x.CustID) && (g.ID == x.Max(ID)) .Select(r => r.CustID))
这都是伪代码,但希望您能明白。
Update:
So I made a test table and wrote a Linq -> SQL Query that will do exactly what you need. Take a look at this and let me know what you think. Only thing to keep in mind if this query is scaled I believe it will run a query to the DB for each and every CustID record after the grouping in the select new. The only way to be sure would be to run SQL Tracer when you run the query for info on that go here .. http://www.foliotek.com/devblog/tuning-sql-server-for-programmers/
Original:
Could you do something like this?
from g in ee.Records where g.CustID == (from x in ee.Records where (g.CustID == x.CustID) && (g.ID == x.Max(ID)).Select(r => r.CustID))
That's all pseudo code but hopefully you get the idea.
我可能来不及帮助解决您的问题,但我遇到了类似的问题,并且能够通过如下查询获得所需的结果:
I'm probably too late to help with your problem, but I had a similar issue and was able to get the desired results with a query like this:
如果用简单的 Last() 替换 LastOrDefault() 会怎样?
(是的,你必须检查你的记录表不为空)
因为我看不出MySQL如何返回你的“默认”组。这不是简单翻译成SQL就可以的事情。
What if you replace LastOrDefault() with simple Last()?
(Yes, you will have to check your records table isn't empty)
Because I can't see a way how MySQL can return you "Default" group. This is not the thing that can be simply translated to SQL.
我认为 grp.LastOrDefault() 这个 C# 函数是 SQL 不知道的。 LINQ 将您的查询转换为 SQL 查询,以便数据库服务器理解。您可能想尝试创建一个存储过程,或者使用其他方法来过滤掉您要查找的内容。
第二个查询有效的原因是 LINQ to SQL 返回一个列表,然后您在 C# 列表上执行 LINQ 查询(以过滤出您需要的内容),该列表实现 IEnumerable/IQueryable 接口并理解 grp.LastOrDefault() 。
I think grp.LastOrDefault(), a C# function, is something that SQL doesn't know about. LINQ turns your query into an SQL query for your db server to understand. You might want to try and create an stored procedure instead, or another way to filter out what your looking for.
The reason your second query works is because the LINQ to SQL returns a list and then you do a LINQ query (to filter out what you need) on a C# list, which implements the IEnumerable/IQueryable interfaces and understands the grp.LastOrDefault().
我有另一个想法:
I had another idea: