我有一个项目不允许我们更改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 是动态的,我实际上无法分配任何属性。
有人能帮助我吗?
答案 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的结果没有任何特定顺序(比如它按FirstName
,AccountNumber
,LastName
的顺序返回了列),那么Dapper&#39;无法帮助你。