我应该传递什么给 SQLitePCL.raw.SetProvider() 以避免“‘Microsoft.Data.Sqlite.SqliteConnection’的类型初始值设定项引发异常”

B. *_*non 3 c# sqlite uwp

我收到此错误消息:

“Microsoft.Data.Sqlite.SqliteConnection”的类型初始值设定项引发异常。

更明确地说,我得到:

Message =“Microsoft.Data.Sqlite.SqliteConnection”的类型初始值设定项引发异常。

内部异常 = System.Exception:您需要调用 SQLitePCL.raw.SetProvider()。如果您使用的是捆绑包,则可以通过调用 SQLitePCL.Batteries.Init() 来完成。在 SQLitePCL.raw.get_Provider() 在 SQLitePCL.raw.sqlite3_win32_set_directory(Int32typ,字符串路径) 在 Microsoft.Data.Sqlite.Utilities.BundleInitializer.Initialize() 在 Microsoft.Data.Sqlite.SqliteConnection..cctor()

堆栈跟踪 = 位于 Microsoft.Data.Sqlite.SqliteConnection..ctor(String connectionString) 位于 CartographerYou.MainPage.InsertMapRecord(String mapName, String mapNotes, Int32 PreferredZoomLevel) 位于 CartographerYou.MainPage.btnCre8NewMap_Click(Object sender, RoutedEventArgs e)

这是 StackTrace 中提到的两个方法(事件处理程序和自定义方法):

private async void btnCre8NewMap_Click(object sender, RoutedEventArgs e)
{
    try
    {
        string mapName = string.Empty;
        string mapNotes = string.Empty;
        int defaultZoomLevel = 1;
        ClearLocations();
        // Popul8 the cmbx
        for (int i = 1; i < 20; i++)
        {
            cmbxCre8MapZoomLevels.Items.Add(i.ToString());
        }
        ContentDialogResult result = await cntDlgCre8Map.ShowAsync();

        if (result == ContentDialogResult.Primary)
        {
            mapName = txtbxMapName.Text;
            mapNotes = txtbxMapNotes.Text;
            defaultZoomLevel = cmbxCre8MapZoomLevels.SelectedIndex + 1;
            // select "Step Into Specific" from context menu
            await InsertMapRecord(mapName, mapNotes, defaultZoomLevel); 
        }
        // else do nothing (don't save)                                
    }
    catch (Exception ex)
    {
        string excMsg = string.Format("{0} Inner Exception: {1} Stack Trace: {2}", ex.Message, ex.InnerException, ex.StackTrace);
        MessageDialog exceptionMsgDlg = new MessageDialog(excMsg, "btnCre8NewMap_Click");
        await exceptionMsgDlg.ShowAsync();
    }
}

private async Task InsertMapRecord(string mapName, string mapNotes, int preferredZoomLevel)
{
    path = folder.Path;
    connStr = string.Format(connStrBase, path);
    try
    {
        using (SqliteConnection conn = new SqliteConnection(connStr))
        {
            String query = "INSERT INTO dbo.CartographerMain " +
                           "(MapName, MapNotes, PreferredZoomLevel) " +
                           "VALUES (@MapName, @MapNotes, @PreferredZoomLevel)";

            using (SqliteCommand cmd = new SqliteCommand(query, conn))
            {
                cmd.Parameters.AddWithValue("@MapName", mapName);
                cmd.Parameters.AddWithValue("@MapNotes", mapNotes);
                cmd.Parameters.AddWithValue("@PreferredZoomLevel", preferredZoomLevel);
                await conn.OpenAsync();
                int result = await cmd.ExecuteNonQueryAsync();

                if (result < 0)
                {
                    MessageDialog dialog = new MessageDialog("Error inserting data into CartographerMain");
                    await dialog.ShowAsync();
                }
            }
        }
    }
    catch (SqliteException sqlex)
    {
        string sqlExcMsg = string.Format("{0} Inner Exception: {1} Stack Trace: {2}", sqlex.Message, sqlex.InnerException, sqlex.StackTrace);
        MessageDialog dialog = new MessageDialog(sqlExcMsg, "InsertMapRecord");
        await dialog.ShowAsync();
    }
}
Run Code Online (Sandbox Code Playgroud)

基于需要调用 SQLitePCL.raw.SetProvider() 的内部异常,我更改了代码:

using (SqliteConnection conn = new SqliteConnection(connStr))
{
    . . .
Run Code Online (Sandbox Code Playgroud)

...对此:

SqliteConnection conn = new SqliteConnection(connStr);
SQLitePCL.raw.SetProvider();
. . .
Run Code Online (Sandbox Code Playgroud)

...但我不知道我需要将什么传递给 SetProvider() - 如果这真的是问题的真正解决方案。

这就是我通过该代码得到的结果:

在此输入图像描述

需要将什么传递给 SetProvider()?

tim*_*mur 5

我认为不鼓励SQLitePCL.raw直接使用:

……那不是你想做的事。这不是您用来编写应用程序的那种 SQLite 库。它是围绕 SQLite C API 的一个非常薄的 C# 包装器。这是“生的”。

假设您对此感到满意,您可以考虑使用包装器,例如sqlite-net(作者在其页面上提到它是选项之一):

    class CartographerMain // the library provides ORM functionality, so i created a simple object based on your example
    {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }
        public string MapName { get; set; }
        public string MapNotes { get; set; }
        public int PreferredZoomLevel { get; set; }
    }

    private async Task InsertMapRecord(string mapName, string mapNotes, int preferredZoomLevel)
    {
        var path = "a.db";
        var connStr = string.Format(connStrBase, path);
        SQLiteAsyncConnection db = null;
        try
        {
            db = new SQLiteAsyncConnection(connStr);
            await db.CreateTableAsync<CartographerMain>();
            var result = await db.InsertAsync(new CartographerMain { MapName = mapName, MapNotes = mapNotes, PreferredZoomLevel = preferredZoomLevel });

            if (result < 0)
            {
                MessageDialog dialog = new MessageDialog("Error inserting data into CartographerMain");
                await dialog.ShowAsync();
            }
        }
        catch (SQLiteException sqlex)
        {
            string sqlExcMsg = string.Format("{0} Inner Exception: {1} Stack Trace: {2}", sqlex.Message, sqlex.InnerException, sqlex.StackTrace);
            MessageDialog dialog = new MessageDialog(sqlExcMsg, "InsertMapRecord");
            await dialog.ShowAsync();
        }
        finally
        {
            await db.CloseAsync();
        }
    }
Run Code Online (Sandbox Code Playgroud)

为了使上面的代码正常工作,我只引用了一个nuget 包- 它取决于SQLitePCLRaw.bundle_green,我认为这是您无论如何都会安装的包

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="sqlite-net-pcl" Version="1.7.335" />
  </ItemGroup>

</Project>
Run Code Online (Sandbox Code Playgroud)

UPD

假设您在使用Microsoft.Data.Sqlite时遇到此异常,我怀疑该问题可能源于SQLitePCLRaw.bundle_e_sqlite3(底层依赖项)未针对运行它的环境捆绑本机二进制文件。

如果您已Microsoft.Data.Sqlite安装,则应该将e_sqlite3捆绑包作为依赖项提供,并且可以尝试使用dynamic提供程序

SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_dynamic_cdecl())
Run Code Online (Sandbox Code Playgroud)

如果这不起作用,您可以搜索SQLitePCLRaw.provider.e_sqlite3.*您的特定目标并尝试如下操作:

SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_e_sqlite3());
Run Code Online (Sandbox Code Playgroud)

  • 我并不怀疑你在这里所说的是正确的(“我不认为鼓励直接使用 SQLitePCL.raw”),但这正是 InnerExceptions 所说的。 (2认同)