2012-08-26 21 views
5

私はlinqを初めて使っています。linq join on guidと文字列

 using (CommentEntities db = new CommentEntities()) 
     { 
      // filteredComments is a query that is not run until the next .ToList() 
      IQueryable<Comment> filteredComments = this.CommentGetList(...); 
      var query = from comment in filteredComments 
         // following line is the syntax error, because columns' types don't match 
         join user in db.AnonymousUsers on comment.UserId equals user.AnonymousId into gj 
         from userNull in gj.DefaultIfEmpty() 
         select new CommentWithName 
         { 
          Comment = comment, 
          UserId = comment.UserId, 
          FirstName = (userNull == null ? "" : userNull.Name), 
          LastName = "", 
          Email = (userNull == null ? "" : userNull.Email) 
         }; 
      return query.ToList(); 
     } 

まず私は.ToString()でクエリを書いて幸せだった:私は2つの列(AnonymousUser.AnonymousIduniqueidentifierいるとcomment.UserIdはnvarchar(100)ている)を結合し、以下のようなものは、クエリを実行する必要があります!エンティティ・フレームワークはそれをSQLに変換する方法を知らないことが判明しました。 Guid.Parse(string)についても同様です。また、new Guid(string)は、エンティティへのlinqでは使用できません(パラメータのないコンストラクタのみが許可されます)!

検索後、私はEF 4.0でそのようなことをすることができないことを知った!私は自分のコードをストアドプロシージャに移行しました。私は実際にそれについて幸せではありません。

エンティティフレームワークにCASTをSQLで使用するように指示できますか?

この問題の解決方法はありますか?ロジックをコードで実現できる方法はありますか?

:私はでこれを行うことを意味しました。GO。そうしないと、最初のテーブルからEntitiesを取得し、そのIDをリストに入れて、2番目のテーブルからエンティティを取得します。

+0

'comment.UserId'がGUIDの文字列表現である場合、その列を一意の識別子に変換する方が簡単でしょうか?これは、Entity FrameworkでSQLでこのキャストを実行しようとするよりも優れたソリューションです。 – mclark1129

+0

残念ながら、必ずしもGUIDというわけではありません。ユーザのタイプに基づいて、 'Guid'または' int'であるかもしれません。 – Ashkan

+0

'new Guid(string)'の代わりに['Guid.Parse(string)'](http://stackoverflow.com/a/8067647/484214)を試しましたか? –

答えて

0

これらのメソッドを適用する前にtoList()を呼び出します。同様に:

var Product = db.Products.Where(p => p.ProductId == Guid.Parse("B4E913F9-166C-49BA-AADE-6DB889D1756F")).Single(); 

はメソッド「可能System.Guid解析」(可能System.String)」メソッドを、認識していない事業​​体へ

C#のLINQを投げるだろうし、この方法は、ストアに翻訳することはできません表現

しかし、これは動作します:

var Product = db.Products.ToList().Where(p => p.ProductId == Guid.Parse("B4E913F9-166C-49BA-AADE-6DB889D1756F")).Single() 

PSは:私はあなたを考えますlazyloadingが失われますが、.ToList()を呼び出す前に.Includeを使ってeagerloadingを行うことができます。

+0

リレーションを持たない2つのテーブルに適用できる場合は、熱心なローディングを使用することをお勧めします。 P.S:コメントと匿名ユーザーのテーブルの間には関係がありません – Ashkan

+2

このオプションを使用すると、リスト全体がメモリに保存されます。製品のテーブルが小さい場合にのみこれを実行します。 –

+0

コメントのテーブルは非常に大きいテーブルです... – Ashkan

0

あなたlistは文句を言わないの参加で含まれ、あなたがタイプintであるUserId必ず、最初UserIdにそれをベースにフィルタを適用し、新しい匿名型を作成して、識別子としてGUIDを持つ型に変換可能性がオブジェクトリストの場合:

 int output = 0; 

    var secondList = list.Where(x=>!int.TryParse(x.UserID, out output)) 
        .Select(x=>new {Comment = x, ID = new Guid(x.UserID)) 
        .ToList(); 

secondListを使用してdbをクエリできました。

+0

'list'は' IQueryable '型であるとは言及していませんでした。 – Ashkan

+1

それはdb項目だということですが、この場合はストアドプロシージャを使用するように指定します。 –

+0

+1。それではEFがこれを行う方法はないと思いますか? EFの新しいバージョンはどうですか? – Ashkan