使用列表中的列表将 Dapper 多映射结果聚合到对象
Aggregating Dapper Multi Mapping Results To Object with List Within a List
我对 dapper 比较陌生,并试图聚合它的数据 returns。我试图弄清楚如何将结果映射到具有列表 属性 的对象,该列表也具有列表 属性.
我的对象:
public class Employee()
{
public string Id { get; set; }
public string Name { get; set; }
public List<Employement> Employments { get; set; }
}
public class Employment()
{
public string CompanyId { get; set; }
public string Company { get; set; }
public DateTime HireDate { get; set; }
public List<JobInfo> JobInfo { get; set; }
}
public class JobInfo()
{
public string JobTitle { get; set; }
public string Salary { get; set; }
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
}
我的方法:
var historyDictionary = new Dictionary<string, Employee>();
var results = await connection.QueryAsync<Employee, Employment, JobInfo, Employee>(
sqlQuery,
(e, em, ji) => {
Employee emp;
if (!lookup.TryGetValue(e.Id, out emp))
historyDictionary .Add(e.Id, emp = e);
if (emp.Employments == null)
emp.Employments = new List<Employment> { em };
else if (!emp.Employments.Exists(ec => ec.CompanyId == em.CompanyId))
emp.Employments.Add(em);
//map JobInfo
return emp;
}, SplitOn: "Id"
);
我似乎无法全神贯注地映射 JobInfo。我知道我不能只做我在映射 Employment 时正在做的事情,因为它是 Employee 下的列表并且做 Employee.Employments 不会让我直接访问 JobInfo 对象,所以我假设我需要使用 linq
这就是我想要得到的
Id,
Name,
new List<Employment> {
new Employment1 {
CompanyId,
CompanyName,
HireDate,
new List<JobInfo> {
new JobInfo {
JobTitle1,
Salary,
StartDate,
EndDate
},
new JobInfo {
JobTitle2,
Salary,
StartDate,
EndDate
}
}
}
new Employment2 {
CompanyId,
CompanyName,
HireDate,
new List<JobInfo> {
new JobInfo {
JobTitle1,
Salary,
StartDate,
EndDate
}
}
}
}
并希望确保将正确的工作信息映射到正确的工作
另外,我想充分了解dapper mapping,是不是每行数据映射sql个数据?
样本sql数据
Id Name CompanyId Company HireDate JobTitle Salary StartDate EndDate
001 employee1 123 company1 01-01-2010 job1 12345 01-01-2010 01-01-2012
001 employee1 123 company1 01-01-2010 job2 23456 01-01-2012 02-02-2015
001 employee1 456 company2 01-01-2016 job3 34567 03-03-2016 null
002 employee2 123 company1 02-02-2015 job4 23789 02-02-2015 null
首先,你的Dapper查询不太正确:当使用multi-mapping时,对象在结果集中垂直分割(一些列用于父对象,一些用于子),并且您需要提供 split 点,即每个对象的起始列。
然后您将每个对象映射到其嵌套位置,具体取决于它是否存在。对于另一层嵌套,您只需获取上一层并再次查找。
var historyDictionary = new Dictionary<string, Employee>();
var results = await connection.QueryAsync<Employee, Employment, JobInfo, Employee>(
sqlQuery,
(e, em, ji) => {
if (!lookup.TryGetValue(e.Id, out var emp))
historyDictionary.Add(e.Id, emp = e);
if (emp.Employments == null)
emp.Employments = new List<Employment> { em };
else
{
em2 = emp.Employments.Find(ec => ec.CompanyId == em.CompanyId);
if(em2 == null)
emp.Employments.Add(em);
else
em = em2;
}
em.JobInfo = em.JobInfo ?? new List<JobInfo>();
em.JobInfo.Add(ji);
return emp;
}, SplitOn: nameof(Employment.CompanyId) + "," + nameof(JobInfo.JobTitle)
);
您可以通过在构造函数中分配默认 List
对象来稍微简化逻辑。通常我会使用 Dictionary
而不是 List
,这样查找也更简单:
var historyDictionary = new Dictionary<string, Employee>();
var results = await connection.QueryAsync<Employee, Employment, JobInfo, Employee>(
sqlQuery,
(e, em, ji) => {
if (!lookup.TryGetValue(e.Id, out var em2))
historyDictionary.Add(e.Id, em2 = e);
if (!emp.Employments.TryGetValue(em.CompanyId, out var em2))
emp.Employments.Add(em.CompanyId, em2 = em);
em2.JobInfo.Add(ji);
return emp;
}, SplitOn: nameof(Employment.CompanyId) + "," + nameof(JobInfo.JobTitle)
);
您还应该查看 QueryMultiple
,其中有多个 SELECT
查询,您可以自己映射它们。这可以防止在某些情况下出现大量重复行。
我对 dapper 比较陌生,并试图聚合它的数据 returns。我试图弄清楚如何将结果映射到具有列表 属性 的对象,该列表也具有列表 属性.
我的对象:
public class Employee()
{
public string Id { get; set; }
public string Name { get; set; }
public List<Employement> Employments { get; set; }
}
public class Employment()
{
public string CompanyId { get; set; }
public string Company { get; set; }
public DateTime HireDate { get; set; }
public List<JobInfo> JobInfo { get; set; }
}
public class JobInfo()
{
public string JobTitle { get; set; }
public string Salary { get; set; }
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
}
我的方法:
var historyDictionary = new Dictionary<string, Employee>();
var results = await connection.QueryAsync<Employee, Employment, JobInfo, Employee>(
sqlQuery,
(e, em, ji) => {
Employee emp;
if (!lookup.TryGetValue(e.Id, out emp))
historyDictionary .Add(e.Id, emp = e);
if (emp.Employments == null)
emp.Employments = new List<Employment> { em };
else if (!emp.Employments.Exists(ec => ec.CompanyId == em.CompanyId))
emp.Employments.Add(em);
//map JobInfo
return emp;
}, SplitOn: "Id"
);
我似乎无法全神贯注地映射 JobInfo。我知道我不能只做我在映射 Employment 时正在做的事情,因为它是 Employee 下的列表并且做 Employee.Employments 不会让我直接访问 JobInfo 对象,所以我假设我需要使用 linq
这就是我想要得到的
Id,
Name,
new List<Employment> {
new Employment1 {
CompanyId,
CompanyName,
HireDate,
new List<JobInfo> {
new JobInfo {
JobTitle1,
Salary,
StartDate,
EndDate
},
new JobInfo {
JobTitle2,
Salary,
StartDate,
EndDate
}
}
}
new Employment2 {
CompanyId,
CompanyName,
HireDate,
new List<JobInfo> {
new JobInfo {
JobTitle1,
Salary,
StartDate,
EndDate
}
}
}
}
并希望确保将正确的工作信息映射到正确的工作
另外,我想充分了解dapper mapping,是不是每行数据映射sql个数据?
样本sql数据
Id Name CompanyId Company HireDate JobTitle Salary StartDate EndDate
001 employee1 123 company1 01-01-2010 job1 12345 01-01-2010 01-01-2012
001 employee1 123 company1 01-01-2010 job2 23456 01-01-2012 02-02-2015
001 employee1 456 company2 01-01-2016 job3 34567 03-03-2016 null
002 employee2 123 company1 02-02-2015 job4 23789 02-02-2015 null
首先,你的Dapper查询不太正确:当使用multi-mapping时,对象在结果集中垂直分割(一些列用于父对象,一些用于子),并且您需要提供 split 点,即每个对象的起始列。
然后您将每个对象映射到其嵌套位置,具体取决于它是否存在。对于另一层嵌套,您只需获取上一层并再次查找。
var historyDictionary = new Dictionary<string, Employee>();
var results = await connection.QueryAsync<Employee, Employment, JobInfo, Employee>(
sqlQuery,
(e, em, ji) => {
if (!lookup.TryGetValue(e.Id, out var emp))
historyDictionary.Add(e.Id, emp = e);
if (emp.Employments == null)
emp.Employments = new List<Employment> { em };
else
{
em2 = emp.Employments.Find(ec => ec.CompanyId == em.CompanyId);
if(em2 == null)
emp.Employments.Add(em);
else
em = em2;
}
em.JobInfo = em.JobInfo ?? new List<JobInfo>();
em.JobInfo.Add(ji);
return emp;
}, SplitOn: nameof(Employment.CompanyId) + "," + nameof(JobInfo.JobTitle)
);
您可以通过在构造函数中分配默认 List
对象来稍微简化逻辑。通常我会使用 Dictionary
而不是 List
,这样查找也更简单:
var historyDictionary = new Dictionary<string, Employee>();
var results = await connection.QueryAsync<Employee, Employment, JobInfo, Employee>(
sqlQuery,
(e, em, ji) => {
if (!lookup.TryGetValue(e.Id, out var em2))
historyDictionary.Add(e.Id, em2 = e);
if (!emp.Employments.TryGetValue(em.CompanyId, out var em2))
emp.Employments.Add(em.CompanyId, em2 = em);
em2.JobInfo.Add(ji);
return emp;
}, SplitOn: nameof(Employment.CompanyId) + "," + nameof(JobInfo.JobTitle)
);
您还应该查看 QueryMultiple
,其中有多个 SELECT
查询,您可以自己映射它们。这可以防止在某些情况下出现大量重复行。