Dapper,Lambda表达式并返回正确的映射字段

时间:2016-06-15 15:04:12

标签: c# lambda dapper

我有一个项目不允许我们更改SPROCS,但我想使用一些东西来自动将datareader行映射到POCO类。 来到Dapper来救援。在大多数情况下它工作得很好,但在某些情况下我需要填充嵌套类。 例如,我有这个模型

public class Account
{
    public string AccountNumber { get; set; }

    /* Removed for brevity */

    public Contact Contact { get; set; }
}

public class Contact
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

我的资源库看起来像这样:

/// <summary>
/// Lists a range of items
/// </summary>
/// <param name="storedProcedureName">The name of the SPROC to execute</param>
/// <param name="parameters">The parameters needed for the SPROC</param>
/// <returns></returns>
public async Task<IList<T>> ListAsync(string storedProcedureName, OracleDynamicParameters parameters = null)
{
    return await ExecuteReaderAsync(storedProcedureName, parameters);
}

/// <summary>
/// Private method for executing a reader and returning the results as a list
/// </summary>
/// <param name="storedProcedureName">The name of the SPROC to execute</param>
/// <param name="parameters">The parameters needed for the SPROC</param>
/// <returns></returns>
private async Task<IList<T>> ExecuteReaderAsync(string storedProcedureName, OracleDynamicParameters parameters = null)
{

    // Init command
    InitializeCommand(storedProcedureName, parameters);

    // Dynamically populate our list
    var list = await this._connection.QueryAsync<T>(storedProcedureName, parameters, commandType: CommandType.StoredProcedure);

    // Dispose
    DisposeCommand();

    // Return our list
    return list.ToList();
}

可以从任何服务中调用,如下所示:

return await Repository.ListAsync("IBPA_ORDERS.readLines", parameters);

就像我说的,这适用于没有子课程的POCO课程,但正如您所看到的,帐户模型有一个联系人。 显然,您可以使用 Lambda表达式填充联系人,如下所示:

.Select(x => new Account
{
    AccountNumber = x.AccountNumber 
    Contact = new Contact 
    {
        FirstName = x.Firstname,
        LastName = x.LastName
    }
});

所以,我正在尝试更新我的Repository方法来处理它。 到目前为止,我有这个:

/// <summary>
/// Private method for executing a reader and returning the results as a list
/// </summary>
/// <param name="storedProcedureName">The name of the SPROC to execute</param>
/// <param name="parameters">The parameters needed for the SPROC</param>
/// <returns></returns>
private async Task<IList<T>> ExecuteReaderAsync(string storedProcedureName, OracleDynamicParameters parameters = null, Func<dynamic, T> query = null)
{

    // Init command
    InitializeCommand(storedProcedureName, parameters);

    // Get our models
    var models = await this._connection.QueryAsync(storedProcedureName, parameters, commandType: CommandType.StoredProcedure);

    // If we supply a query, use it. Otherwise cast the result as our type
    var results = query == null ? models.Select(m => (T)m) : models.Select(query);

    // Dispose
    DisposeCommand();

    // Return our list
    return results.ToList();
}

但我不确定这是否正确。 我试着这样称呼它:

// Execute and return our acctuons
return await Repository.ListAsync("IBPA_ACCOUNTSS.LIST", parameters, m => new Account {
    // LineRef = /* m is dynamic */
});

因为 m 是动态的,我实际上无法分配任何属性。

有人能帮助我吗?

1 个答案:

答案 0 :(得分:0)

我可能有点困惑,但我认为你要问的是你是否可以让Dapper执行反序列化,以便正确填充Account.Contact

如果订购了返回的列,以便所有Account属性都是第一个,并且所有Contact属性都在后面,那么您可以使用Dapper的Multi Mapping功能

例如:

Func<Account, Contact, Account> map = (a, c) => { a.Contact = c; return a; };

var results = conn.Query<Account, Contact, Account>(
    sql: storedProcedureName,
    map: map,
    splitOn: "FirstName",
    param: parameters,
    commandType: CommandType.StoredProcedure);

在上面的代码中,Dapper期望从Account解除启发。然后,当它到达名为&#34; FirstName&#34;的列时,它将开始反序列化为Contact。完成后,它会调用map,它会将所有反序列化类型合并为一个返回值(Account)。

类型参数可以看作:<DeserializeType1, DeserializeType2, ..., ReturnType>

splitOn参数默认为&#34; Id&#34;因为它通常是任何表的第一个列名。我相信splitOn也接受以逗号分隔的列名列表,如果您要组合两个以上的表,并且拆分列不同,这可能很方便。

如果查询/ SProc的结果没有任何特定顺序(比如它按FirstNameAccountNumberLastName的顺序返回了列),那么Dapper&#39;无法帮助你。