2011-08-29 14 views
5

私はテーブルを持って、レコードと呼ぶことができます。含まれるもの: 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; 

これは動作しますが、それはメモリにデータベースからすべてのレコードをロードした後、各グループのちょうど最後の(最も最近のメンバー)を抽出しているため、非効率的です。

前述のSQLソリューションの効率性と可読性に近づくLINQソリューションはありますか?

+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レコードごとにDBにクエリを実行すると信じています。

は、あなたがこのような何かを行うことができます:あなたはそれがここに行く上での情報のためのクエリを実行するときに必ずする唯一の方法は、http://www.foliotek.com/devblog/tuning-sql-server-for-programmers/

オリジナル.. SQLトレーサーを実行するだろうか? 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

だから、私は、あなたが話していることとそのエラーを2つの大群で試してみました:Delegate System.Func 'は1つの引数を取っていません –

+0

現在のコンテキストに名前 'id'が存在しません –

+0

あなたがしようとしているものを手に入れましたが、動作させるために必要な変更を行うことができませんでした: –

1

私はgrp.LastOrDefault()は、C#の関数は、SQLは知らないものだと思います。 LINQは、クエリをデータベースサーバーが理解できるようにSQLクエリに変換します。代わりにストアドプロシージャを作成したり、探しているものをフィルタリングする別の方法を試してみてください。

LINQ to SQLがリストを返し、IEnumerable/IQueryableインターフェイスを実装し、grpを理解しているC#リストで(必要なものを除外するために)LINQクエリを実行するためです.LastOrDefault()。

+0

True、LastOrDefaultは、(エラーが示すように)MySQL Entity Frameworkプロバイダに実装されていません。 –

+0

うん、それはメモリコレクションとして長いリストを返します。メモリリストは、CustIDごとに1つのエントリにフィルタリングされ、メモリとプロセッサの使用には理想的ではありません。それは私がここで助けを求めている理由: –

1

LastOrDefault()を単純なLast()に置き換えるとどうなりますか? (はい、レコードテーブルが空でないことを確認する必要があります)

MySQLがあなたに「デフォルト」グループを返す方法がわかりません。これは単にSQLに変換できるものではありません。

+0

最後に私はこのエラーが表示されます:System.NotSupportedExceptionがユーザーコードによって処理されていません メッセージ= LINQ to Entitiesは、メソッド 'Faizan_Kazi_Utils.Record Last [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を実行しません。 Toall(ToList()、ToArray()、First()、Last()など)をリクエストする主な事柄は、私が重複している場合にはごめんなさい。とにかに私の答えは、あなたが必要とするものを正確に更新しました。それがあなたのために働くならば、私を答えとしてupvote /マークしてください!これは役に立ちましたか? – bigamil

+0

hmmm ...最初の.ToArrayは、2つの整数をメモリー(個別のcust id)にロードし、次に2番目のものを正確に(レコード全体をロードします。 ...それは大丈夫じゃない? –

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

これはすばらしかったです。 .. 良い成果! –

関連する問題