【问题标题】:Convert multiple SQL JOINs to Entity Framework将多个 SQL JOIN 转换为实体框架
【发布时间】:2017-08-04 05:47:42
【问题描述】:

我正在尝试转换此 SQL 查询:

select t.id,t.name as table_name,r.name as room_name,iif(c.id is null ,0,1) as opened,
 from gs_pos_t t
inner join gs_pos_r r on t.id_r=r.id
left join gs_pos_c c on t.id=c.id_t
left join gs_pos_pz p on c.id=p.id_c
 where c.open_date is not null
 group by 1,2,3,4

我需要从所有房间中选择所有表以及它们是否有已开售的状态,在这种情况下是当前已开售的总和

我尝试过这样的事情,但没有运气:

        db.GS_POS_t.Join(
                      db.GS_POS_r,
                      t => t.ID_r,
                      r => r.ID,
                   (tables, rooms) => new {tables,rooms})
               .GroupJoin(
                     db.GS_POS_C
                       .GroupJoin(
                           db.GS_POS_C_PZ,
                           c => c.ID,
                           p => p.ID_C,
                           (sales, p) => new { sales, s_detail= p.DefaultIfEmpty() }
                           )
                           ,
                     mg => mg.tables.ID,
                     cg => cg.sales.ID_t,
                     (tablesrooms, saleswithdetail) => new { tablesrooms, saleswithdetail }
                ).Where(r => r.saleswithdetail.) <=Here !!!!
            );

这是模型:

GS_POS_T  (tables)
        public long ID { get; set; }
        public short ID_R { get; set; }
        public string NAME { get; set; }
        public virtual ICollection<GS_POS_C> GS_POS_C { get; set; }
        public virtual GS_POS_R GS_POS_R { get; set; }
       ...

GS_POS_R (rooms)

        public short ID { get; set; }
        public string NAME { get; set; }
        public virtual ICollection<GS_POS_T> GS_POS_T { get; set; }
        ...

GS_POS_C (sales)
        public long ID { get; set; }
        public long ID_T { get; set; }
        public Nullable<System.DateTime> OPEN_DATE { get; set; }
        ......    
        public virtual GS_POS_M GS_POS_M { get; set; }
        public virtual ICollection<GS_POS_C_PZ> GS_POS_C_PZ { get; set; }


GS_POS_C_PZ  (sale details)
        public long ID { get; set; }
        public long ID_C { get; set; }
        public Nullable<decimal> CANT { get; set; }
        public Nullable<decimal> PRICE { get; set; }
        public virtual GS_POS_C GS_POS_C { get; set; }
       ...

部分解决方案 我得到了下一个几乎可以工作的代码,但有两个问题:

1.我无法在 db.GS_POS_C 的最终结果 ID 字段中包含

ExceptionMessage":"转换为值类型 'System.Int64' 失败,因为具体化的值为 null。结果类型的泛型 参数或查询必须使用可为空的类型。"

2.我想把它转换成方法语法

from t in db.GS_POS_T
        join r in db.GS_POS_R on t.id_r equals r.id //it is inner join statement
        join c in db.GS_POS_C on t.id equals c.id_t  into ct
              from sub1 in ct.DefaultIfEmpty()  //it is left join statement
        join p in db.GS_POS_PZ on sub1.id equals p.id_c into psub1
              from sub2 in psub1.DefaultIfEmpty() //it is left join statement
              where t.activ == 1
        select new { t.id, t.name, rname = r.name,  sub2.cant, sub2.price } into x
        group x by new { id = x.id, name = x.name, rname = x.rname } into g
        select new
        {
            tid = g.Key.id,
            tname = g.Key.name,
            rname = g.Key.rname,
            sumpcantpprice = g.Sum(abc => abc.price * abc.cant)
        };

感谢您的帮助!

【问题讨论】:

  • 你的模型看起来怎么样?
  • 嗨,我在第一篇文章中添加了
  • 你应该使用导航属性(如GS_POS_T),而不是加入。

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


【解决方案1】:

对于 linq 中的左外连接,您可以使用以下语法:

DefaultIfEmpty(new Model())

所以,这可能会给你一个想法,我很快就写好了,所以它可能不会从第一次尝试就成功。我不知道你的模型,所以替换 linq 语句中的模型并尝试一下:

    var result = from t in gs_pos_t

                        join r in gs_pos_r on t.id_r equals r.id

                        join c in gs_pos_c on t.id equals c.id_t into firstList from lt1 in firstList.DefaultIfEmpty(new Model1())

                        join p in gs_pos_pz onc.id equals p.id_c into secondList from lt2 in secondList.DefaultIfEmpty(new Model2())

                        where c.open_date != null

                        select new
                        {
                            t.id,
                            t.name,
                            r.name,
                            lt1.id == null ? 0 : 1
                        };

希望对你有帮助

【讨论】:

  • 嗨,感谢您的回答,我正在使用方法语法并尝试了 .DefaultIfEmpty 但最后一个 .GroupJoin 出现了同样的问题 当我按下点时,我无法从 t.cgcom 中选择字段
  • 能否粘贴您使用 DefaultIfEmpty 编写的代码?
  • 我在第一篇文章中更新了代码,我无法从 saleswithdetail 中选择任何字段: .Where(r => r.saleswithdetail.
  • 我的问题 简而言之:在 T1 和 T2 上使用 .Join 使我可以选择在最后使用 .Where() 时从 T1 或 T2 中选择字段名称,但使用 .GroupJoin 只给我来自T1,我做错了什么
  • 我已经添加到第一个发布部分解决方案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 2021-12-16
  • 2014-06-04
相关资源
最近更新 更多