今天在开发中偶然发现了正常查询语句出现了错误,但是没改代码的情况下之前一直没问题呢,想了不出现错误和出现错误中间就改了一个参数。
public static SqlSugarClient GetInstance()
{
SqlSugarClient db = new SqlSugarClient(
new ConnectionConfig()
{
ConnectionString = DBConfigPool.ConnectionString,
DbType = SqlSugar.DbType.SqlServer,
InitKeyType = InitKeyType.Attribute,//从特性读取主键和自增列信息
IsAutoCloseConnection = true,//开启自动释放模式和EF原理一样我就不多解释了
IsShardSameThread = true//设为true相同线程是同一个SqlConnection
//"server=118.178.94.27;Database=AltrainTest;Uid=sa;Pwd=string@111999"
});
return db;
}
IsShardSameThread = true//设为true相同线程是同一个SqlConnection
为了做事务,改了这个参数后就出现了以下错误
这个错误是以下代码运行后生成的
Db.Updateable<MaterialSaleModel>()
.Where(a => a.BuyerID == user.BuyerID && a.IsDelete == false && a.ID == MaterialSaleID)
.SetColumns(a => a.ShowSaleNum == showSaleNum)
.ExecuteCommand();
这是一条很正常的查询语句,每有问题,那问题就出现在其他地方。
在重现错误的时候发现只能我把数据库里测试数据全部错误后,现调试程序就出现了这个错误。
就是有数据的时候不出现,很郁闷的情况。
在不知试了多少次后发现是之前一个嵌套查询引起的。
var sq1 = Db.Queryable<MaterialSaleModel, MaterialModel>((a, b) => new object[] { SqlSugar.JoinType.Inner, a.MaterialID == b.ID && a.BuyerID == b.BuyerID && b.IsDelete == false })
.Where(a => a.BuyerID == user.BuyerID && a.IsDelete == false && a.PlaceID == PlaceID)
.Select<MaterialSaleInfo>();
return Db.Queryable(sq1)
.WhereIF(!string.IsNullOrEmpty(par.Filter), par.Filter)
.OrderByIF(!string.IsNullOrEmpty(par.OrderInfo), par.OrderInfo)
.ToPageList(par.PageIndex, par.PageSize, ref par.TotalNumber, ref par.TotalPage);
这个查询且满足查出来记录是空才能触发错误。
protected ISugarQueryable<T> _As(string tableName, string entityName)
{
IsAs = true;
OldMappingTableList = this.Context.MappingTables;
this.Context.MappingTables = this.Context.Utilities.TranslateCopy(this.Context.MappingTables);
if (this.Context.MappingTables.Any(it => it.EntityName == entityName))
{
this.Context.MappingTables.Add(this.Context.MappingTables.First(it => it.EntityName == entityName).DbTableName, tableName);
}
this.Context.MappingTables.Add(entityName, tableName);
this.QueryableMappingTableList = this.Context.MappingTables;
return this;
}
以上是查询后把查询的表保存到缓存。
public virtual List<T> ToPageList(int pageIndex, int pageSize, ref int totalNumber)
{
_RestoreMapping = false;
List<T> result = null;
int count = this.Count();
_RestoreMapping = true;
QueryBuilder.IsDisabledGobalFilter = UtilMethods.GetOldValue(QueryBuilder.IsDisabledGobalFilter, () =>
{
QueryBuilder.IsDisabledGobalFilter = true;
if (count == 0)
{
result = new List<T>();
}
else
result = ToPageList(pageIndex, pageSize);
});
totalNumber = count;
return result;
}
只有有记录的情况下程序进入ToPageList()里面,再进入
protected void RestoreMapping()
{
if (IsAs && _RestoreMapping)
{
this.Context.MappingTables = OldMappingTableList == null ? new MappingTableList() : OldMappingTableList;
}
}
输出数据后会把旧的缓存赋值给缓存集合。
public virtual List<T> ToPageList(int pageIndex, int pageSize, ref int totalNumber)
{
_RestoreMapping = false;
List<T> result = null;
int count = this.Count();
_RestoreMapping = true;
QueryBuilder.IsDisabledGobalFilter = UtilMethods.GetOldValue(QueryBuilder.IsDisabledGobalFilter, () =>
{
QueryBuilder.IsDisabledGobalFilter = true;
if (count == 0)
{
result = new List<T>();
RestoreMapping();
}
else
result = ToPageList(pageIndex, pageSize);
});
totalNumber = count;
return result;
}
所以问题就是空记录的时候没有把旧缓存赋值给缓存集合,也不知道作者是有其他作用还是什么情况。
这样的情况下后面的方法如果用到同名的缓存表,但又不是之前的语句时,就会读取缓存的SQL语句
internal string GetClassString(DbTableInfo tableInfo, ref string className)
{
string classText;
var columns = this.Context.DbMaintenance.GetColumnInfosByTableName(tableInfo.Name);
if (this.Context.IgnoreColumns.HasValue())
{
var entityName = this.Context.EntityMaintenance.GetEntityName(tableInfo.Name);
columns = columns.Where(c =>
!this.Context.IgnoreColumns.Any(ig => ig.EntityName.Equals(entityName, StringComparison.CurrentCultureIgnoreCase) && c.DbColumnName == ig.PropertyName)
).ToList();
}
classText = this.ClassTemplate;
string ConstructorText = IsDefaultValue ? this.ConstructorTemplate : null;
if (this.Context.MappingTables.HasValue())
{
var mappingInfo = this.Context.MappingTables.FirstOrDefault(it => it.DbTableName.Equals(tableInfo.Name, StringComparison.CurrentCultureIgnoreCase));
if (mappingInfo.HasValue())
{
className = mappingInfo.EntityName;
}
if (mappingInfo != null)
{
classText = classText.Replace(DbFirstTemplate.KeyClassName, mappingInfo.EntityName);
}
}
这里就是后面读取缓存同名的时候把之前的SQL取出。
也没太深入了解,只能是先在查询空的时候加入恢复缓存的方法来应急用了。