将 Dapper 一对多(拆分)与泛型结合使用

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

我正在尝试使用 Dapper 以一对多关系映射对象。假设一个数据库包含一个 Departments 表和一个 People 表。 People 表有一个 DepartmentId 列,用于创建人员和部门之间的关系。每个人只能在一个部门。

我的代码中有以下模型:

public class PersonModel
{
    public int Id {get; set;}
    public string FullName {get; set;}
    public DepartmentModel Department {get; set;}
}
public class DepartmentModel
{
    public int Id {get; set;}
    public string Name {get; set;}
}

我想使用 Dapper 来获取 People 并将它们存储在包含 Departments 属性的对象中。 SplitOn 可以做到这一点,如下所示:

public Task<IEnumberable<PersonModel>> GetPeople<PersonModel>(string connectionString)
{
     using var connection = new SqlConnection(connectionString);

     var query = "Select People.Id, People.FullName, Department.Name FROM People LEFT JOIN Departments ON People.Id = Departments.Id";

    return await connection.QueryAsync<PersonModel, DepartmentModel, PersonModel>(query, (person, department) => {
        person.Department = department;
        return person;
    }, 
    splitOn: "Id" );
}

实际问题

到目前为止一切顺利。我现在想要的是使用泛型将其转换为可重用的方法,但我陷入困境,因为我无法使用泛型进行赋值

person.Department = department
,因为
.Department
是我不知道的属性。我不能简单地使用
department
。我也尝试过
model.typeof(TSubModel)
(见下文)。有什么办法可以实现这一点吗?失败的代码是:

public Task<IEnumberable<TModel>> GetPeople<TModel, TSubModel>(string connectionString, string query)
{
     using var connection = new SqlConnection(connectionString);


    return await connection.QueryAsync<TModel, TSubModel, TModel>(query, (model, subModel) => {
        model.subModel= subModel; // <-- obviously model.subModel fails and so does model.typeof(TSubModel). 
        return model;
    }, 
    splitOn: "Id" );
}

PS,OP 回答了一个类似的问题,但没有使用 SplitOn 这里(SO 问题)

c# sql-server dapper
1个回答
0
投票

除非有某种方法可以确定通过反射设置哪个属性,否则这是不可能的。

您可以从外部穿过

Action<TModel, TSubModel>
lambda。

public Task<IEnumberable<TModel>> GetPeople<TModel, TSubModel>(string connectionString, string query, Action<TModel, TSubModel> splitOnAction)
{
    using var connection = new SqlConnection(connectionString);
    return await connection.QueryAsync<TModel, TSubModel, TModel>(query, (model, subModel) => {
        splitOnAction(model, subModel);
        return model;
    }, 
    splitOn: "Id" );
}

var results = await GetPeople<PersonModel, DepartmentModel>(connString, query,
  (person, dep) => person.Deparmtent = dep
);

但目前我不确定直接使用 Dapper 能带来什么好处。最重要的是,您无法传递查询参数或

QueryAsync
所采用的任何其他参数。

我建议你重新考虑尝试“通用”地执行此操作,因为 Dapper 已经为你提供了这一点。

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