我正在为我的网络应用程序使用asp.net mvc,dapper和MySql存储过程。 到目前为止,对于每个页面我都有1-3个存储过程调用。 我最近发现我的主机只提供10个并行连接,所以我想将每个调用组合成一个。 我已经在数据库中创建了必要的存储过程,但我的问题是以通用的方式使用dapper来获取程序结果。
我想要的是制作一个通用函数: 1)存储过程名称。 2)存储过程返回的类型列表。对于每种类型,如果它是Single / ToList。 泛型函数应该生成一个变量列表,它是存储过程的结果。
dapper页面中的示例显示了如何进行非通用的QueryMultiple调用:
var sql =
@"
select * from Customers where CustomerId = @id
select * from Orders where CustomerId = @id
select * from Returns where CustomerId = @id";
using (var multi = connection.QueryMultiple(sql, new {id=selectedId}))
{
var customer = multi.Read<Customer>().Single();
var orders = multi.Read<Order>().ToList();
var returns = multi.Read<Return>().ToList();
...
}
基本上,我想要的是将Customer,Order,Return类型插入到一个字典中,该字典会将每个类型声明为Single或ToList,然后执行以下操作:
var result = new List<dynamic>();
var sql =
@"
select * from Customers where CustomerId = @id
select * from Orders where CustomerId = @id
select * from Returns where CustomerId = @id";
using (var multi = connection.QueryMultiple(sql, new {id=selectedId}))
{
foreach(var item in dictionary)
{
if (item.Value.equals("Single"))
result.Add(multi.Read<item.Key>().Single());
else if (item.Value.equals("ToList"))
result.Add(multi.Read<item.Key>().ToList());
}
}
return result;
我的问题是,visual studio说:
The type or namespace name 'item' could not be found
指向'item':multi.Read()
我做错了什么? 有没有更好的方法来实现使用dapper的QueryMultiple的泛型函数?
答案 0 :(得分:2)
虽然这是一个古老的话题,但认为它可能对其他人有所帮助。在这种情况下,您可以使用下面的代码使其工作。将Read函数中的类型作为参数传递。你可以返回动态。使用Expando对象可以动态生成属性。
我更喜欢创建像下面这样的对象,并将对象列表传递给函数,这将为您生成动态返回类型。
public class MapItem
{
public Type Type { get; private set; }
public DataRetriveTypeEnum DataRetriveType { get; private set; }
public string PropertyName { get; private set; }
public MapItem(Type type, DataRetriveTypeEnum dataRetriveType, string propertyName)
{
Type = type;
DataRetriveType = dataRetriveType;
PropertyName = propertyName;
}
}
//And then make a reusable function like below
public async Task<dynamic> ExecuteQueryMultipleAsync(IDbConnection con, string spName, object param = null,IEnumerable<MapItem> mapItems = null)
{
var data = new ExpandoObject();
using (var multi = await con.QueryMultipleAsync(spName,param, commandType:CommandType.StoredProcedure))
{
if (mapItems == null) return data;
foreach (var item in mapItems)
{
if (item.DataRetriveType == DataRetriveTypeEnum.FirstOrDefault)
{
var singleItem = multi.Read(item.Type).FirstOrDefault();
((IDictionary<string, object>) data).Add(item.PropertyName, singleItem);
}
if (item.DataRetriveType == DataRetriveTypeEnum.List)
{
var listItem = multi.Read(item.Type).ToList();
((IDictionary<string, object>)data).Add(item.PropertyName, listItem);
}
}
return data;
}
}
以下如何调用上述方法:
var mapItems = new List<MapItem>()
{
new MapItem(typeof(YourObject1), DataRetriveTypeEnum.FirstOrDefault, "Object1"),
new MapItem(typeof(YourObject2), DataRetriveTypeEnum.List, "Object2")
};
var response = await ExecuteQueryMultipleAsync(name, request, mapItems);
var object1 = response.Result.Object1;
var listOfObject2 = ((List<dynamic>)response.Result.Object2).Cast<YourObject2>();
希望这会有所帮助。
干杯
答案 1 :(得分:0)
我认为可以使用替代方法代替QueryMultiple()
方法,您可以使用
IDbConnection.ExecuteReader()
来自Dapper.SqlMapper
的扩展方法,它返回IDataReader
,您可以遍历它并通过reader.NextResult()
获取结果集并将其映射到您的对象。