您将如何使用 EF/Linq 执行 MultiMap?

问题描述 投票:0回答:1

我试图从具有一对多关系的 SQL 语句中获取返回结果,并将其映射到具有标头信息和“多”表中的对象子集的模型。

我当前正在使用实体框架生成查询:

var result = from PI in PersonId
             join ab in Breakfast on PI.BreakfastId equals ab.Id into abTemp
             from AB in abTemp
             join al in Lunch on PI.LunchId equals al.Id into alTemp
             from AL in alTemp
             join ad in Dinner on PI.DinnerId equals ad.Id into adTemp
             from AD in adTemp
             select new Person {
                ...?
             }

SQL 的返回看起来像这样:

身份证 姓名 吃早餐 吃午餐 吃晚餐
123 蒂姆 鸡蛋 火腿三明治 牛排
123 蒂姆 培根 薯片 土豆
456 莎伦 麦片 鸡肉卷 沙拉
456 莎伦 烤鸡
789 拉尔夫 麦片 烤宽面条

我想将其放入以下型号的列表中:

public class Person
{
   public decimal Id {get; set;}
   public string Name {get; set;}
   public IEnumerable<string> AteForBreakfast {get; set;}
   public IEnumerable<string> AteForLunch {get; set;}
   public IEnumerable<string> AteForDinner {get; set;}
}

在将 Dapper 与 QueryAsync 和 MultiMap 一起使用之前,我已经看到过这样做,但似乎找不到使用 Entity Framework 和 Linq 的等效方法。

我已经尝试了一些事情,从执行“group by”到尝试从左连接转储到的分组“temp”中提取数据,但是 group by 杀死了性能(在分页)并不断收到无法评估临时组的错误。

我不确定我是否遗漏了某些内容或错误地处理了此映射。任何帮助将不胜感激,提前谢谢您!

c# entity-framework linq asp.net-core multidimensional-array
1个回答
0
投票

我试图从具有一对多的 SQL 语句中获取返回 关系并将其映射到具有标头信息和 “许多”表中的对象子集。

根据您的场景,虽然 Entity Framework 没有直接相当于 Dapper 的 QueryAsync 和 MultiMap,但您可以在 Linq 查询中使用 SelectMany 和匿名类型的组合来实现类似的多重映射结果

让我们考虑一下,您有以下课程:

型号:

public class PersonId { public decimal Id { get; set; } public string Name { get; set; } public int? BreakfastId { get; set; } public int? LunchId { get; set; } public int? DinnerId { get; set; } } public class Breakfast { public int Id { get; set; } public string Name { get; set; } } public class Lunch { public int Id { get; set; } public string Name { get; set; } } public class Dinner { public int Id { get; set; } public string Name { get; set; } } public class Person { public decimal Id { get; set; } public string Name { get; set; } public List<string> AteForBreakfast { get; set; } public List<string> AteForLunch { get; set; } public List<string> AteForDinner { get; set; } }
现在为了实现您的要求,我们可以在每个导航属性上使用 SelectMany,而不是加入每个餐桌。 SelectMany 将集合的集合扁平化为单个集合。让我们看看我们如何实现它:

重构查询:

var result = from PI in personIds join ab in breakfasts on PI.BreakfastId equals ab.Id into abTemp from AB in abTemp.DefaultIfEmpty() join al in lunches on PI.LunchId equals al.Id into alTemp from AL in alTemp.DefaultIfEmpty() join ad in dinners on PI.DinnerId equals ad.Id into adTemp from AD in adTemp.DefaultIfEmpty() group new { AB, AL, AD } by new { PI.Id, PI.Name } into g select new Person { Id = g.Key.Id, Name = g.Key.Name, AteForBreakfast = g.Select(x => x.AB != null ? x.AB.Name : null).Where(x => x != null).ToList(), AteForLunch = g.Select(x => x.AL != null ? x.AL.Name : null).Where(x => x != null).ToList(), AteForDinner = g.Select(x => x.AD != null ? x.AD.Name : null).Where(x => x != null).ToList() };
输出:

注意:我只是尝试使用示例虚拟数据,因此很少有列包含我允许为空的数据,您可以使用真实数据和场景进行测试,并可以根据您的要求重新配置。另外,如果您想了解更多,请参考这个官方文档

© www.soinside.com 2019 - 2024. All rights reserved.