嵌套查询实体框架

时间:2018-09-08 07:39:31

标签: entity-framework linq

在将下面的SQL嵌套查询转换为LINQ查询时需要帮助吗?

select P.ProductId, P.Name, C.Name, I.Image
from Product P 
join ProductImage I on P.ProductId = I.ProductId
join ProductCategory C on P.Category = C.CategoryId
where P.ProductId in (select distinct ProductId
                      from ProductVariantMapping M
                      where M.GUID in (select top 3 V.Guid
                                       from [Order] O 
                                       join Inventory V on V.InventoryId = O.InventoryId
                                       group by O.InventoryId, V.Guid
                                       order by Sum(O.Quantity) desc))

以下是我尝试转换为LINQ查询的尝试:

var a = (from product in ekartEntities.Products
         join productImage in ekartEntities.ProductImages
                        on product.ProductId equals productImage.ProductId
         join category in ekartEntities.ProductCategories
                        on product.Category equals category.CategoryId
         where product.ProductId
         select new ProductDTO()
                    {
                            ProductId = product.ProductId,
                            Name = product.Name,
                            Category = category.Name,
                            Image = productImage.Image
                    }).ToList();

转换为LINQ时等效于“ IN”。

我得到了'IN'子句的解决方案。 但是,如何在分组后按顺序使用sum(Quantity)?

我是实体框架的新手。谁能帮我吗?

2 个答案:

答案 0 :(得分:2)

在LINQ中,您将需要使用“ contains()”方法来生成“ IN”,您需要在Contains方法中放置一个列表。如果发送查询,该查询将重复执行以完成操作,这将导致性能下降。

示例:

var sampleList = (from order ekartEntities.Order
                  join inventory in ekartEntities.Inventory on order.InventoryId equals inventory.InventoryId
                  select order).toList();

var query = (from product in ekartEntities.Products
                        join productImage in ekartEntities.ProductImages
                        on product.ProductId equals productImage.ProductId
                        join category in ekartEntities.ProductCategories
                        on product.Category equals category.CategoryId
                     where sampleList.Contains(product.ProductId)
                        select new ProductDTO()
                        {
                            ProductId = product.ProductId,
                            Name = product.Name,
                            Category = category.Name,
                            Image = productImage.Image
                        }).ToList();

答案 1 :(得分:0)

不要在第一个查询中应用 ToList()

我做了一些测试。

测试 1(使用我自己的数据):

    var phIds = new List<string>
    {
        //List of Ids
    };
    using (var db = new ApplicationDbContext())
    {
        var studentsId = db.Relations
            .Where(x => phIds.Contains(x.RelationId))
            .Select(x => x.Id)
            .Distinct(); //IQueryable here
        var studentsQuery = from p in db.Students
            where studentsId.Contains(p.Id)
            select p;

        var students= studentsQuery .ToList();
    }

生成的查询如下所示:

SELECT 
    [Extent1].[Id] AS [Id], 
    [...]
    FROM [dbo].[Students] AS [Extent1]
    WHERE  EXISTS (SELECT 
        1 AS [C1]
        FROM ( SELECT DISTINCT 
            [Extent2].[StudentId] AS [StudentId]
            FROM [dbo].[Relations] AS [Extent2]
            WHERE ([Extent2].[RelationId] IN (N'ccd31c3d-dfa3-4b40-...', N'd2cb05a2-ece3-4060-...'))
        )  AS [Distinct1]
        WHERE [Distinct1].[StudentId] = [Extent1].[Id]
    )

查询看起来和我想要的完全一样

但是,如果您在第一个查询中添加 ToList() 以获取 ID,您将不再拥有 IQueryable 而是一个列表。

测试 2:错误(我添加了 ToList):

var phIds = new List<string>
{
    //List of Ids
};
using (var db = new ApplicationDbContext())
{
    var studentsId = db.Relations
        .Where(x => phIds.Contains(x.RelationId))
        .Select(x => x.Id)
        .Distinct().ToList(); // No longer IQueryable but a list of 3000 int
    var studentsQuery = from p in db.Students
        where studentsId .Contains(p.Id)
        select p;

    var students= studentsQuery .ToList();
}

生成的查询很难看:

SELECT 
    [Extent1].[Id] AS [Id], 
    [...]
    FROM [dbo].[Patients] AS [Extent1]
    WHERE [Extent1].[Id] IN (611661, 611662, 611663, 611664,.... 
    //more than 3000 ids here
    )