2

我刚开始使用 Dapper。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 });
}
4

1 回答 1

7

根据MSDN 文章

某些数据库引擎,例如 Microsoft Access Jet 数据库引擎,不支持输出参数,并且不能在一个批处理中处理多个语句。

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

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

Access 无法处理。

环顾四周,似乎有各种关于在处理 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();
    }
}

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

于 2016-09-02T12:14:59.927 回答