【问题标题】:How to convert this SQL statement into a Lambda/Linq expression如何将此 SQL 语句转换为 Lambda/Linq 表达式
【发布时间】:2019-01-11 13:50:33
【问题描述】:

我正在寻找此 SQL 语句的等效 LINQ Lambda 表达式。

SELECT A.USER_ID, A.GIVEN_NAME, A.SURNAME, A.REGION, A.EMAIL 
FROM USER A
WHERE A.USER_ID IN (
    SELECT B.USER_ID_TXT 
    FROM TRAINING_COURSE B
    WHERE B.COURSE_ID_TXT IN 
        (SELECT C.MITT_COURSE_ID_TXT 
            FROM TRAINING_MITT C 
            WHERE C.TRAINING_ID =
                (SELECT D.TRAINING_ID 
                 FROM TRAINING_ROLE D 
                 WHERE D.ROLE_ID = 3011)))

这里是实体。我添加了一些 cmets 来说明 SQL 查询中对 TABLES 和 FIELDS 的引用。

此表存储用户信息,并作为物化视图挂载。

// TABLE USER 
public class TCUser
{
    // Field USER_ID
    public string UserId { get; set; }
    public string GivenName { get; set; }
    public string Surname { get; set; }
    public string OfficeBuilding { get; set; }
    public string Address { get; set; }
    public string FloorLocation { get; set; }
    public string FloorNumber { get; set; }
    public string Region { get; set; }
    public string Province { get; set; }
    public string PostalCode { get; set; }
    public string City { get; set; }
    public string Email { get; set; }
}  

下一个表格存储培训课程,它来自外部资源。它基本上是数据的导入。

// TABLE TRAINING_COURSE - EXTERNAL SOURCE
public class TrainingCourse
{
    // Field USER_ID_TXT
    public String UserId { get; set; }

    // Field COURSE_ID_TXT
    public String CourseId { get; set; }
    public String CourseDescription { get; set; }
    public String ScheduleId { get; set; }
    public String ScheduleDescription { get; set; }
    public DateTime? ScheduleStartDate { get; set; }
    public DateTime? ScheduleEndDate { get; set; }
    public String Status { get; set; }
}

此表对履行角色所需的培训课程进行关联。

// TABLE TRAINING_ROLES - XREF between TRAINING_MITT and ICS_ROLE
public class IcsTrainingRole
{
     // Field ROLE_ID
     public int RoleId { get; set; }

     // Field TRAINING_ID
     public int TrainingId { get; set; }
     public virtual IcsTraining IcsTraining { get; set; }
     public virtual IcsRole IcsRole { get; set; }
}

此表将 Training 与外部 MITT Training DB 关联

// TABLE TRAINING_MITT
public class IcsTrainingMitt
{
    // Field TRAINING_ID             
    public int TrainingId { get; set; }

    // Field MITT_COURSE_ID_TXT
    public string MittCourseId { get; set; }
    public virtual IcsTraining IcsTraining { get; set; }
}

public class IcsTraining
{
    public int TrainingId { get; set; }
    public string TrainingName { get; set; }
    public virtual ICollection<IcsTrainingRole> IcsTrainingRoles { get; set; }
    public virtual ICollection<IcsTrainingMitt> IcsTrainingMitt { get; set; }
}


public class IcsRole
{
    public int RoleId { get; set; }
    public int SectionId { get; set; }
    public string RoleName { set; get; }
    public virtual ICollection<IcsTrainingRole> IcsTrainingRoles { get; set; }
}

【问题讨论】:

  • 不要。 LINQ 不是 SQL,也不是 SQL 的替代品。这是一种与 ORM 一起使用的语言。正确配置您的 ORM 实体,添加正确的导航关系和属性,您的 ORM 将从 LINQ 查询生成 SQL 语句
  • 鉴于这个查询,我怀疑 ORM 最终也会得到一个更清晰的查询。没有理由在WHERE A.USER_ID IN 之后使用子查询,简单的连接会产生相同的执行计划。
  • 请在问题中添加您的实体模型代码。
  • @kaffekopp : 用实体模型更新问题。
  • 也许我的SQL to LINQ Recipe 可以帮到你?

标签: c# .net entity-framework linq linq-to-entities


【解决方案1】:

如果您使用连接重新编写代码,它将如下所示:

SELECT A.USER_ID, A.GIVEN_NAME, A.SURNAME, A.REGION, A.EMAIL 
FROM USER A
JOIN TRAINING_COURSE B ON A.USER_ID = B.USER_ID_TXT
JOIN TRAINING_MITT C ON B.COURSE_ID_TXT = C.MITT_COURSE_ID
JOIN TRAINING_ROLE D ON C.TRAINING_ID = D.TRAINING_ID AND D.ROLE_ID = 3011

【讨论】:

    【解决方案2】:

    通过使用连接将 Linq 查询语法与您的模型类一起使用(如 Hogan 建议的那样):

    var users = from u in TCUser
                join tc in TrainingCourse on u.UserId equals tc.UserId
                join tm in IcsTrainingMitt on tc.CourseId equals tm.MittCourseId
                join tr in IcsTrainingRole on tm.TrainingId equals tr.TrainingId
                where tr.RoleId == 3011
                select new
                {
                    UserId = u.UserId,
                    GivenName = u.GivenName,
                    Surname = u.Surname,
                    Email = u.Email
                };
    

    我认为查询语法应该比使用 lambda 更清晰,因为该模型似乎缺乏适当的导航属性。

    【讨论】:

      【解决方案3】:

      好的,使用 join 实际上更简单,并且基于 @kaffekopp 的帖子,使用 lambdas 的等效表达式将是:

      var users = TCUser
          .Join(TrainingCourse, u => u.UserId, tc => tc.UserId, (u, tc) => new {u, tc})
          .Join(IcsTrainingMitt, @t => @t.tc.CourseId, tm => tm.MittCourseId, (@t, tm) => new {@t, tm})
          .Join(IcsTrainingRole, @t => @t.tm.TrainingId, tr => tr.TrainingId, (@t, tr) => new {@t, tr})
          .Where(@t => @t.tr.RoleId == 3011)
          .Select(@t => new
          {
              UserId = @t.@t.@t.u.UserId,
              GivenName = @t.@t.@t.u.GivenName,
              Surname = @t.@t.@t.u.Surname,
              Email = @t.@t.@t.u.Email
          });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-04
        • 1970-01-01
        • 2017-08-22
        • 1970-01-01
        • 1970-01-01
        • 2011-07-18
        相关资源
        最近更新 更多