【问题标题】:Querying distinct columns across rows filtering by another column在由另一列过滤的行中查询不同的列
【发布时间】:2020-07-09 21:40:06
【问题描述】:

我正在开发一个使用 Linq 和 Entity Framework Core 的项目。

我正在为一个查询而苦苦挣扎。

我有两种数据访问模型。

public class JobPost
{
  public int Id {get;set;}
  public string RoleTitle  { get; set;}
  public Domain Domain1 {get;set;}
  public Domain Domian2 {get;set;}
  public Domain Domain3 {get;set;}
  public Domain Domain4 {get;set;}
  public Domain Domain5 {get;set;}
}

[Owned]
public  class Domain
{
   public int? CategoryId {get;set;}
   public int? SubcategoryId {get;set;}
}

职位发布是一个以 ID 为键的实体/表。它有一个角色标题(强制)和 1-5 个域(这解释了为什么 Domain 的 Id 属性可以为空)。 Domain 有 CategoryId 和 SubcategoryId 作为键。求职者将能够按域过滤职位发布。域名示例如下:

            Category      Subcategory
Domain      IT            Mobile
Domain      IT            Database
Domain      IT            Design
Domain      Transport     Driving
Domain      Transport     Spedition

如果 categoryId 或 subcategoryId 不同,则两个域是不同的。

相关查询的用户案例: 用户(雇主 X)发布了 3 个职位:Y、Z 和 W。Y 和 Z 的职位名称均为“软件开发人员”,而 W 的职位名称为“前端开发人员”。职位 Y 有一个域:IT、移动。职位发布 Z 有两个域:IT、移动和 IT、数据库。职位 W 有一个领域:IT、设计。 用户现在想要创建第三个帖子。用户单击+发布按钮,系统会提示您选择以前的角色标题(“软件开发人员”或“前端开发人员”)或创建一个新职位。在这种情况下,用户从上一个项目列表中选择“软件开发者”。接下来,提示用户提交域。我们希望通过提供一个可选择的不同域列表来简化我们的用户,这些域之前已申请职位名称为“软件开发人员”的职位。在这种特定情况下,列表中有两个域,“IT,Mobile”和“IT,Database”,用​​户可以申请。

所以问题是我们如何在 Linq 中编写此查询,以便我们获得所有不同域的 IEnumerable,这些域适用于所有职位的特定角色头衔,由 SQL 服务器执行,而不是由客户端执行。

我在 Linq 中尝试了不同的策略,例如投影、加入、分组,但没有得到我想要的结果。我能做到这一点的唯一方法是检索按角色标题过滤的所有职位发布并删除我的视图模型中的重复项。

from p in dbCotext.JobPosts
where p.RoleTitle == roleTitle
select p

//client code for removing duplicates, not what I want

是否可以在 Linq 中执行此操作,还是我必须在 SQL 中编写此查询?

提前致谢。

【问题讨论】:

  • “不同域”是什么意思?您能描述一下您正在寻找的结果以及您尝试过的方法吗?
  • 为什么 JobPost 没有域集合,而不是 5 个不同的域属性。似乎它会使您的查询更容易。
  • 这会将我的域放在一个单独的表中,我不希望这样......
  • 如果您没有将域视为实体,请使用a collection of owned types
  • 问题仍然存在,您的模型违反了与任何 ORM (3NF) 顺利工作所需的最低 范式。第一个违规是域不依赖于密钥,只依赖于密钥:第二个域只能在第一个域时填充,等等。第二个是CategoryIdSubCategoryId 是多余的。子类别“Mobile”意味着类别“IT”等。我认为实际上,JobPostSubCategory 实体之间存在多对多关联,最多限制为 5 个项目。

标签: sql entity-framework linq entity-framework-core linq-to-entities


【解决方案1】:
 PreviousSubcategories =
          from c in dbContext.Categories
             let posts = 
             from p in a.Posts p in dbContext.Posts
             where p.RoleTitle == roleTitle
             where (c.Id == p.Domain1.CategoryId
             || c.Id == p.Domain2.CategoryId
             || c.Id == p.Domain3.CategoryId
             || c.Id == p.Domain4.CategoryId
             || c.Id == p.Domain5.CategoryId
             orderby p.CreatedOn descending 
             select new Domain[]
                   {
                     p.Domain1,
                     p.Domain2,
                     p.Domain3,
                     p.Domain4,
                     p.Domain5
                   }
            where posts.Any()
            select new DomainViewModelDto
                  {
                      SubcategoryId = (int)c.Id,
                      SubcategoryName = c.Name,
                      LatestExperienceLevelsApplied = new LatestExperienceLevelsApplied
                      {
                          IsExperienceLevel1Applied = (bool)posts.First().Where(d => d.CategoryId == c.Id).First().IsExperienceLevel1Applied,
                          IsExperienceLevel2Applied = (bool)posts.First().Where(d => d.CategoryId == c.Id).First().IsExperienceLevel2Applied,
                          IsExperienceLevel3Applied = (bool)posts.First().Where(d => d.CategoryId == c.Id).First().IsExperienceLevel3Applied,
                          IsExperienceLevel4Applied = (bool)posts.First().Where(d => d.CategoryId == c.Id).First().IsExperienceLevel4Applied,
                          IsExperienceLevel5Applied = (bool)posts.First().Where(d => d.CategoryId == c.Id).First().IsExperienceLevel5Applied,
                          IsExperienceLevel6Applied = (bool)posts.First().Where(d => d.CategoryId == c.Id).First().IsExperienceLevel6Applied,
                      }


                  }

【讨论】:

    猜你喜欢
    • 2022-01-21
    • 2011-08-18
    • 1970-01-01
    • 2023-01-27
    • 2017-04-23
    • 2018-06-30
    • 2014-01-28
    • 1970-01-01
    • 2017-01-28
    相关资源
    最近更新 更多