如何使用Linq-to-SQL在查询结果中创建摘要列?

时间:2018-07-31 19:48:30

标签: linq linq-to-sql

假设我们有以下表格:

CAR
ID  Name
1   Mustang
2   Taurus

CAR_PART
ID   CAR_ID   PART_NUMBER
1    1        M772
2    1        A443
3    2        Z889

CAR_COLOR
ID     CAR_ID  COLOR_NAME
1      1       Red
2      1       Blue
3      2       Yellow

我们需要使用Linq-to-SQL来获得以下结果:

CAR_ID   CAR_NAME   CAR_PART_LIST     CAR_COLOR_LIST
1        Mustang    M772,A443         Red,Blue

这将如何实现?我用结果列名称创建了一个新类,并在末尾添加了一个select new MyClass{};,但不确定如何处理CAR_PART_LISTCAR_COLOR_LIST的多个分组列。

有什么想法吗?


编辑:这是我到目前为止的内容:

from car in db.CAR
join part in db.CAR_PART on car.ID equals part.CAR_ID
join color in db.CAR_COLOR on car.ID equals color.CAR_ID
where car.ID = 1
select new MySearchResult{
     CAR_ID = car.ID,
     CAR_NAME = car.Name,
     CAR_PART_LIST = ?,
     CAR_COLOR_LIST = ?
}

public class MySearchResult{
    public int CAR_ID { get; set; }
    public string CAR_NAME { get; set; }
    public string CAR_PART_LIST { get; set; }
    public string CAR_COLOR_LIST { get; set; }

    public MySearchResult() { }
}

4 个答案:

答案 0 :(得分:1)

使用明显的String扩展方法:

public static string Join(this IEnumerable<string> s, string sep) => String.Join(s, sep);

您可以通过在每个相关表上使用组联接来计算答案:

var ans = from car in db.CAR
          join part in db.CAR_PART on car.ID equals part.CAR_ID into partj
          join color in db.CAR_COLOR on car.ID equals color.CAR_ID into colorj
          where car.ID == 1
          select new MySearchResult {
              CAR_ID = car.ID,
              CAR_NAME = car.Name,
              CAR_PART_LIST = partj.Select(p => p.PART_NUMBER).Join(","),
              CAR_COLOR_LIST = colorj.Select(c => c.COLOR_NAME).Join(",")
          };

答案 1 :(得分:1)

您是否为db.CAR_PART和db.CAR_COLOR设置了外键?如果是这样,该linq-to-sql将自动为您提供联接的属性。因此,它变为:

var q = from car in db.Car
where car.ID == 1
select new MySearchResult
{
    CAR_ID = car.ID,
    CAR_NAME = car.Name,
    CAR_PART_LIST = String.Join(",", car.CAR_PARTs.Select(cp=>cp.PART_NUMBER))
    CAR_PART_LIST = String.Join(",", car.CAR_COLORs.Select(cp=>cp.COLOR_NAME))
};

答案 2 :(得分:1)

我在这里{{3}}上写下了它,请查看:

    var q = from car in cars
    join part in carparts on car.ID equals part.CAR_ID  into parts
    join color in carcolors on car.ID equals color.CAR_ID into clrs
    where  car.ID == 1

 select new MySearchResult{
 CAR_ID = car.ID,
 CAR_NAME =  car.Name,
 CAR_PART_LIST =  String.Join(",",parts.Select(p => p.PART_NUMBER)),
 CAR_COLOR_LIST = String.Join(",",clrs.Select(c => c.COLOR_NAME))};

        foreach (var item in q)
            Console.WriteLine("{0} {1} {2} {3}",
                item.CAR_ID,
                item.CAR_NAME,
                item.CAR_PART_LIST,
                item.CAR_COLOR_LIST);

答案 3 :(得分:1)

因此,您有一个CarParts表,其中每个CarPart都有一个CarId和一个PartNumber;并且您有一个CarColours表,其中每个CarColour都有一个Carid和一个ColourName

我假设您不支持隐形车,所以每辆车至少都有一个零件和一种颜色。

您想要一个所有CarIds的序列,每个CarIdCarName,属于这个CarParts(=此CarId作为外键)和属于该CarId的所有ColourNames的列表(再次使用外键。

要做到这一点,首先我们要获得所有CarId和所有CarIds with their CarParts,然后我们可以CarIds with their ColourNames在通用Join上获得结果。

如果您认为可能有没有零件或没有颜色的汽车,则需要执行“完全外部联接”而不是常规联接。这不是标准LINQ的一部分,但是您可以自己编写扩展功能。参见LINQ Full Outer Join

在普通CarId上加入联接后,我们将结果与您在CarId上的Cars联接

CarId

最后将所有颜色和零件的汽车连接起来:

var partsGroupedByCarId = carParts.GroupBy(     // make groups of carParts
    carPart => carPart.CarId);                  // with common CarId as Key

var coloursGroupedByCarId = carColours.GroupBy( // make groups of carColours
    carColour => carColour.CarId);,             // with common CarId as Key

var joinResult = partsGroupedByCarId.Join(      // Join the two groups
    coloursGroupedByCarId,
    partGroup => partGroup.Key,                 // from each group of parts take the key (= CarId)
    colourGroup =>                              // from each group of colours take the key (= CarId)
    (partGroup, colourGroup) => new             // when they match make a new object
    {
        CarId = partGroup.Key,                  // with the common CarId
        CarParts = partGroup                    // all partNumbers of the car with CarId
           .Select(item => item.PartNumber),
        CarColours = colourGroup                 // all colourNames of the car with carId
            .Select(item => item.ColourName),
    });

TODO:考虑创建一个大型LINQ语句。由于所有语句都使用延迟执行,因此我认为这不会提高效率。当然会降低可读性。