简体   繁体   English

可从代码优先实体框架中查询两个表

[英]IQueryable two tables from Code First Entity Framework

I have a seemingly simple Post table with multiple Votes like this: 我有一个看似简单的Post表格,上面有多个投票:

Post: 发布:

namespace Api.Models
{
    public class Post
    {
        public int id { get; set; }
        public bool deleted { get; set; }
        public virtual User creator { get; set; }

        (...)

        public virtual ICollection<Vote> votes { get; set; }
    }
}

Vote: 投票:

namespace Api.Models
{
    public class Vote
    {
        public int id { get; set; }    
        public bool seen { get; set; } = false;

        (...)

        [JsonIgnore]
        [IgnoreDataMember]
        public virtual ICollection<Post> post { get; set; }    
    }
}

This has generated a VotePost table in the SQL database with Vote_id and Post_id as foreign keys. 这已在SQL数据库中生成了VotePost表,其中Vote_id和Post_id为外键。

I am trying to only get the Votes that seen == false that are connected to the post with p.creator.user_id, if the post has 0 votes or all votes are seen. 如果帖子具有0票或看到了所有票数,我试图仅获得与p.creator.user_id连接到帖子的看到== false的投票。 Then I don't need to return the post element 然后我不需要返回post元素

The posts has multiple votes objects and I don't know how to filter out all the vote.seen == false 这些帖子有多个投票对象,我不知道如何过滤掉所有投票。

        IQueryable<Post> postQuery = (from p in db.Posts where 
                                      p.deleted == false && 
                                      p.creator.user_id == user_id &&

                                      // all p.votes object seen == false ?

                                      select p);

Thanks in advance for any help 预先感谢您的任何帮助

You can try like that; 你可以这样尝试;

IQueryable<Post> postQuery = (from p in db.Posts
                  where 
                  p.deleted == false && 
                  p.creator.user_id == user_id &&
                  (p.votes == null || !p.votes.Any(v => v.seen == true))
                  select p);

So you have Users, Posts and Votes. 因此,您拥有用户,帖子和投票。

There is a one-to-many relation between a Creator and a Post: Every Creator has zero or more Posts, every Post belongs to exactly one Creator. 创建者和帖子之间存在一对多的关系 :每个创建者都有零个或多个帖子,每个帖子都完全属于一个创建者。

There seems to be a many-to-many relation between Posts and Votes: Every Post has zero or more Votes, and every Votes is for to zero or more Posts. 帖子和投票之间似乎存在多对多的关系:每个帖子都有零个或多个投票,每个投票最多可以有零个或多个帖子。

I'm not sure why you chose to deviate from standard entity framework conventions and left out the foreign keys of your class definitions. 我不确定您为什么选择偏离标准实体框架约定,而忽略了类定义的外键。 This only makes your query more difficult. 这只会使您的查询更加困难。 But we'll have to do with what you've designed. 但是我们将与您的设计有关。

You wrote: 你写了:

I am trying to only get the Votes that seen == false that are connected to the post with p.creator.user_id, if the post has 0 votes or all votes are seen. 如果帖子具有0票或看到了所有票数,我试图仅获得与p.creator.user_id连接到帖子的看到== false的投票。 Then I don't need to return the post element 然后我不需要返回post元素

I gues this is a difficult and a bit ambiguous way to say: 我认为这是一种困难且有点含糊的说法:

Given a variable user_id, which is the primary key of a user. 给定变量user_id,这是用户的主键。 Give me the query that results in all Votes, that are not Seen, that have any Post of the Creator with primary key user_Id. 给我一个查询,该查询会导致所有投票(未看到)具有所有创建者的帖子,且带有主键user_Id。

var result = dBContext.Votes
    .Where(vote => !vote.Seen 
        && vote.Posts.Any(post => post.Creator.user_id == user_id);

If you'd included the foreign keys in your classes it would even have been simpler: 如果您将外键包含在类中,它甚至会更简单:

class User
{
    public int Id {get; set;}    // primary key
    // a User has zero or more Posts:
    public virtual ICollectioins<Post> Posts {get; set;}
    ...
}
class Post
{
    public int Id {get; set;}    // primary key

    // Every Post belongs to exactly one User via foreign key
    public User User {get; set;}
    public int UserId {get; set;}

    // a Post has zero or more Votes (many-to-many)
    public virtual ICollection<Vote> Votes{get; set;}
    ...
}

class Vote
{
    public int Id {get; set;}    // primary key
    // A vote is for zero or more Posts (many-to-many)
    public virtual ICollection<Post> Posts{get; set;}

    public bool Seen {get; set;}
}

It might be that you named some of the properties differently, but you get the gist. 可能是您对某些属性进行了不同的命名,但是您的主旨是。

Once you've included the foreign key to the User of the Post, your query is even simpler: 一旦包含了Post User的外键,您的查询就更加简单了:

 var result = dBContext.Votes
    .Where(vote => !vote.Seen 
        && vote.Posts.Any(post => post.userid == user_id);

Advice: whenever you think of deviating from entity framework code first conventions , like using non-conventional names for primary keys and foerign keys, using non-conventional names for ICollection properties etc. think twice: is this deviation really needed? 建议:每当您想到偏离实体框架代码的第一约定时 ,例如对主键和副键使用非常规名称,对ICollection属性使用非常规名称,等等。请三思:真的需要这种偏离吗?

Deviating means the need of fluent Api, or Attributes. 偏离意味着需要熟练的Api或属性。 Maintenance: others won't immediately see what you mean. 维护:其他人不会立即明白您的意思。 And your queries might become more difficult 您的查询可能会变得更加困难

You can just use All() linq method: 您可以只使用All() linq方法:

IQueryable<Post> postQuery = (from p in Posts
                              where p.deleted == false 
                              && p.creator.user_id == user_id 
                              && p.votes.All(v => !v.seen)
                              select p).AsQueryable();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM