2010-12-03 15 views
1

もともと私はこのようなコードを持つ2つの結果セットをマージしたToList()を実行すると、なぜこのLINQ to SQLクエリが中断しますか?

var list1 = from a in IDataSourceObject 
      blahblah 
      select a; 

var list2 = from a in IDataSourceObject2 
      blahblah 
      select a;  

var joinedlist = from a in list1 
       join b in list2 on a.id = b.id 
       into fishcakes 
       from b in fishcakes.DefaultIfEmpty() 
       orderby b.ranking 
       select new { blah=cakes, etc. } 

は、これが正常に動作するために使用されるが、その後私はもう少し、リスト1をフィルタリングしたかったので、私はこれでした:

var list1 = from a in IDataSourceObject 
      blahblah 
      select a; 

// ToList required because im calling a method in my code 
var updatedList1 = from a in list1.ToList() 
        where myMethod(somestuff) == true 
        select a; 

var list2 = from a in IDataSourceObject2 
      blahblah 
      select a;  

var joinedlist = from a in updatedList1 
       join b in list2 on a.id = b.id 
       into fishcakes 
       from b in fishcakes.DefaultIfEmpty() 
       orderby b.ranking 
       select new { blah=cakes, etc. } 

しかし、私は本質的にOrderBy brankingがnullであると言っています。 ToListを実行した後に結果をマージすることはもうありません。私はupdatedList1をチェックして、myMethodを常にtrueにしました。本質的に問題はToList()を使用することから来ています。

遅延実行とは関係があると私は理解していますが、どのように控えめなアイデアは持っていません。それはまったく同じでなければなりません。

誰にも提案はありますか?

+0

を試してみてくださいするために、いくつかのaので、fishcakes.DefaultIfEmtpy()はnullを返すことができるためfishcakesが空であることができるようにすることで、遠方の方でメモリコレクションに参加するん念頭に置いてこれで解決策を探してみてください! –

答えて

6

fishcakes.DefaultIfEmpty()を呼び出すと、nullのコレクションを返すことができます。

.ToList()を呼び出すと、すべての現在の結果がローカル(.Net)オブジェクトにコピーされ、.ToList()以降のすべてのコマンドがプログラムで実行されます。

.Netコレクションに対してクエリを実行する場合、null.rankingを呼び出すと、NullReferenceExceptionがスローされます。一方、SQLではサブプロパティがnull(これは単にnullを返す)であるため、SQLでは実行が例外をスローしません。

はあなたの例では、例外を防ぐために:あなたは nullに等しい rankingを持っている、またはフィルタ項目のいずれかがこのような何かにあなたの

orderby b.ranking 

を置き換えることができます

orderby b != null ? b.ranking : -1 
(私は ranking仮定はintです)


同じ状況では、値がマテリアライズされています。例えば、(ItemCategory、または有していなくてもよいを有することができること、を前提と):

// this will work, because it's executed on SQL-side 
db.Items 
     .Select(x=>new { CatId = (int?)x.Category.Id, x.Id}) 
     .ToList(); 

// this will throw NullRefException, because it's executed against collection in .Net environment, not on SQL Server. 
db.Items 
     .ToList() 
     .Select(x=>new { CatId = (int?)x.Category.Id, x.Id}); 

PS:あなたはReSharperのを使用している場合、それはint?にキャストすることは必要ないことを、最初の例では文句を言うでしょう。それを信じてはいけない! )

0

ToListメソッドは、()のIQueryableされていない、IEnumerableを返すので

明確化:あなたは暗黙的のIQueryableを使用しているので、それらの選択は、加入して発注LINQ to SQLのを使用し

はSQLに変換されて実行されますDBサーバー上で実行します。しかし、updatedList1をListに変換すると、linq2sqlは文全体をSQLクエリに変換することができなくなり、通常のLinqと同様に文が1つずつ実行されます。だけでなく、いくつかのエラー(上記の答えで述べたNullReferenceExceptionのような)を導入するだけでなく、 "純粋な" linq2sql式よりもはるかに効率が悪いです。

+1

これはやや曖昧です。 –

+0

彼はどのIQueryable操作を使用しようとしていますか?私は 'from ... where ... select'がLINQメソッド呼び出しに変換される方法を忘れています。あなたは確か 'List <>'で '.Where()'を呼び出すことができます。 – Rup

+0

@Robert Harveyそうです。私は私の答えに少し明確化を加えました。 – buru

0

2つの異なる(互換性のない)タイプを結合しようとしているためです。 list2を取得して同様の操作を.ToList()実行すると、症状が緩和されます。

2

join intoは、SQLの左内ジョインに似ています。いくつかのa

var joinedlist = from a in updatedList1 
       join b in list2 on a.id = b.id 
       into fishcakes 
       from b in fishcakes 
       where b != null 
       orderby b.ranking 
       select new { blah=cakes, etc. } 
関連する問題