0

I trying to figure out how to use .Include() when selecting from abstract type to include relation entities of Implemented type, here is an example of what am I trying to do:

[Table("Comments")]
public abstract class Comment
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int CommentId { get; set; }
    public int UserId { get; set; }
    public virtual UserProfile User { get; set; }
    public string Content  { get; set; }
}

[Table("PostComments")]
public class PostComment : Comment
{
    public int PostId { get; set; }
    public virtual Post Post { get; set; }
}

[Table("UserProfiles")]
public class UserProfile
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    [MaxLength(200)]
    public string UserName { get; set; }
    public ICollection<Comments> Comments { get; set; }
}

  using (DataContext db = new DataContext())
  {
       return db.UserProfiles.Include(x => x.Comments)
       .Single(u => u.UserId == WebSecurity.CurrentUserId);

       // Here I need a way to include Comment.Post if Comment 
       // is PostComment or some other child entity if Comment is 
       // from another inherited type

  }
formatc
  • 4,261
  • 7
  • 43
  • 81

1 Answers1

1

You can't do it this way. A different approach may work better for you:

Change UserProfile to this:

[Table("UserProfiles")]
public class UserProfile
{
    // ...
    public ICollection<PostComment> PostComments { get; set; }
    public ICollection<OtherComment> OtherComments { get; set; }
}

What EF does when you inherit a common type is create a discriminator column in a shared table. So when you select PostComments, the WHERE clause that EF generates will have something like AND type='PostComment'. (I don't remember the name of the column it generates, but you get the idea).

Then you can get the data like this:

var data = db.UserProfiles
                .Include("PostComments.Post")
                .Include("OtherComments.OtherData")
                .Single(p => p.UserId == WebSecurity.CurrentUserId);

If you want to use all the comments as a single list, you can create it like such:

var comments = data.PostComments.ToList<Comment>();
comments.AddRange(data.OtherComments);
Artless
  • 4,522
  • 1
  • 25
  • 40