#c# #dapper
#c# #dapper
Вопрос:
В Dapper можно запросить список с помощью where, используя этот код:
var sql = "SELECT * FROM Invoice WHERE Kind IN @Kind;";
using (var connection = My.ConnectionFactory())
{
connection.Open();
var invoices = connection.Query<Invoice>(sql, new {Kind = new[] {InvoiceKind.StoreInvoice, InvoiceKind.WebInvoice}}).ToList();
}
Но я хотел бы запросить список продуктов нескольких поставщиков и их код продукта. Поэтому, чтобы сделать это, я попытался создать массив массивов. Это мой метод в моем репозитории:
public Dictionary<int, Dictionary<string, Product>> GetGroupedListByRelationIdAndProductCode(Dictionary<int, List<string>> productKeysByRelationId)
{
Dictionary<int, Dictionary<string, Product>> list = new Dictionary<int, Dictionary<string, Product>>();
string sql = "SELECT * FROM Products WHERE 1=1 ";
int i = 0;
foreach (KeyValuePair<int, List<string>> productKeys in productKeysByRelationId)
{
sql = sql " AND (ManufacturerRelationId = " productKeys.Key " AND ManufacturerProductCode in @ProductCodeList[" i "] )";
i;
}
using (var conn = _connectionFactory.CreateConnection())
{
conn.Open();
var param = new { ProductCodeList = productKeysByRelationId.Select(x => x.Value.ToArray()).ToArray() };
var productsList = conn.Query<Product>(sql, param).ToList();
if (productsList.Count > 0)
{
foreach (var product in productsList)
{
list[product.ManufacturerRelationId][product.ManufacturerProductCode] = product;
}
}
}
return list;
}
Это дает мне эту ошибку, хотя: System.ArgumentException: 'No mapping exists from object type System.String[] to a known managed provider native type.'
Любые предложения о том, как это сделать?
Ответ №1:
У вас есть несколько проблем с вашим кодом.
Если у вас есть более одного элемента в вашем productKeysByRelationId
, вы в конечном итоге получите SQL, подобный:
WHERE 1=1 AND ManufacturerRelationId = 1 ... AND ManufacturerRelationId = 2
Это вряд ли вернет какие-либо результаты, вам нужно добавить туда несколько ИЛИ.
Ошибка, которую вы получаете, заключается в том, что у вас есть что-то вроде:
AND ManufacturerProductCode in @ProductCodeList[0]
Dapper не может справиться с этим. В основном ожидается, что параметры запроса будут объектом с точно названными элементами нескольких простых типов или массивов.
К счастью, у Dapper есть решение этой проблемы, DynamicParameters на помощь!
Вы можете построить свой запрос следующим образом:
var queryParams = new DynamicParameters();
foreach (var productKeys in productKeysByRelationId)
{
sql = sql $" ... AND ManufacturerProductCode in @ProductCodeList{i} )";
queryParams.Add($"ProductCodeList{i}", productKeys.Value);
i ;
}
Теперь у вас есть параметры вашего запроса в правильном формате, так что вы можете просто сделать это:
var productsList = conn.Query<Product>(sql, queryParams).ToList();
Это должно это исправить, но вы действительно должны попытаться параметризовать ManufacturerRelationId
also. Речь идет не только о внедрении SQL, могут быть некоторые проблемы, связанные с производительностью кэша SQL.
Вы также можете получить некоторую ясность в коде, используя SqlBuilder от Dapper.Contrib.