代码之家  ›  专栏  ›  技术社区  ›  ganjan

IQueryable来自代码优先实体框架的两个表

  •  0
  • ganjan  · 技术社区  · 8 年前

    我有一个看似简单的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\u id和Post\u id为外键。

    我试图只获得与p.creator的帖子相关的seen==false的投票。user\u id,如果帖子有0票或看到所有投票。那么我不需要返回post元素

    这些帖子有多个投票对象,我不知道如何过滤掉所有投票。seen==假

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

    提前感谢您的帮助

    3 回复  |  直到 8 年前
        1
  •  1
  •   Harald Coppoolse    8 年前

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

    有一个 one-to-many relation 在创建者和帖子之间:每个创建者都有零个或多个帖子,每个帖子只属于一个创建者。

    似乎有 a many-to-many relation between Posts and Votes: 每个帖子都有零张或多张选票,每张选票都指向零张或多张帖子。

    我不知道为什么您选择偏离标准实体框架约定,而忽略了类定义的外键。这只会使您的查询更加困难。但我们要做的是你设计的。

    您写道:

    我只想得到那些被认为是错误的选票 已与p.creator连接到帖子。user\u id,如果帖子有0票 或者看到所有投票。那么我不需要返回post元素

    我认为这是一种困难且有点模糊的表达方式:

    给定一个变量user_id,它是用户的主键。给我一个查询,结果是所有投票,没有看到,有任何职位的创造者与主键user\u 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 ,例如使用非常规名称作为主键和foerign键,使用非常规名称作为ICollection属性等。请三思:真的需要这种偏差吗?

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

        2
  •  1
  •   Emre Kabaoglu    8 年前

    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
  •  0
  •   daniell89    8 年前

    你可以用 All()

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