这是我的dto.Worker
表:
| id | first_name | current_branch |
|----|------------|----------------|
| 1 | Adam | 5 |
从表中获取数据的方式如下:
public async Task<WorkerDTO> GetById(int workerId)
{
using (var connection = connectionFactory.GetConnection())
{
string sQuery = $@"SELECT * FROM dto.Worker WITH(NOLOCK) WHERE id = @WorkerId";
return await connection.QueryFirstAsync<WorkerDTO>(sQuery, new { WorkerId = workerId }).ConfigureAwait(false);
}
}
WorkerDTO
类具有与dto.Worker
表相同的结构,但属性不包含_
字符:
public class WorkerDTO
{
public int Id {get; set;}
public string FirstName {get; set;}
public int CurrentBranch {get; set;}
}
还有一个dto.Job
表:
| id | job_name |
|----|----------|
| 1 | foo |
Anddto.WorkerJob
table:
| worker_id | job_id |
|-----------|--------|
| 1 | 1 |
我想获取所有工人及其工作。我已经确定我需要使用multi mapping dapper feature
。我带来了这样的东西:
public async Task<IEnumerable<WorkerJobDTO>> GetAllWorkersJobs()
{
using (SqlConnection connection = connectionFactory.GetConnection())
{
var sQuery = $@"SELECT worker.*, job.* FROM dbo.Worker worker
LEFT JOIN dbo.WorkerJob workerJob ON workerJob.worker_id = worker.id
LEFT JOIN dbo.Job job ON job.id = workerJob.job_id";
var workers = await connection.QueryAsync<WorkerJobDTO, JobDTO, (WorkerJobDTO workerJob, JobDTO job)>(sQuery, (worker, job) => (worker, job), parameters).ConfigureAwait(false);
return workers.GroupBy(x => x.worker.Id)
.Select(group =>
{
var worker = group.First().worker;
worker.Jobs = group
.Select(x => x.job)
.Where(x => x != null)
.ToList();
return worker;
});
}
}
不幸的是,这不起作用,因为WorkerJobDTO
属性名称和数据库列名之间存在不匹配。要解决这个问题,我必须更改WorkerJobDTO
类从:
public class WorkerJobDTO
{
public int Id {get; set;}
public string FirstName {get; set;}
public int CurrentBranch {get; set;}
public List<JobDTO> Jobs {get; set;}
}
:
public class WorkerJobDTO
{
public int id {get; set;}
public string first_name {get; set;}
public int current_branch {get; set;}
public List<JobDTO> Jobs {get; set;}
}
有没有办法解决这个问题,而不修改DTO
模型的属性名称?
如果指定每个列和别名,则可以更改查询返回的名称。无论如何,选择"*"都不是最佳实践,因为与显式指定列相比,在服务器中会有一些性能损失。将您的查询更改为:
var sQuery = $@"SELECT worker.id AS Id,
worker.first_name AS Name,
worker.current_branch AS CurrentBranch,
job.* FROM dbo.Worker worker
LEFT JOIN dbo.WorkerJob workerJob ON workerJob.worker_id = worker.id
LEFT JOIN dbo.Job job ON job.id = workerJob.job_id";
那将是一个快速修复。但是,您的多映射代码看起来不像标准代码,而且我不知道您需要WorkerJobDTO做什么,毕竟它只是一个链接表。我要把整个东西改成这样:
public async Task<IEnumerable<WorkerJobDTO>> GetAllWorkersJobs()
{
using (SqlConnection connection = connectionFactory.GetConnection())
{
var workerDictionary = new Dictionary<int, WorkerDTO>();
var sQuery = $@"SELECT worker.*, job.* FROM dbo.Worker worker
LEFT JOIN dbo.WorkerJob workerJob ON workerJob.worker_id = worker.id
LEFT JOIN dbo.Job job ON job.id = workerJob.job_id";
var workers = await connection.QueryAsync<WorkerDTO, JobDTO, WorkerDTO>(sQuery,
(worker, job) =>
{
WorkerDTO workerEntry;
if (!workerDictionary .TryGetValue(worker.Id, out workerEntry))
{
workerEntry = worker;
workerEntry.Jobs = new List<JobDTO>(); // only if it's not done in the default constructor
workerDictionary.Add(worker.Id, workerEntry);
}
workerEntry.Jobs.Add(job);
return null; // This doesn't matter, the result will be in workers
}, parameters).ConfigureAwait(false);
}
}
这几乎是Dapper中标准的多映射模式,并且不需要后燃。