Ответ 1
Текущий исходный код (еще не выпущенный для NuGet) решает эту проблему; должно работать следующее:
var result = conn.Query(
"select code, name from mytable where id = ?id? order by name",
new { id = 1 });
Этот запрос вызывает ошибку No value given for one or more required parameters
:
using (var conn = new OleDbConnection("Provider=..."))
{
conn.Open();
var result = conn.Query(
"select code, name from mytable where id = ? order by name",
new { id = 1 });
}
Если я изменил строку запроса на: ... where id = @id ...
, я получу ошибку: Must declare the scalar variable "@id".
Как построить строку запроса и как передать параметр?
Текущий исходный код (еще не выпущенный для NuGet) решает эту проблему; должно работать следующее:
var result = conn.Query(
"select code, name from mytable where id = ?id? order by name",
new { id = 1 });
В текущей сборке ответ на это будет "нет" по двум причинам:
@id
, :id
или ?id
в sqlХорошей новостью является то, что оба они являются фиксируемыми
Выполняя эти изменения в моем локальном клоне, теперь выполняется следующее:
// see https://stackoverflow.com/q/18847510/23354
public void TestOleDbParameters()
{
using (var conn = new System.Data.OleDb.OleDbConnection(
Program.OleDbConnectionString))
{
var row = conn.Query("select Id = ?, Age = ?", new DynamicParameters(
new { foo = 12, bar = 23 } // these names DO NOT MATTER!!!
) { RemoveUnused = false } ).Single();
int age = row.Age;
int id = row.Id;
age.IsEqualTo(23);
id.IsEqualTo(12);
}
}
Обратите внимание, что в настоящее время я использую DynamicParameters
здесь, чтобы избежать добавления еще большего количества перегрузок до Query
/Query<T>
- потому что это нужно будет добавить к большому числу методов. Добавление его в DynamicParameters
разрешает его в одном месте.
Я открыт для обратной связи, прежде чем я выдвигаю это - подходит ли это для вас?
Edit: с добавлением funky smellsLikeOleDb
(нет, не шутка), мы можем сделать это еще более прямо:
// see https://stackoverflow.com/q/18847510/23354
public void TestOleDbParameters()
{
using (var conn = new System.Data.OleDb.OleDbConnection(
Program.OleDbConnectionString))
{
var row = conn.Query("select Id = ?, Age = ?",
new { foo = 12, bar = 23 } // these names DO NOT MATTER!!!
).Single();
int age = row.Age;
int id = row.Id;
age.IsEqualTo(23);
id.IsEqualTo(12);
}
}
Я тестировал использование Dapper в своем программном продукте, использующем odbc-соединения (на данный момент). Однако однажды я намерен отойти от odbc и использовать другой шаблон для поддержки различных продуктов RDBMS. Однако моя проблема с реализацией решения в 2 раза:
В то же время я взломал решение, которое позволяет мне делать это с помощью Dapper. По сути, у меня есть подпрограмма, которая заменяет именованные параметры? а также восстанавливает объект параметра, убедившись, что параметры находятся в правильном порядке. Однако, глядя на код Dapper, я вижу, что я повторил некоторые из того, что делает dapper в любом случае, эффективно каждое значение параметра теперь посещается еще раз, чем это необходимо. Это становится проблемой для массовых обновлений/вставок. Но, по крайней мере, это работает для меня o.k...
Я заимствовал немного кода из здесь, чтобы сформировать часть моего решения...
? для параметров был частью решения для меня, но он работает только с целыми числами, как ID. Это все еще терпит неудачу для строк, потому что длина параметра не определена.
OdbcException: ОШИБКА [HY104] [Microsoft] [ODBC Microsoft Access Driver] Неверное значение точности
System.Data.Odbc. OdbcParameter.Bind (OdbcStatementHandle hstmt, команда OdbcCommand, короткий порядковый номер, параметр CNativeBufferBuffer, bool allowReentrance)
System.Data.
System.Data.Odbc.OdbcCommand.ExecuteReaderObject (поведение CommandBehavior, строковый метод, bool needReader)
System.Data.Common.DbCommand.ExecuteDbDataReaderAsync (поведение CommandBehavior, CancellationToken cancellationToken)
Dapper.SqlMapper.QueryAsync(IDbConnection cnn, введитеffectiveType, команда CommandDefinition) в SqlMapper.Async.cs
WebAPI.DataAccess.CustomerRepository.GetByState (состояние строки) в Repository.cs
var result = await conn.QueryAsync(sQuery, new {State = state});
WebAPI.Controllers.CustomerController.GetByState (состояние строки) в CustomerController.cs
return await _customerRepo.GetByState(state);
Чтобы Dapper передавал строковые параметры в ODBC, мне нужно было указать длину.
var result = await conn.QueryAsync<Customer>(sQuery, new { State = new DbString { Value = state, IsFixedLength = true, Length = 4} });