实体框架 - 与Where的关系

时间:2018-01-06 17:08:59

标签: asp.net-mvc entity-framework entity-relationship

关注this answer我试图这样做:

var posts = await _context.Posts
            .Select(p => new 
            { 
                p,
                Comments = p.Comments
                .Where(c.Status == "approved")
            })
            .Include(p => p.Author)
            .Include(p => p.Comments)
            .SingleOrDefaultAsync(m => m.Id == id);

仅获得批准"我的帖子评论。

但是我收到以下错误:

  

名称' c'在当前上下文中不存在[ASPress]

所以我不能用语法

来解决问题

2 个答案:

答案 0 :(得分:3)

您必须在lambda ...

中定义您正在使用的标识符
.Where(c => c.Status == "approved")

应该修复它。

刚刚阅读了您的评论,我相信它是基于您使用LINQ方法的顺序。从Posts开始,您将投射到匿名类型,并且不会拥有您想要的内容。尝试重新安排它,如下所示:

var posts = await _context.Posts
      .Include(p => p.Author)
      .Include(p => p.Comments)
      .Select(p => new
      {
          p,
          Comments = p.Comments
            .Where(c => c.Status == "approved")
      })

答案 1 :(得分:1)

虽然您忘记编写课程,但在我看来,您有一系列帖子。邮政只有一个作者。每个帖子都有零个或多个评论,每个评论都属于一个帖子:没有任何评论都没有,帖子和评论之间存在真正的一对多关系。

如果您按照guidelines for a one-to-many configuration进行操作,则会有以下类似内容:

class Author
{
    public int Id {get; set;}

    // not certain, but very likely: every Author has zero or more Posts:
    public virtual ICollection<Post> Posts {get; set;}
}
class Post
{
    public int Id {get; set;}

    // Every Post is posted by exactly one Author, using foreign key
    public int AuthorId {get; set;}
    public virtual Author Author {get; set;}

    // Every Post has zero or more Comments:
    public virtual ICollection<Comment> Comments {get; set;}
}
class Comment
{
    public int Id {get; set;}

    // every Comment belongs to exactly one Post using foreign key
    public int PostId {get; set;}
    public virtual Post Post {get; set;}

    public string Status {get; set;}
}

因为我遵循entity framework naming conventions,这足以告诉实体框架主键,外键和一对多关系。如果您决定偏离命名约定,您可能需要一些流畅的API属性,但这个想法保持不变。

回到你的问题

在我看来,你想要所有的帖子,连同他们的作者,只有他们批准的评论。

使用Include语句从数据库中获取数据。这通常是浪费处理能力,因为您可能不会使用所有Post属性和所有Comment Properties。最好明确命名您计划使用的属性。

var result = myDbcontext.Posts.Select(post => new
{
    // query only the attributes you plan to use, for example:
    Id = post.Id,
    Title = post.Title,

    Author = new
    {
        Id = post.Author.Id,
        Name = post.Author.Name,
        // no need to query the foreign Key Author.PostId, I already got that one in property Id
        ... // other author properties you need
    },

    Comments = post.Comments
        .Where(comment => comment.Status == "approved")
        .Select(comment => new
        {   // again: query only the properties you plan to use:
            Text = comment.Text,
            ...
        }
        .ToList(),

    ... 
};

根据我的经验,如果您正确配置一对多关系,则很少需要加入。请改用ICollections。实体框架将知道需要加入。

但是,您可以使用联接获得相同的结果:

var result = myDbContext.Posts
    .Join(myDbContext.Comments.Where(comment => comment.Status = "approved"),
     post => post.Id,              // from every Post take the Id
     comment => comment.PostId     // from every Comment take the PostId
     (post, comment) = new         // when they match make a new object
     {
         Id = post.Id,
         Title = post.Title,

         CommentText = comment.Text,
      }

等。请注意,这是一个真正的内部联接。如果您想要“发布评论”,则需要执行GroupBy Id

最后:如果您的状态数量有限,请考虑为您的状态创建枚举。这样可以防止人们将“已批准”分配给州而不是“已批准”,或者更糟糕的是:错误如“已批准”?在数据库内部,它们仍然是字符串,但是实体框架会将它们解析为正确的枚举值,并且您将无法在数据库中放置不正确的值。