【问题标题】:C# Create lambda expression with Left and right Join with 3 tablesC#使用左右连接创建3个表的lambda表达式
【发布时间】:2021-09-16 09:28:37
【问题描述】:

我目前正在为我的应用程序开发一个搜索过滤器,但我在按特定键进行过滤时遇到问题,当我制作 lambda 表达式时,它会为我提供范围内的所有值,但我不知道我还需要什么添加以正确获取过滤器。

我有三个带有各自外键的表: 表 A:id_contract, 表 B:id_build 和 id_contract, 表 C:id_build

实体如下: 表A

    public partial class TableA
    {
        public TableA()
        {
            this.TableB = new List<TableB>();
        }
        public int id_contract { get; set; } //Primary Key
        public int id_client { get; set; } //FK another table not important for now
        public int contract_name { get; set; } //Information
   }

表 B

    public partial class TableB
    {
        public int id_tableB { get; set; } //primary key (not use)
        public int id_contract { get; set; } //FK Table A
        public int id_build { get; set; } //FK Table C
            
        public virtual TableC TableC { get; set; }
        public virtual TableA TableA { get; set; }
        
    }

表 C

public partial class TableC
    {
        public TableC()
        {
            this.TableB = new List<TableB>();
        }
        public int id_build { get; set; } //Primary Key
        public string build_code { get; set; 
        public virtual List<TableB> TableB { get; set; }
    }

过滤器的参数来自控制器内部的 id_builds 列表,然后我使用 Contains 检查表是否具有相应的值。

我的SQL查询如下:


    SELECT c.contract_name, b.build_value, MAX(p.update_date) AS [updt_date] 
    FROM
    (
        SELECT id_contract, MAX(id_build) AS id_build
     FROM [Table B]
        GROUP BY id_contract
    ) d
    JOIN [Table B] P ON p.id_contract = d.id_contract AND p.id_build = d.id_build
    RIGHT JOIN [Table A] c WITH(NOLOCK) ON p.id_contract = c.id_contract
    LEFT JOIN [Table C] b WITH(NOLOCK) ON p.id_build = b.id_build
    /*This where is where i filter it, and the correct value must be based from id_build as below, i commented it to test and get all values from query before.*/
    WHERE c.contract_name <> 0 AND c.id_company = 1 AND c.ativo = 1 --and b.id_build = XXX 
    GROUP BY c.contract_name, b.build_value

当我在不按 XXX 值过滤的情况下运行此查询时,我会得到所有 750 个结果,这适用于任何值,并且使用过滤器,我会通过 id_build 获得 61 个结果,这些结果对应于我从过滤器中给出的任何值。

我目前在 C# 中的 lambda 表达式如下:


    results = db.TableA
           .Join(db.TableB, tbA => id_contract, tbB => id_contract, (tbA , tbB ) => new { tbA, Key = tbB.id_build})
           .Join(db.TableC, tbC => tbC.Key, FKTableB=> TableB.id_build, (tbC , FKTableB) => new {tbC, FKTableB})
           .Where(c => c.tbC.tbA.ativo == true && c.tbC.tbA.id_company == 1 && id_build.Contains(c.FKTableB.id_build))
    /*ignore this select inside content, but consider it as i need this output to be printed out.*/
           .Select(x => new
                   {
                      x.tbC.tbA.id_contract,
                      contract_name = x.tbC.tbA.contrato + " - " + 
                      x.tbC.tbA.client_name
                    }).ToList();

我不知道如何在这种状态下复制 Join。

谢谢!

【问题讨论】:

  • 你能展示实体类吗? (表A、表B、表C)
  • 您好@vernou,已添加实体。
  • 为什么在可以使用导航属性(A.TableB 等)的同时加入 LINQ 查询?使查询更容易。 LINQ 查询可以是db.TableA.Where(...),无需任何连接。

标签: c# asp.net-mvc entity-framework linq


【解决方案1】:

我不知道你到底想要什么,但我用 lambda 表达式实现了你确切的 sql 查询。

请使用以下类进行查询。我将update_date 添加到TableB 类和build_valueTableC 类。和id_companyativoTableA 类。

public partial class TableA
{
   public TableA()
   {
       this.TableB = new List<TableB>();
   }
   public int id_contract { get; set; } //Primary Key
   public int id_client { get; set; } //FK another table not important for now
   public int contract_name { get; set; } //Information
   public int id_company { get; set; } //Information
   public int ativo { get; set; }
   public virtual List<TableB> TableB { get; set; }
}
public partial class TableB
{
   public int id_tableB { get; set; } //primary key (not use)
   public int id_contract { get; set; } //FK Table A
   public int id_build { get; set; } //FK Table C
   public DateTime update_date { get; set; }
   public virtual TableC TableC { get; set; }
   public virtual TableA TableA { get; set; }
}

public partial class TableC
{
   public TableC()
   {
      this.TableB = new List<TableB>();
   }
   public int id_build { get; set; } //Primary Key
   public string build_code { get; set; }
   public int build_value { get; set; }
   public virtual List<TableB> TableB { get; set; }
}

lambda 表达式

var results = db.TableB
     .GroupBy(a => a.id_contract)
     .Select(a => new
     {
        id_contract = a.Key,
        id_build = a.Max(x => x.id_build)
     })
     .Join(db.TableB,
        a => new { a.id_contract, a.id_build },
        b => new { b.id_contract, b.id_build },
        (a, b) => new { id_contract = a.id_contract, id_build = a.id_build, tB = b }
     )
     .Join(db.TableA,
        a => a.id_contract,
        b => b.id_contract,
        (a, b) => new { id_contract = a.id_contract, id_build = a.id_build, tB = a.tB, tA = b }
     )
     .Join(db.TableC,
        a => a.id_build,
        b => b.id_build,
       (a, b) => new { id_contract = a.id_contract, id_build = a.id_build, tB = a.tB, tA = a.tA, tC = b })
     .Where(a=>a.tA.contract_name != 0 && a.tA.id_company == 1 && a.tA.ativo == 1)
     .GroupBy(a => new { a.tA.contract_name, a.tC.build_value })
     .Select(a => new
      {
         contract_name = a.Key.contract_name,
         build_value = a.Key.build_value,
         updt_date = a.Max(x => x.tB.update_date)
      }).ToList();

【讨论】:

  • 非常感谢,它帮助我了解了我遗漏的地方,我的目标是调整该查询以充当基于表 C 中的 id_build 的过滤器,现在它可以工作了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多