【问题标题】:IQueryable two tables from Code First Entity Framework来自 Code First Entity Framework 的 IQueryable 两个表
【发布时间】:2018-05-04 04:17:27
【问题描述】:

我有一个看似简单的 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; }
    }
}

投票:

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; }    
    }
}

这已经在 SQL 数据库中生成了一个 VotePost 表,其中 Vote_id 和 Post_id 作为外键。

如果帖子有 0 票或看到所有票,我试图只获得与 p.creator.user_id 相关联的看到 == false 的投票。那我就不需要返回post元素了

帖子有多个投票对象,我不知道如何过滤掉所有投票。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);

提前感谢您的帮助

【问题讨论】:

    标签: c# mysql sql entity-framework linq


    【解决方案1】:

    所以你有用户、帖子和投票。

    在 Creator 和 Post 之间有一个one-to-many relation:每个 Creator 都有零个或多个 Post,每个 Post 都属于一个 Creator。

    似乎有a many-to-many relation between Posts and Votes: 每个帖子都有零个或多个投票,每个投票都是针对零个或多个帖子。

    我不确定您为什么选择偏离标准实体框架约定并省略类定义的外键。这只会使您的查询更加困难。但我们必须处理你的设计。

    你写道:

    我试图只获得看到 == false 的投票 使用 p.creator.user_id 连接到帖子,如果帖子有 0 票 或看到所有选票。那我就不需要返回post元素了

    我认为这是一种困难且有点模棱两可的说法:

    给定一个变量 user_id,它是用户的主键。给我一个查询,该查询会产生所有投票,这些投票没有看到,有任何主键 user_Id 的创建者帖子。

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

    如果你在你的类中包含了外键,那就更简单了:

    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;}
    }
    

    可能是您对某些属性的命名不同,但您明白了要点。

    将外键添加到帖子用户后,您的查询就更简单了:

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

    建议:每当您想到偏离 entity framework code first conventions 时,例如对主键和外键使用非常规名称,对 ICollection 属性使用非常规名称等,请三思:真的需要这种偏离吗?

    偏离意味着需要流畅的 Api 或属性。维护:其他人不会立即明白你的意思。而且您的查询可能会变得更加困难

    【讨论】:

    • 非常感谢您的意见!我可能在这里的数据库设置中犯了一个错误。一个帖子可以有多个投票,但一个投票只能连接到一个帖子。所以我猜投票真的应该只有一个 post_id 外键..再次感谢
    【解决方案2】:

    你可以这样试试;

    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);
    

    【讨论】:

      【解决方案3】:

      您可以使用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();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-07-29
        • 1970-01-01
        • 2015-01-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多