You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在.NET Standard 2.0的FiveM项目中使用Microsoft.Data.Sqlite遇阻

解决FiveM服务器端C#连接SQLite时的e_sqlite3.dll找不到问题

核心修复步骤

1. 调整NuGet包版本与引用

替换项目中的NuGet包为以下版本,确保兼容FiveM的Mono运行环境:

<ItemGroup>
  <PackageReference Include="CitizenFX.Core.Server" Version="1.0.*" />
  <PackageReference Include="Microsoft.Data.Sqlite" Version="5.0.17" />
  <PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.0.7" />
</ItemGroup>

选择5.0.x版本的Microsoft.Data.Sqlite是因为该版本对Mono环境的原生库支持更稳定,SQLitePCLRaw.bundle_e_sqlite3会包含预编译的原生e_sqlite3.dll文件。

2. 强制复制原生DLL到资源目录

FiveM不会自动加载NuGet包中的原生DLL,需在.csproj中添加配置,将原生库复制到资源输出目录:

<Target Name="CopySQLiteNativeDlls" AfterTargets="Build">
  <Copy SourceFiles="$(NuGetPackageRoot)sqlitepclraw.lib.e_sqlite3\2.0.7\runtimes\win-x64\native\e_sqlite3.dll" DestinationFolder="$(OutputPath)" />
</Target>

若服务器为Linux系统,需替换为linux-x64目录下的libe_sqlite3.so文件。

3. 修正数据库文件路径

FiveM服务器端工作目录为服务器根目录,需用GetResourcePath获取资源绝对路径定位数据库文件:

string resourcePath = GetResourcePath(API.GetCurrentResourceName());
string dbPath = Path.Combine(resourcePath, "db.sqlite3");

需在Database类中添加using System.IO;和using static CitizenFX.Core.Native.API;引用。

4. 优化连接与资源管理

使用using语句自动释放数据库连接和命令资源,避免泄漏:

using (var connection = new SqliteConnection($"Data Source={dbPath}"))
{
    connection.Open();
    using (var command = connection.CreateCommand())
    {
        // 命令执行逻辑
        using (var reader = command.ExecuteReader())
        {
            return Serialize(reader);
        }
    }
}

修改后的完整代码

ServerMain.cs

using System;
using System.Collections.Generic;
using CitizenFX.Core;
using static CitizenFX.Core.Native.API;

namespace database.Server
{
    public class ServerMain : BaseScript
    {
        public ServerMain()
        {
            RegisterCommand("dbTest", new Action<int, List<object>, string>((source, args, rawCommand) =>
            {
                var db = new Database();
                var result = db.Query("SELECT * FROM example_table WHERE example=8;");
                foreach (var item in result)
                {
                    foreach (var kv in item)
                    {
                        Debug.WriteLine($"{kv.Key}: {kv.Value.GetType().Name}");
                    }
                }
            }), false);
        }
    }
}

Database.cs

using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Data.Sqlite;
using static CitizenFX.Core.Native.API;

namespace database.Server
{
    class Database
    {
        public List<Dictionary<string, object>> Query(string query, Dictionary<string, string> args=null)
        {
            string resourcePath = GetResourcePath(GetCurrentResourceName());
            string dbPath = Path.Combine(resourcePath, "db.sqlite3");
            
            using (var connection = new SqliteConnection($"Data Source={dbPath}"))
            {
                connection.Open();
                using (var command = connection.CreateCommand())
                {
                    command.CommandText = query;
                    if (args != null)
                    {
                        foreach (var item in args)
                        {
                            command.Parameters.AddWithValue(item.Key, item.Value);
                        }
                    }

                    using (var reader = command.ExecuteReader())
                    {
                        return Serialize(reader);
                    }
                }
            }
        }

        public static List<Dictionary<string, object>> Serialize(SqliteDataReader reader)
        {
            var result = new List<Dictionary<string, object>>();
            while (reader.Read())
            {
                var row = new Dictionary<string, object>();
                for (short i = 0; i < reader.FieldCount; i++)
                {
                    string name = reader.GetName(i);
                    row[name] = reader.GetValue(i);
                }
                result.Add(row);
            }
            return result;
        }
    }
}

修改后的.csproj

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
      <TargetFramework>netstandard2.0</TargetFramework>
      <DebugType>portable</DebugType>
      <TargetName>$(AssemblyName).net</TargetName>
      <DefineConstants>SERVER</DefineConstants>
    </PropertyGroup>
  
    <ItemGroup>
      <PackageReference Include="CitizenFX.Core.Server" Version="1.0.*" />
      <PackageReference Include="Microsoft.Data.Sqlite" Version="5.0.17" />
      <PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.0.7" />
      
      <Compile Include="../Shared/**/*.cs" />
    </ItemGroup>

    <Target Name="CopySQLiteNativeDlls" AfterTargets="Build">
      <Copy SourceFiles="$(NuGetPackageRoot)sqlitepclraw.lib.e_sqlite3\2.0.7\runtimes\win-x64\native\e_sqlite3.dll" DestinationFolder="$(OutputPath)" />
    </Target>
</Project>

问题原因分析

  1. FiveM运行环境限制:FiveM使用自定义Mono运行时,无法自动识别NuGet包中嵌入的原生DLL,必须手动复制到资源目录才能加载。
  2. 版本兼容性:高版本Microsoft.Data.Sqlite(如7.x)的原生库加载逻辑在Mono环境下存在兼容性问题,5.0.x版本适配性更好。
  3. 路径错误:默认相对路径指向服务器根目录而非资源目录,导致数据库文件或DLL无法被找到。

内容的提问来源于stack exchange,提问作者Ghostino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 19:05:23