偶发异常 Safe handle has been closed. 返回

SqlSugar 沟通中
9 135

异常信息

System.ObjectDisposedException: Safe handle has been closed.

Object name: 'SafeHandle'. System.ObjectDisposedException: Safe handle has been closed.

Object name: 'SafeHandle'.

   at System.StubHelpers.StubHelpers.SafeHandleAddRef(SafeHandle pHandle, Boolean& success)

   at SQLitePCL.SQLite3Provider_e_sqlite3.NativeMethods.sqlite3_prepare_v2(sqlite3 db, Byte* pSql, Int32 nBytes, IntPtr& stmt, Byte*& ptrRemain)

   at SQLitePCL.SQLite3Provider_e_sqlite3.SQLitePCL.ISQLite3Provider.sqlite3_prepare_v2(sqlite3 db, ReadOnlySpan`1 sql, IntPtr& stm, ReadOnlySpan`1& tail)

   at Microsoft.Data.Sqlite.SqliteCommand.PrepareAndEnumerateStatements(Stopwatch timer)+MoveNext()

   at Microsoft.Data.Sqlite.SqliteCommand.GetStatements(Stopwatch timer)+MoveNext()

   at Microsoft.Data.Sqlite.SqliteDataReader.NextResult()

   at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior)

   at Microsoft.Data.Sqlite.SqliteCommand.ExecuteDbDataReader(CommandBehavior behavior)

   at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)

   at SqlSugar.AdoProvider.GetDataReader(String sql, SugarParameter[] parameters)

   at SqlSugar.QueryableProvider`1.GetData[TResult](KeyValuePair`2 sqlObj)

   at SqlSugar.QueryableProvider`1._ToList[TResult]()

   at SqlSugar.QueryableProvider`1.ToList()

   at SqlSugar.SimpleClient`1.GetList()


背景:

上位机软件,使用了sqlite数据库。

部署了6台,平均半个月出现1次


使用方式:

使用SqlSugarScope单例注入,全程序没有使异步。

 在一个Task中,定时(1s)查询表中的数据。一旦出现,该task一直报这个错误。程序其他功能操作数据库是成功的。


报错代码:

   

 private void Start()

 {

     bool runFlag;

     Action work = () =>

     {

         Thread.Sleep(1000);

         Run();

     };

     var tokenSource = new CancellationTokenSource();

     var task = Task.Factory.StartNew(() =>

     {

         runFlag = true;

         while (runFlag && !tokenSource.Token.IsCancellationRequested)

         {

             work?.Invoke();

         }

     }, TaskCreationOptions.LongRunning);

 }


 public void Run()

 {

     try

     {

         var db = IOCServer.Resolve<DbProvider>();

         var requests = db.GetRepository<T_ScanPortRequest>().GetList();//这里报错


         //...后面省略

     }

     catch (Exception ex)

     {

         //write log

     }

 }


 //db.GetRepository  函数说明  

 //public SimpleClient<T> GetRepository<T>() where T : class, new()

 //{

 //    return dbClient.GetSimpleClient<T>();

 //}

 // public ISqlSugarClient dbClient { get; private set; }




热忱回答9

  •      var db = IOCServer.Resolve<DbProvider>().CopyNew();//CopyNew强制线程安全
         var requests = db.GetRepository<T_ScanPortRequest>().GetList();
    0 回复
  • 因为我看不到你完整的代码,如果只是一个地方可以用copynew解决

    如果地方很多需要提供DbProvider的实现

    还有IOC的实现

    0 回复
  • 目前就这个地方报错


    我使用的版本比较老,有没有必要升级到最新版本

    目前使用的版本

    image.png



    IOC实现

    public class SqliteDbContext

    {

        public static SqlConfig sqlConfig;


        ISqlSugarClient _db;

        public SqliteDbContext()

        {

            if (sqlConfig == null)

                throw new ArgumentNullException("Db config is null");

                

            _db = new SqlSugarScope(new ConnectionConfig()

            {

                DbType = sqlConfig.DbType,

                InitKeyType = InitKeyType.Attribute,

                IsAutoCloseConnection = true,

                //ConnectionString = sqlConfig.ConnectionString,

                ConnectionString = sqlConfig.ConnectString,

                ConfigureExternalServices = new ConfigureExternalServices

                {

                    EntityService = (c, p) =>

                    {

                        if (p.IsPrimarykey == false && c.PropertyType.IsGenericType &&

                        c.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))

                        {

                            p.IsNullable = true;

                        }                  

                    }

                }

            },

           db =>

           {           

               db.Aop.OnLogExecuting = (sql, pars) =>

               {

                   //  Console.WriteLine(sql);//输出sql,

               };

           }

           );

        }

    }


    //注入

    var db = new SqliteDbContext();

    service.AddSingleton<ISqlSugarClient>(it => { return db.Context; });


    0 回复
  • public partial class DbProvider

    {

        public ISqlSugarClient dbClient { get; private set; }

        public DbProvider(ISqlSugarClient SugarClient)

        {

            this.dbClient = SugarClient;

            InitEntityProvider();

        }

        public MyDbContext GetUow()

        {

            return dbClient.CreateContext<MyDbContext>();

        }


        public SimpleClient<T> GetRepository<T>() where T : class, new()

        {

            return dbClient.GetSimpleClient<T>();

        }


        public static SimpleClient<T> GetRepository<T>(ISqlSugarClient dbClient) where T : class, new()

        {

            return dbClient.GetSimpleClient<T>();

        }

    }

    //注入

    service.AddSingleton<DbProvider>();

    0 回复
  • Task 中循环 操作数据库,是不是就有可能引发线程安全的问题?

    0 回复
  • 看着没有问题,需要提供可以重现的测试用例,删掉OBJ和BIN文件上传

    0 回复
  • 老版本没有CopyNew,也可以手动new

     var newdb=new SqlSugarClient(db.CurrentConnectionConfig);


    0 回复
  • @fate sta:目前只能日志捕获异常,测试无法重现。 概率太低了。  工作代码有加密,无法上传

    0 回复
  • @小小Coder:那就new对象解决吧

     var newdb=new SqlSugarClient(db.CurrentConnectionConfig);//new的不能是Scope只能是client


    0 回复