简体   繁体   English

使用 Dapper 和 SQLite,Query Method 抛出空引用异常

[英]Using Dapper with SQLite, Query Method throws a null reference exception

Testing environment:测试环境:

-- Framework version: .NET 6 -- 框架版本:.NET 6

-- Microsoft.Data.Sqlite, version: 6.0.6 -- Microsoft.Data.Sqlite,版本:6.0.6

-- Dapper, version: 2.0.123 -- Dapper,版本:2.0.123

Q: When only one query is executed, there is no problem.问:只执行一个查询时,没有问题。 Problems occur when multiple concurrent queries are executed.执行多个并发查询时会出现问题。

(Reference: When I write code in native ADO.NET instead of Dapper(conn.Query), there is no problem!) (参考:当我用原生ADO.NET而不是Dapper(conn.Query)写代码时,没有问题!)

Here is a simple demo that can reproduce the problem very easily.这是一个简单的演示,可以很容易地重现问题。

using System.Data;
using Dapper;
using Microsoft.Data.Sqlite;

// SQLite db file
string connStr = $"Data Source={AppDomain.CurrentDomain.BaseDirectory}test.db";

// SQLite connection (Share the singleton connection) 
using SqliteConnection conn = new SqliteConnection(connStr);
conn.Open();
 
bool existError = false;
while (true)
{
    if (existError == true)
    {
        break;
    }

    // Perform concurrent reads
    Parallel.For(0, 100, index =>
    {
        try
        {
            // Test SQL
            string sql_test = " select * from T_Account where AccountId='ab001' ";

            // Perform query data (May throw a null reference exception )
            var t = conn.Query(sql_test);
        }
        catch (Exception ex)
        {
            existError = true;

            // Test output: Object reference not set to an instance of an object.
            Console.WriteLine($"Read error ({index}): {ex.Message}");
        }
    });

    Console.WriteLine($"{DateTime.Now}-------- split line --------");
}

The whole project has been using Dapper, I want to know where the problem is, how should I solve it?整个项目一直在用Dapper,想知道问题出在哪里,应该怎么解决?

You might think that it's a super good idea to reuse the connection, but it isn't.您可能认为重用连接是一个非常好的主意,但事实并非如此。 There already is a connection pool built-in to ADO, and it's far more efficient than anything we can come up with. ADO 已经内置了一个连接池,它比我们能想出的任何东西都高效得多。 I tried to run your code, obviously with another sqlite database and query, and on the 6th or 7th iteration I got the null reference exception.我尝试运行您的代码,显然使用另一个 sqlite 数据库和查询,并且在第 6 次或第 7 次迭代中,我得到了空引用异常。 Then I changed your code like this:然后我像这样更改了您的代码:

// Perform concurrent reads
Parallel.For(0, 100, index =>
{
    try
    {
        // These two lines moved inside the loop
        using SqliteConnection conn = new SqliteConnection(connStr);
        conn.Open();

        // Test SQL
        string sql_test = " select * from T_Account where AccountId='ab001' ";

        // Perform query data (May throw a null reference exception )
        var t = conn.Query(sql_test);
    }
    catch (Exception ex)
    {
        existError = true;

        // Test output: Object reference not set to an instance of an object.
        Console.WriteLine($"Read error ({index}): {ex.Message}");
    }
});

And the code can go on and on as expected.并且代码可以按预期继续运行。 Best practice is to create the database connection in a using statement and have it disposed as soon as you are done with it.最佳实践是在 using 语句中创建数据库连接,并在完成后立即处理它。 Since I haven't seen your code with raw ADO.NET, I can't tell why that works.由于我还没有看到您使用原始 ADO.NET 编写的代码,所以我不知道为什么会这样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM