1

查询有问题,请看一下。我的目标是:

  • 我需要一个接Products一个Image
  • ProductsValues一些关于产品的附加信息,如规格等。
  • Image并且Values可以是null
  • ProductsImage和返回所有Values
  • 因为Values我只需要Ids这样就可以了List<int> of Values
  • ProductValues并且ImageObjects是关系的连接表->Products可以有很多ProductValuesProducts可以有很多ImageObjects但可以有一个Image
  • DistinctBy来自more linq

问题我不知道如何以Values正确的方式聚合以返回Values每个列表Product

PS我也在使用更多的linq

var q1 = (from p in Products
        join pv in ProductValues on p.ProductId equals pv.ProductId into ljpv
        from pv in ljpv.DefaultIfEmpty()
        select new
            {
                ProductId = p.ProductId,
                Description = p.Description,
                Name = p.Name,
                Price = p.Price,
                Quantity = p.Quantity,
                Type = p.Type,
                Values = (from v in ValueTypes 
                            where v.ValueId == pv.ValueId 
                            select new {
                             ValueId = v.ValueId
                            }).ToList(),
                ImageObjects = (from io in ImageObjects
                                where io.ProductId == p.ProductId && io.IsDefault == true
                                select new 
                                    {
                                               Image = io.Image,
                                               IsDefault = io.IsDefault,
                                               ProductId = io.ProductId
                                    })
                                .ToList()
            })
        .DistinctBy(x=>x.Name)
        .OrderBy(x=>x.Name);
q1.Dump();

回答 Values = (from tmp in ljpv select new { ValueId = tmp.ValueId}),

我知道这不是回答的地方,但是有人会对我的代码有任何建议,或者可以更清楚或更快地完成。我一直想知道如何做这个查询很长一段时间,但是当我写信给你时,我感到眼花缭乱:)


回答后@Harald Coppoolse- 代码更快!

                return context.Product.GroupJoin(
                    context.ProductValue,
                    context.ImageObject.Include(x => x.Image),
                    p => p.ProductId,
                    pv => pv.ProductId,
                    io => io.ProductId,
                    (p, pv, io) => new ProductModel
                    {
                        ProductId = p.ProductId,
                        Name = p.Name,
                        Price = p.Price,
                        ProductValue = pv
                            .Select(npv => new ProductValueModel
                            {
                                ProductId = npv.ProductId,
                            }).ToList(),
                        ImageObject = io
                            .Select(nio => new ImageObjectModel
                            {
                                Image = nio.Image.DtoToModel(),
                                IsDefault = nio.IsDefault,
                                ProductId = nio.ProductId
                            }).ToList(),
                    });
4

1 回答 1

2

因此,您有一个表 ofProducts和一个ProductValues具有一对多关系的表: everyProduct有零个或多个ProductValues,并且ProductValueeach 恰好属于 one Product,即Product外键ProductId指向的 。

你想要(几个属性) all Products,每个Product都有它的ProductValues. 之后你DistinctByOrderBy,但这不是你的问题。

每当您想要“带有子项目的项目”,例如“学校和学生”、“客户及其订单”、“订单及其订单行”时,请考虑使用Enumerable.GroupJoin

GroupJoin 实际上是一个左外连接,后跟一个 GroupBy。

var productsWithTheirProductValues = products.GroupJoin(  // GroupJoin Products
    productValues,                                        // with ProductValues
    product => product.ProductId,           // from every Product take the ProductId
    productValue => productValue.ProductId, // from every ProductValue take the foreign key

    // ResultSelector: take the product with its zero or more matching ProductValues
    // to make a new object:
    (product, productValuesOfThisProduct) => new
    {
        // Select only the product properties you plan to use:
        Id = product.Id,
        Name = product.Name,
        Price = product.Price,
        ...

        ProductValues = productValuesOfThisProduct
            // only if you don't want all ProductValues of this product:
            .Where(productValue => ...)   

            .Select(productValue => new
            {
                // again select only the properties you plan to use
                Id = productValue.Id,
                ...

                // not needed: the foreign key, you already know the value
                // ProductId = productValue.ProductId,
            })
            .ToList(),
    });

在您的情况下,您不想 GroupJoin 两个序列,而是三个序列。你需要做一个额外的 GroupJoin:

var result = products.GroupJoin(productValues,
    product => product.ProductId,
    productValue => productValue.ProductId,

    // ResultSelector: remember the product and all its productValues
    (product, productValuesOfThisProduct) => new
    {
        Product = product,
        ProductValues = productValuesOfThisProduct,
    })

    // now do the 2nd join:
    .GroupJoin(imageObjects,
        firstJoinResult => firstJoinResult.Product.ProductId,
        imageObject => imageObject.ProductId,

        // result selector:
        (firstJoinResult, imageObjectsOfThisProduct) => new
        {
            Product = firstJoinResult.Product,
            ProductValues = firstJoinResult.ProductValues,
            ImageObjects = imageObjectsOfThisProduct,
        })

        // take each element of this group join result and select the items that you want
        .Select(joinResult => new
        {
            ProductId = joinResult.Product.ProductId,
            Price = joinResult.Product.Price,
            ...

            ProductValues = joinResult.ProductValues.Select(productValue => new
            {
                 ...
            })
            .ToList(),

            ImageObjects = joinResult.ImageObjects.Select(imageObject => new
            {
                ...
            })
            .ToList(),
       });

这看起来很可怕。因此,如果您必须更频繁地对三个表进行 GroupJoin,请考虑为三个表创建 GroupJoin:

static IEnumerable<TResult> GroupJoin<T1, T2, T3, TKey, TResult>(
   this IEnumerable<T1> source1, IEnumerable<T2> source2, IEnumerable<T3> source3,
   Func<T1, TKey> key1Selector,
   Func<T2, TKey> key2Selector,
   Func<T3, TKey> key3Selector,
   Func<T1, IEnumerable<T2>, IEnumerable<T3>, TResult> resultSelector)
{
     // put all source2 and source3 elements in lookuptables, using the keyselector
     var lookup2 = source2.ToLookup(item => key2Selector(item));
     var lookup3 = source3.ToLookup(item => key3Selector(item));

     // now for every source1 item, get all source2 and source3 items with the same key
     // and create the result:
     foreach (var item1 in source1)
     {
         TKey key1 = key1Selector(item1);
         IEnumerable<T2> items2 = lookup2[key1];
         IEnumerable<T3> items3 = lookup3[key1];
         // returns empty collection if no items with this key

         TResult result = resultSelector(item1, items2, items3);
         yield return result;
    }
}

用法:

var result = products.GroupJoin(productValues, imageObjects,
   product => product.ProductId,
   productValue => productValue.ProductId,
   imageObject => imageObject.ProductId,

   (product, productValues, imageObjects) => new
   {
       ProductId = product.ProductId,
       ...

       ProductValues = productValues.Select(productValue => new
       {
          ...
       }),
       ImageObjects = imageObjects.Select(imageObject => new
       {
          ...
       }),
    }); 
于 2019-04-25T09:34:31.623 回答