这种错误并不是每次都能重现,当遇到偶尔发生的错误,99%是因为线程安全问题引起的,我把这些客户出现错误的代码进行了分类和整理
1、用到IOC的情况
2、没用到IOC ,一般有3种情况
2.1 因为 SqlSugarClient 对象给单例或者静态引起的//正确用法
public static SqlSugarClient db
{
get
{
return new SqlSugarClient(new ConnectionConfig()
{
DbType = DbType.SqlServer,
ConnectionString = Config.ConnectionString,
InitKeyType = InitKeyType.Attribute,
IsAutoCloseConnection = true
});
}
}
//用的时候需要注意因为每次执行到db都会new出一次新对象
var mydb=db;//正确使用,防止多次new
db.xxx
db.xxxxx
//错误用法
public static SqlSugarClient db = new SqlSugarClient(new ConnectionConfig()
{
DbType = DbType.SqlServer,
ConnectionString = Config.ConnectionString,
InitKeyType = InitKeyType.Attribute,
IsAutoCloseConnection = true,
});
//无论如何用都是错误的
2.2 SqlSugarClient 跨线程使用引起的,保证一个线程new出一个新的SqlSugarClient实例//正确用法
Task.Run(() =>
{
var db = new SqlSugarClient(..);//保证线程唯一
var query2 = db.Queryable().Where(it => it.Id == 1);
});
//错误用法
Task.Run(() =>
{
//db已经跨线程了
var query2 = db.Queryable().Where(it => it.Id == 1);
});
2.3 继承引起的单例//错误用法
public class Worker:DbContext
{
public void Test()
{
Db.xxxxx
Db.xxxx
}
}
public class DbContext
{
public SqlSugarClient Db;
public DbContext(){
Db=new SqlSugarClient(....);
}
}
public class WorkerBLL
{
public static Worker worker=new Worker(); //当Worker给静态后 db也给变相的静态了
}
注意如果Worker没给单例,但是WorkerBLL给单例也会出现问题,也就是说只要继承关系最上层有一个单例全部出错
//正确用法
public class DbContext
{
public SqlSugarClient Db
get{
return new SqlSugarClient(...);//每调用Db都会new一个新的SqlSugarClient
}
}
public class Worker:DbContext
{
public void Test()
{
var db=Db;//传给变量不然每次执行Db都会new
db.xxxxx
db.xxxx
}
}
3、异步引起的线程问题
首先你要保证上面的1和2没有问题,才能看下面的问题//错误用法
public async Task> Test()
{
var db = GetInstance();
await GetAsync();
//在task出现另开线程这种db就跨了线程,task里面的db必须new出来
await new Task(() => { db.Queryable().ToListAsync(); });
return await db.Queryable().ToListAsync();
}
//错误用法
public async Task> Test()
{
var db = GetInstance();
await GetAsync();
var list= db.Queryable().ToListAsync().Result;//.Result或者.Await()都会阻塞当前线程
return await db.Queryable().ToListAsync();
}
//正确用法 每个异步方法都用await进行串起来
public async Task> Test()
{
var db = GetInstance();
await GetAsync();
await db.Queryable().ToListAsync();
return await db.Queryable().ToListAsync();
}
//错误用法,异步中禁止用sleep
Thread.Sleep(1)
//正确用法
Task.Delay(1)
4、反射动态调用多个程序集引起的偶发性错误
一般会报找不到XXX类
更新到最新版本,最新版本已经支持了
5、手动修改数据库表结构,没有重启IIS程序
因为查询会缓存数据绑定方法,你表结构不同了这个缓存的绑定实体方法就报错了