【问题标题】:linq subquery join and group bylinq 子查询加入和分组依据
【发布时间】:2016-12-08 03:48:27
【问题描述】:

您好,是否可以将以下查询转换为 linq ? ... 我正在使用实体框架核心并尝试使用存储过程,但似乎我必须创建一个适用于存储过程元数据的模型。所以我想了解这种查询是否可以翻译成 linq,所以我不必创建单独的数据库模型。

    SELECT 
    Stock.stockID ProductID, 
    stockName ProductName, 
    categoryName ProductCategory, 
    typeName ProductType, 
    sizeName ProductSize, 
    currentQuantity CurrentQuantity, 
    standardQuantity QuantityPerBox, 
    CONVERT(VARCHAR(255),CONVERT(INT,Stock.price)) AvgUnitCost,
    CONVERT(VARCHAR(255),CONVERT(INT,x.lastUnitCost)) LastOrderUnitCost,
    CONVERT(VARCHAR(10),CONVERT(DATE,x.lastOrderDate)) LastOrderDate
FROM dbo.Stock
LEFT JOIN 
(
SELECT stockID,unitPrice lastUnitCost ,orderDate lastOrderDate, ROW_NUMBER() OVER (PARTITION BY stockID ORDER BY orderDate DESC) rn FROM dbo.SalesOrder 
    JOIN dbo.SalesOrderDetail ON SalesOrderDetail.salesOrderID = SalesOrder.salesOrderID
WHERE customerID = @customerID AND salesStatus = 'S'
) x ON x.stockID = Stock.stockID AND rn = 1
LEFT JOIN dbo.StockCategory ON StockCategory.stockCategoryID = Stock.stockCategoryID
LEFT JOIN dbo.StockType ON StockType.stockTypeID = Stock.stockTypeID
LEFT JOIN dbo.StockSize ON StockSize.stockSizeID = Stock.stockSizeID
WHERE disStock = 0

【问题讨论】:

    标签: entity-framework linq


    【解决方案1】:

    几乎一切皆有可能。你只需要注意性能。

    var query = 
        from stock in db.Stocks
        join x in (
          from grp in (
            from so in db.SalesOrders
            join sod in db.SalesOrderDetails on so.SalesOrderId equals sod.SalesOrderId
            where so.CustomerId == customerId && so.SalesStatus == "S"
            orderby so.OrderDate descending
            select new {
                sod.StockId, 
                LastUnitCost = sod.UnitPrice,
                LastOrderDate = so.OrderDate
            } into inner
            group inner by inner.StockId)
          select grp.Take(1)) on x.StockId equals stock.StockId into lastStockSales
        from x in lastStockSales.DefaultIfEmpty()
        join sc in db.StockCategories on stock.StockCatergotyId equals sc.StockCategoryId into scLeft
        from sc in scLeft.DefaultIfEmpty()
        join st in db.StockTypes on stock.StockTypeId equals st.StockTypeId into stLeft
        from st in stLeft.DefaultIfEmpty()
        join ss in db.StockSizes on stock.StockSizeId equals ss.StockSizeId into ssLeft
        from ss in ssLeft.DefaultIfEmpty()
        where stock.DisStock == 0
        select new MyDTO {
          ProductId = stock.StockId,
          ProductName = stock.StockName,
          ProductType = st.TypeName,
          ProductSize = ss.SizeName,
          CurrentQuantity = stock.CurrentQuantity,
          QuantityPerBox = stock.StandardQuantity,
          AvgUnitCost = stock.Price,
          LastOrderUnitCost = x.LastUnitCost,
          LastOrderDate = x.LastOrderDate
        };
    

    正如您所见,重写这些查询很容易,我不得不稍微更改一下有关如何获取库存商品最新销售的逻辑,因为从 LINQ 的角度来看,ROW_NUMBER() OVER (PARTITION... 不受支持。同样,您必须在重写查询时考虑性能。

    希望这会有所帮助。

    【讨论】:

    • 哇..这真的很有帮助!但是考虑到性能..在上下文中创建单独的模型然后可以与存储过程一起使用是更好的做法吗?我遇到的问题是我使用的是数据库优先方法,这意味着我必须创建表并在模型中反映它意味着 sql 数据库中的这个表只是为了在代码中制作模型而创建的......
    • 我会说这取决于您所谈论的数据量。您可以进行一些性能测试以查看此 LINQ 查询是否接近原始查询。 ROW_NUMBER()... 可能会给您更好的性能,但可能不会。做一些测试,看看有什么不同。我的回答只是向您展示了如何从 C# 中表达丰富的查询。您的应用程序将决定什么是最佳方法。 EF 是一个工具(一个很棒的工具),但不是唯一的。您可以决定混合使用工具,这不是一个坏方法。为了给最终用户提供最好的体验,我已经做了很多次了。
    • 就必须添加另一个模型来处理存储过程的结果而言,这将是您当前唯一的解决方案。我希望在不久的将来添加更好的原始 SQL 支持,就像 EF 6 今天提供的 Database.SqlQuery<T>(...) 方法一样。
    • 感谢它真的帮了很多忙。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多