2016-08-29 2 views
0

Я только начал использовать Dapper. Даппер отлично работает. В качестве следующего шага, когда я попытался интегрироваться с расширением Dapper. Он генерирует исключение, называемое System.Data.OleDb.OleDbException "Additional information: Characters found after end of SQL statement." Почему это? Расширение Dapper не поддерживает Ms Access (из-за символа конца) или проблемы с моим кодом, или я чего-то не хватает. Мой код нижеDapper Extension Ms Access System.Data.OleDb.OleDbException

using (var conn = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=myAccessFile.accdb;")) 
{ 
    conn.Open(); 
    conn.Insert<Person>(new Person { Name = "John Stan", Age = 20 }); 
} 
+1

Попробуйте найти способ определения SQL, который генерирует расширения Dapper. Возможно, он объединяет инструкции INSERT и SELECT @@ IDENTITY в одном вызове. Если это так, то Database Database Engine выдает указанную вами ошибку. –

+1

Возможно, вы сможете написать собственный класс SqlDialect для MSAccess, который реализует DapperExtensions SqlDialectBase. Затем вы можете реализовать метод GetIdentitySql с помощью SQL-запроса Access, чтобы получить идентификатор вашей последней записи. вы могли бы придерживаться расширений Dapper. Существует 5 реализаций для основных механизмов SQL в репозитории GitHub @ https://github.com/tmsmith/Dapper-Extensions/tree/master/DapperExtensions/Sql –

+1

@G Davison https://github.com/tmsmith/Dapper -расширения/вопросы/79 – RobinAtTech

ответ

3

Согласно MSDN article,

Некоторые базы данных системы, такие как ядро ​​базы данных Microsoft Access Jet, не поддерживают выходные параметры и не может обрабатывать несколько операторов в одной партии.

Таким образом, проблема заключается в том, что метод Insert генерирует заявление, такие как

INSERT INTO [Person] ([Person].[PersonName]) VALUES (@PersonName); 
SELECT CAST(SCOPE_IDENTITY() AS BIGINT) AS [Id] 

и доступа не может справиться с ней.

Чтение вокруг, кажется, что это различные предложения о том, как делать insert-and-get-new-record-key при работе с Access (эта статья MSDN предлагает второй оператор SELECT), но это не помогает если вы используете библиотеку DapperExtensions, так как именно это генерирует запрос для вас.

Итак, в принципе, я думаю, что вы правы в том, что DapperExtensions не будет работать с Access.


На стороне записки у меня был кошмар, пытаясь выяснить, какие запросы были сгенерированы. Существуют различные статьи, в которых говорится о взломе реестра, чтобы установить значение «JETSHOWPLAN» в «ON», но я не мог заставить их работать. В конце концов, я создал завершенные соединения с базой данных и командные классы, чтобы запросы могли быть захвачены на выходе. В случае, если это будет полезно любому человеку в будущем, я включу его ниже.

Код инициализации соединения с базой данных должен немного измениться - например.

var connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Database2.mdb;"; 
using (var conn = new WrappedDbConnection(new OleDbConnection(connectionString))) 
{ 
    conn.Insert<Person>(new Person { PersonName = "Dan" }); 
} 

и следующие два класса должны быть определены -

public class WrappedDbConnection : IDbConnection 
{ 
    private readonly IDbConnection _conn; 
    public WrappedDbConnection(IDbConnection connection) 
    { 
     if (connection == null) 
      throw new ArgumentNullException(nameof(connection)); 

     _conn = connection; 
    } 

    public string ConnectionString 
    { 
     get { return _conn.ConnectionString; } 
     set { _conn.ConnectionString = value; } 
    } 

    public int ConnectionTimeout 
    { 
     get { return _conn.ConnectionTimeout; } 
    } 

    public string Database 
    { 
     get { return _conn.Database; } 
    } 

    public ConnectionState State 
    { 
     get { return _conn.State; } 
    } 

    public IDbTransaction BeginTransaction() 
    { 
     return _conn.BeginTransaction(); 
    } 

    public IDbTransaction BeginTransaction(IsolationLevel il) 
    { 
     return _conn.BeginTransaction(il); 
    } 

    public void ChangeDatabase(string databaseName) 
    { 
     _conn.ChangeDatabase(databaseName); 
    } 

    public void Close() 
    { 
     _conn.Close(); 
    } 

    public IDbCommand CreateCommand() 
    { 
     return new WrappedDbCommand(_conn.CreateCommand()); 
    } 

    public void Dispose() 
    { 
     _conn.Dispose(); 
    } 

    public void Open() 
    { 
     _conn.Open(); 
    } 
} 

public class WrappedDbCommand : IDbCommand 
{ 
    private readonly IDbCommand _cmd; 
    public WrappedDbCommand(IDbCommand command) 
    { 
     if (command == null) 
      throw new ArgumentNullException(nameof(command)); 

     _cmd = command; 
    } 

    public string CommandText 
    { 
     get { return _cmd.CommandText; } 
     set { _cmd.CommandText = value; } 
    } 

    public int CommandTimeout 
    { 
     get { return _cmd.CommandTimeout; } 
     set { _cmd.CommandTimeout = value; } 
    } 

    public CommandType CommandType 
    { 
     get { return _cmd.CommandType; } 
     set { _cmd.CommandType = value; } 
    } 

    public IDbConnection Connection 
    { 
     get { return _cmd.Connection; } 
     set { _cmd.Connection = value; } 
    } 

    public IDataParameterCollection Parameters 
    { 
     get { return _cmd.Parameters; } 
    } 

    public IDbTransaction Transaction 
    { 
     get { return _cmd.Transaction; } 
     set { _cmd.Transaction = value; } 
    } 

    public UpdateRowSource UpdatedRowSource 
    { 
     get { return _cmd.UpdatedRowSource; } 
     set { _cmd.UpdatedRowSource = value; } 
    } 

    public void Cancel() 
    { 
     _cmd.Cancel(); 
    } 

    public IDbDataParameter CreateParameter() 
    { 
     return _cmd.CreateParameter(); 
    } 

    public void Dispose() 
    { 
     _cmd.Dispose(); 
    } 

    public int ExecuteNonQuery() 
    { 
     Console.WriteLine($"[ExecuteNonQuery] {_cmd.CommandText}"); 
     return _cmd.ExecuteNonQuery(); 
    } 

    public IDataReader ExecuteReader() 
    { 
     Console.WriteLine($"[ExecuteReader] {_cmd.CommandText}"); 
     return _cmd.ExecuteReader(); 
    } 

    public IDataReader ExecuteReader(CommandBehavior behavior) 
    { 
     Console.WriteLine($"[ExecuteReader({behavior})] {_cmd.CommandText}"); 
     return _cmd.ExecuteReader(); 
    } 

    public object ExecuteScalar() 
    { 
     Console.WriteLine($"[ExecuteScalar] {_cmd.CommandText}"); 
     return _cmd.ExecuteScalar(); 
    } 

    public void Prepare() 
    { 
     _cmd.Prepare(); 
    } 
} 

Теперь запросы записываются в консоли перед отправкой в ​​базу данных.

Смежные вопросы