2015-09-24 10 views
5

に私は、しかし、私は私の問題に答えを適用する方法を動作するように見えることはできません、同様の質問にいくつか答えを見てきました。条件は、(インクルード)Entity Frameworkの

var allposts = _context.Posts 
      .Include(p => p.Comments) 
      .Include(aa => aa.Attachments) 
      .Include(a => a.PostAuthor) 
      .Where(t => t.PostAuthor.Id == postAuthorId).ToList(); 

アタッチメントは、作成者(タイプ著者)またはコントリビュータ(タイプコントリビュータ)によってアップロードできます。私がしたいのは、添付ファイルの所有者がAuthorタイプの添付ファイルのみです。

私は、これは動作しません知っているとエラーを与える:

.Include(s=>aa.Attachments.Where(o=>o.Owner is Author)) 

私はここにフィルタリングされた投影について読んだ

EDIT - 記事へのリンク: :http://blogs.msdn.com/b/alexj/archive/2009/10/13/tip-37-how-to-do-a-conditional-include.aspx

が、私はちょうどそれの周りに私の頭を得ることができません。

私はすべての投稿をしたいが、私は著者に属し、それらの記事のために、添付ファイルを取得すると、最終的なwhere句でフィルタを含める必要はありません。

EDIT 2: - プロパティにポストスキーマはInclude()

public abstract class Post : IPostable 
{ 

    [Key] 
    public int Id { get; set; } 

    [Required] 
    public DateTime PublishDate { get; set; } 

    [Required] 
    public String Title { get; set; } 

    [Required] 
    public String Description { get; set; } 

    public Person PostAuthor { get; set; } 
    public virtual ICollection<Attachment> Attachments { get; set; } 
    public List<Comment> Comments { get; set; } 
} 
+0

私たちに 'Posts'スキーマを教えてもらえますか? – DarkKnight

+0

@DarkKnight - 編集を参照してください – grayson

+0

@graysonあなたがしたいことはできません。 'Linq2Sql'はあなたのコードを生の' SQL'に変換し、結合を介して子の行を返します。このような条件付き結合を 'SQL'で行うことはできません。あなたの唯一のオプションは、 '.Include(aa => aa.Attachments)'を削除し、所有者が著者/寄稿者であるかどうかによって添付ファイルを返す2番目のクエリです。 – Rob

答えて

5

。この場合、Post-Attachmentは1対多の関係である必要がありますので、完全に適用可能です。ここであなたが持つべきクエリは次のとおりです。

//this should be disabled temporarily 
_context.Configuration.LazyLoadingEnabled = false; 
var allposts = _context.Posts.Where(t => t.PostAuthor.Id == postAuthorId) 
         .Select(e => new { 
          e,//for later projection 
          e.Comments,//cache Comments 
          //cache filtered Attachments 
          Attachments = e.Attachments.Where(a => a.Owner is Author), 
          e.PostAuthor//cache PostAuthor 
         }) 
         .AsEnumerable() 
         .Select(e => e.e).ToList(); 
+0

"_context.Configuration.LazyLoadingEnabled = true;"を追加する必要がありますか?この呼び出しの後に読み込み可能な遅延ロードに? – grayson

+0

@graysonはい、それを再び有効にしたい場合。 – Hopeless

0

ラムダを要求したことが唯一のポイント:Include()joinとあなたを意味するので

.Include(a => a.Attachments) 
.Include(a => a.Attachments.Owner); 

あなたの条件は私のために理にかなっていませんそれをするかしない。条件付きではありません。あなたは生のSQLでこれを書くとどのように


なぜだけではなく、この:

context.Attachments 
     .Where(a => a.Owner.Id == postAuthorId && 
        a.Owner.Type == authorType); 

?あなたは、私がそのトリック作品を確認するだけで1対多数(または多対1)関係のためにできる投稿のリンクから

+0

ありがとうございます。私はこのすべてにかなり新しいです。私は希望のタイプの添付ファイルを取得するためにそれを行うことができますが、私はどのようにPostにそれをマージするのか分かりません。私のDisplayTemplateはPostから派生し、Post.Attachmentsを表示します – grayson

3

あなたが(例えば)拡張メソッドのthis implementationを使用することができますInclude2()。その後、あなたが呼び出すことができます。

_context.Posts.Include2(post => post.Attachments.Where(a => a.OwnerId == 1)) 

上記のコードはAttachment.OwnerId == 1添付ファイルのみが含まれています。

+0

投稿の添付ファイルがない場合、こんにちは、これは動作していないようです。 A、何かを逃して – grayson

1

遅延ロードを防ぐために、あなたのAttachmentsナビゲーションプロパティからvirtualキーワードの削除:

public ICollection<Attachment> Attachments { get; set; }

最初の方法:問題二つの別々のクエリ:投稿用、添付ファイルのための1つ、と聞かせて関係をFIX-アップ残りを行います

List<Post> postsWithAuthoredAttachments = _context.Posts 
    .Include(p => p.Comments) 
    .Include(p => p.PostAuthor) 
    .Where(p => p.PostAuthor.Id == postAuthorId) 
    .ToList(); 

List<Attachment> filteredAttachments = _context.Attachments 
    .Where(a => a.Post.PostAuthor.Id == postAuthorId) 
    .Where(a => a.Owner is Author) 
    .ToList() 

関係フィックスアップでは、ポストのナビゲーションプロパティを経由してこれらのフィルタの添付ファイルにアクセスできることを意味し

第二の方法:

var query = _context.Posts 
    .Include(p => p.Comments) 
    .Include(p => p.PostAuthor) 
    .Where(p => p.PostAuthor.Id == postAuthorId) 
    .Select(p => new 
     { 
      Post = p, 
      AuthoredAttachments = p.Attachments 
       Where(a => a.Owner is Author) 
     } 
    ); 

私は匿名型は、ここで

var postsWithAuthoredAttachments = query.ToList() 

を使用するか、私はへのViewModelクラスを作成します。メモリ内のクエリに続いてデータベースへの1つのクエリあなたが本当に投稿をアンラップする場合

List<MyDisplayTemplate> postsWithAuthoredAttachments = 
    //query as above but use new PostWithAuthoredAttachments in the Select 

または、::匿名型を避ける

List<Post> postsWithAuthoredAttachments = query.//you could "inline" this variable 
    .AsEnumerable() //force the database query to run as is - pulling data into memory 
    .Select(p => p) //unwrap the Posts from the in-memory results 
    .ToList() 
-1

"a"タイプが "YourType"であると仮定すると、条件付きインクルードはメソッド拡張を使用することで解決できます。

public static class QueryableExtensions 
{ 
    public static IQueryable<T> ConditionalInclude<T>(this IQueryable<T> source, bool include) where T : YourType 
    { 
     if (include) 
     { 
      return source 
       .Include(a => a.Attachments) 
       .Include(a => a.Attachments.Owner)); 
     } 

     return source; 
    } 
} 

...あなたが使用しているのと同じように使用してください。

bool yourCondition; 

.ConditionalInclude(yourCondition) 
+3

これは冗談か何かですか? – sam