Dapper Extension Ms Access System.Data.OleDb.OleDbException

时间:2016-08-29 05:43:02

标签: ms-access dapper dapper-extensions

我刚刚开始使用Dapper。小巧玲珑工作得很好。当我尝试与Dapper Extension集成时,下一步。它会生成一个名为System.Data.OleDb.OleDbException "Additional information: Characters found after end of SQL statement."的异常。为什么会这样? Dapper Extension不支持Ms Access(因为结束字符)或我的代码有问题,或者我遗漏了一些东西。我的代码在

之下
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 个答案:

答案 0 :(得分:4)

根据MSDN article

  

某些数据库引擎(如Microsoft Access Jet数据库引擎)不支持输出参数,也无法在一个批处理中处理多个语句。

所以问题是Insert方法正在生成一个语句,如

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

并且Access无法处理它。

阅读时,似乎有关于如何在处理Access时使用insert-and-get-new-record-key的各种建议(该MSDN文章建议第二个SELECT语句),但这并不是如果您正在使用DapperExtensions库,请提供帮助,因为这样可以为您生成查询。

所以,基本上,我认为您认为DapperExtensions无法使用Access是正确的。

另一方面,我有一个噩梦试图找出正在生成的查询。有各种文章谈论注册表黑客设置&#34; JETSHOWPLAN&#34;值&#34; ON&#34;但我无法使它们中的任何一个起作用。最后,我创建了包装数据库连接和命令类,以便在出路时捕获查询。如果这对将来的任何人都有用,我将其包括在下面..

数据库连接初始化代码需要稍微改变 - 例如

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();
    }
}

现在,查询在发送到数据库之前会写入控制台。