C# 如何将SQL多表查询转换为Linq

C# 如何将SQL多表查询转换为Linq,c#,sql,linq,C#,Sql,Linq,我尝试将sql查询转换为linq,但无法正确获取它。有人能帮我把下面的转换成linq吗 SELECT stockdiary.datenew, locations.ID AS LOCATIONID, locations.NAME AS LOCATIONNAME, products.REFERENCE, products.NAME, products.CATEGORY, categories.NAME AS CATE

我尝试将sql查询转换为linq,但无法正确获取它。有人能帮我把下面的转换成linq吗

SELECT stockdiary.datenew, locations.ID AS LOCATIONID, locations.NAME AS LOCATIONNAME, 
                    products.REFERENCE, products.NAME, 
                    products.CATEGORY, categories.NAME AS CATEGORYNAME, 
                    products.SUPPLIER, 
                    SUM(CASE WHEN stockdiary.UNITS <0 THEN stockdiary.UNITS ELSE 0 END) AS UNITSOUT, 
                    SUM(CASE WHEN stockdiary.UNITS <0 THEN stockdiary.UNITS * stockdiary.PRICE ELSE 0 END) AS TOTALOUT, 
                    SUM(CASE WHEN stockdiary.UNITS >=0 THEN stockdiary.UNITS ELSE 0 END) AS UNITSIN, 
                    SUM(CASE WHEN stockdiary.UNITS >=0 THEN stockdiary.UNITS * stockdiary.PRICE ELSE 0 END) AS TOTALIN, 
                    SUM(stockdiary.UNITS) AS UNITSDIFF, 
                    SUM(stockdiary.UNITS * stockdiary.PRICE) AS TOTALDIFF 
                FROM stockdiary JOIN locations ON stockdiary.LOCATION = locations.ID, 
                    products LEFT OUTER JOIN categories ON products.CATEGORY = categories.ID 
                WHERE products.ID = stockdiary.PRODUCT 
                GROUP BY locations.ID, locations.NAME, products.REFERENCE, products.NAME, products.CATEGORY, categories.NAME 
                ORDER BY locations.ID, categories.NAME, products.NAME
选择stockdiary.datenew,locations.ID作为LOCATIONID,locations.NAME作为LOCATIONNAME,
products.REFERENCE、products.NAME、,
products.CATEGORY,categories.NAME作为CATEGORYNAME,
产品、供应商、,
总和(当stockdiary.UNITS=0时,则为stockdiary.UNITS*stockdiary.PRICE,否则为0结束)为TOTALIN,
金额(库存日记。单位)为单位DIFF,
总和(stockdiary.UNITS*stockdiary.PRICE)为总差异
从stockdiary.LOCATION=locations.ID上的stockdiary连接位置,
products.CATEGORY=categories.ID上的产品左侧外部联接类别
其中products.ID=stockdiary.PRODUCT
按locations.ID、locations.NAME、products.REFERENCE、products.NAME、products.CATEGORY、categories.NAME分组
按位置.ID、类别.NAME、产品.NAME排序
====== 下面是我的linq查询,它给出了错误的结果

(from sd in Stockdiaries
join loc in Locations on sd.Location equals loc.Id
join prod in Products on sd.Product equals prod.Id
join cat in Categories on prod.Category equals cat.Id
select new 
{
    Location = loc.Name,
    Category = cat.Name,
    Reference = prod.Reference,
    Product = prod.Name,
    UnitsOut = sd.Units < 0 ? sd.Units:0,
    TotalOut = sd.Units < 0 ? sd.Units * sd.Price:0,
    UnitsIn = sd.Units >= 0 ? sd.Units:0,
    TotalIn = sd.Units >= 0 ? sd.Units * sd.Price:0,
    UnitsDiff = sd.Units,
    TotalDiff = sd.Units * sd.Price

})
(来自股票日记中的sd)
在sd上的位置连接loc。位置等于loc.Id
在sd上的产品中加入产品。产品等于产品Id
在产品类别中加入类别。类别等于类别Id
选择新的
{
位置=位置名称,
类别=类别名称,
参考=产品参考,
产品=产品名称,
UnitsOut=sd.单位<0?sd.单位:0,
TotalOut=标准单位<0?标准单位*标准价格:0,
单位sin=sd.Units>=0?标准单位:0,
TotalIn=sd.Units>=0?sd.Units*sd.Price:0,
UnitsDiff=sd.单位,
TotalDiff=标准单位*标准价格
})

原始sql中有一些旧的连接语法!这是对左连接的补充。此处简称:

from        stockdiary 
join        locations on stockdiary.location = locations.id
,           products 
left join   categories on products.category = categories.id 
where       products.id = stockdiary.product 
看看下面的方法是否适合你。它的输出可能并不完全符合您的期望,但它很可能非常接近,并且足以让您在之后使用它。尽管如此,我没有你提供的任何样本数据来测试它,所以我现在唯一能确认的是它不会出错

我在代码中得到了描述其组件的注释

var query = 
    from sd in Stockdiaries
    join loc in Locations on sd.Location equals loc.Id

    // Your old syntax join should work like an inner join
    join prod in Products on sd.Product equals prod.Id

    // This is a left join.  So you've got to do the 'into' hoop and 
    // then 'overwrite' the cat table.
    join cat in Categories on prod.Category equals cat.Id into pCat
    from cat in pCat.DefaultIfEmpty()

    // put it all together into one result set
    select new {
        Location = loc.Name,
        Category = cat?.Name, // Because it's a left join, it may be null, hence the '?'
        Reference = prod.Reference,
        Product = prod.Name,
        sd.Units,
        sd.Price

    } into cnd

    // group as appropriate, and remember that in linq 
    // grouping is a separate operation from aggregation
    group cnd by new { cnd.Location, cnd.Reference, cnd.Product, cnd.Category } into g

    // aggregate
    select new {
        g.Key.Location,
        g.Key.Reference,
        g.Key.Product,
        g.Key.Category,
        UnitsOut = g.Sum(row => row.Units < 0 ? row.Units : 0),
        TotalOut = g.Sum(row => row.Units < 0 ? row.Units * row.Price : 0),
        UnitsIn = g.Sum(row => row.Units >= 0 ? row.Units : 0),
        TotalIn = g.Sum(row => row.Units >= 0 ? row.Units * row.Price : 0),
        UnitsDiff = g.Sum(row => row.Units),
        TotalDiff = g.Sum(row => row.Units * row.Price)
    };

query.Dump();
var查询=
来自股票日记中的sd
在sd上的位置连接loc。位置等于loc.Id
//旧的语法联接应该像内部联接一样工作
在sd上的产品中加入产品。产品等于产品Id
//这是一个左连接。所以你必须做“入”圈和
//然后“覆盖”cat表。
将产品类别中的类别加入pCat。类别等于类别Id
来自pCat.DefaultIfEmpty()中的cat
//将所有这些放在一个结果集中
选择新的{
位置=位置名称,
Category=cat?.Name,//因为它是一个左连接,所以它可能为null,因此为“?”
参考=产品参考,
产品=产品名称,
sd.单位:,
标准价格
}进入cnd
//根据需要分组,记住在linq中
//分组是与聚合分开的操作
按新{cnd.Location,cnd.Reference,cnd.Product,cnd.Category}将cnd分组为g
//聚合
选择新的{
g、 钥匙,位置,
g、 关键。参考,
g、 关键,产品,,
g、 关键。类别,
UnitsOut=g.Sum(行=>行单位<0?行单位:0),
TotalOut=g.Sum(行=>行单位<0?行单位*行价格:0),
UnitsIn=g.Sum(行=>行单位>=0?行单位:0),
TotalIn=g.Sum(行=>行单位>=0?行单位*行价格:0),
UnitsDiff=g.Sum(行=>行单位),
TotalDiff=g.Sum(行=>row.Units*row.Price)
};
query.Dump();

@pwilcox和所有其他朋友

这是最后一个linq查询,它给了我绝对的结果!除了上面的查询之外,我还添加了orderby表达式

(from sd in Stockdiaries
join loc in Locations on sd.Location equals loc.Id
join prod in Products on sd.Product equals prod.Id
join cat in Categories on prod.Category equals cat.Id into pCat
from cat in pCat.DefaultIfEmpty()
select new {
    Location = loc.Name,
    Category = cat.Name,
    Reference = prod.Reference,
    Product = prod.Name,
    sd.Units,
    sd.Price
    } into cnd
group cnd by new {cnd.Location,cnd.Reference, cnd.Product, cnd.Category} into g
orderby g.Key.Location, g.Key.Category, g.Key.Product
select new {
        g.Key.Location,
        g.Key.Reference,
        g.Key.Product,
        g.Key.Category,
        UnitsOut = g.Sum(row => row.Units < 0 ? row.Units : 0),
        TotalOut = g.Sum(row => row.Units < 0 ? row.Units * row.Price : 0),
        UnitsIn = g.Sum(row => row.Units >= 0 ? row.Units : 0),
        TotalIn = g.Sum(row => row.Units >= 0 ? row.Units * row.Price : 0),
        UnitsDiff = g.Sum(row => row.Units),
        TotalDiff = g.Sum(row => row.Units * row.Price)

})
(来自股票日记中的sd)
在sd上的位置连接loc。位置等于loc.Id
在sd上的产品中加入产品。产品等于产品Id
将产品类别中的类别加入pCat。类别等于类别Id
来自pCat.DefaultIfEmpty()中的cat
选择新的{
位置=位置名称,
类别=类别名称,
参考=产品参考,
产品=产品名称,
sd.单位:,
标准价格
}进入cnd
按新{cnd.Location,cnd.Reference,cnd.Product,cnd.Category}将cnd分组为g
按g.Key.Location、g.Key.Category、g.Key.Product排序的订单
选择新的{
g、 钥匙,位置,
g、 关键。参考,
g、 关键,产品,,
g、 关键。类别,
UnitsOut=g.Sum(行=>行单位<0?行单位:0),
TotalOut=g.Sum(行=>行单位<0?行单位*行价格:0),
UnitsIn=g.Sum(行=>行单位>=0?行单位:0),
TotalIn=g.Sum(行=>行单位>=0?行单位*行价格:0),
UnitsDiff=g.Sum(行=>行单位),
TotalDiff=g.Sum(行=>row.Units*row.Price)
})

代码在哪里?这只是一个查询,也许这个help@Dom93这不再是一个受支持的应用程序,而且从2016年年中开始就没有了。正如我所说,没有代码很难提供帮助,我不知道您尝试了什么,或者它在哪里抛出了错误error@Dom93我在上面看到的只是一个SQL查询。该查询检索的结果很好。但我需要将此查询转换为C#Linq查询,以便在我的C#应用程序中获得强类型结果。我不知道如何用等效的linq编写上面的sql@Dom93我尝试了LinqPad,但是我的结果与SQL查询结果不同!完美的这绝对是我需要的。非常感谢。