2011-08-29 30 views
5

我有一个表,可以称之为Record。包含: ID(int)| CustID(int)|时间(日期时间)|数据(VARCHAR)C#LINQ查询(MYSQL EF) - 独特和最新记录

我需要为每个客户的最新(最近)的记录:

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 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版本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解决方案的效率和可读性?

+0

您是如何实现Mysql + LINQ的。 DBSet是否支持Mysql?如果是这样,你可以说怎么样?我渴望达到这个目标,并在上周放弃了。 – prabhakaran

+0

我只需要核心点,至少在你放置连接字符串的地方。 – prabhakaran

回答

4

更新:

var results = (from rec in Record group rec by rec.CustID into grp 
    select new 
    { 
     CustID = grp.Key, 
     ID = grp.OrderByDescending(r => r.ID).Select(x => x.ID).FirstOrDefault(), 
     Data = grp.OrderByDescending(r => r.ID).Select(x => x.Data).FirstOrDefault() 
    } 
); 

所以我做了一个测试表,并写了一个LINQ - > SQL查询,会做正是你需要的。看看这个,让我知道你的想法。唯一要记住的是,如果这个查询是缩放的,我相信它会在select new中的分组后对每个CustID记录运行一次对数据库的查询。可以肯定的唯一方法是运行SQL跟踪程序,当你上到这里运行查询信息.. 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))

这都是伪代码,但希望你能明白这一点。

+0

好的,所以我尝试了你所说的,并在两个轮子上给出了错误:Delegate System.Func '不接受1个参数 –

+0

和在ID(ID)中给出:在当前上下文中不存在名称'id' –

+0

我得到你想要做的,但我一直无法做出所需的更改以使其工作:s –

1

我认为grp.LastOrDefault()是一个C#函数,它是SQL不知道的。 LINQ将您的查询转换为您的数据库服务器要理解的SQL查询。您可能想尝试创建存储过程,或者使用其他方法来筛选出您所需要的内容。

您的第二个查询工作原因是因为LINQ to SQL返回一个列表,然后在C#列表中执行LINQ查询(筛选出您需要的),该列表实现了IEnumerable/IQueryable接口并理解grp .LastOrDefault()。

+0

True,LastOrDefault未在MySQL实体框架提供程序中实现(如错误所示)。 –

+0

是的,它会返回一个长列表作为内存集合,然后每个CustID过滤掉单个条目,这对于内存和处理器使用情况来说并不理想。这就是为什么我在这里寻求帮助:) –

1

如果用简单的Last()替换LastOrDefault()会怎么样? (是的,你将不得不检查你的记录表是不是空的)

因为我看不到MySQL如何返回你的“默认”组。这不是可以简单地转换为SQL的东西。

+0

当我使用最后我得到这个错误:System.NotSupportedException被用户代码未处理 消息= LINQ到实体无法识别方法'Faizan_Kazi_Utils.Record最后[记录](系统.Collections.Generic.IEnumerable'1 [Faizan_Kazi_Utils.Record])'方法,并且此方法不能被转换为商店表达式。 Source = System.Data.Entity –

0

我有另一个想法:

// Get a list of all the id's i need by: 
// grouping by CustID, and then selecting Max ID from each group. 
var distinctLatest = (from x in ee.Records 
          group x by x.CustID into grp 
          select grp.Max(g => g.id)).ToArray(); 

// List<Record> result = new List<Record>(); 

//now we can retrieve individual records using the ID's retrieved above 
// foreach (int i in distinctLatest) 
// { 
// var res = from g in ee.Records where g.id == i select g; 
// var arr = res.ToArray(); 
// result.Add(res.First()); 
// } 

// alternate version of foreach 
dgvLatestDistinctRec.DataSource = from g in ee.Records 
              join i in distinctLatest 
              on g.id equals i 
              select g; 
+0

这是有点基于bigamils解决方案...它在我的脑海中产生了这种思想流 –

+0

你真的不想这样做.ToArray()或ToList(),因为这将返回所有记录并将它们放入记忆。你希望Linq - > SQL来完成所有的工作。基本上它构建了一个动态表达式树,在你请求一个值之前,它并没有真正执行任何SQL。关键的东西,请求瓦尔(ToList(),ToArray(),First(),Last()等)抱歉,如果我是多余的。无论如何更新我的答案,以做到你所需要的。如果它适合您,请将我的评价/标记为答案!希望这有帮助 – bigamil

+0

嗯......但第一个.ToArray只是加载一对夫妇整数内存(独特的客户ID),然后第二个正是我所需要的(加载整个记录:每个不同客户的最新记录) ...不好吗? –

2

我可能为时已晚,以帮助您的问题,但我也有类似的问题,并能够与这样的查询,以获得期望的结果:

from g in ee.Records 
group g by g.CustID into grp 
from last in (from custRec in grp where custRec.Id == grp.Max(cr => cr.Id) select custRec) 
select last 
+0

这太棒了。 .. 很好的表现! –