今天在開發中偶然發現了正常查詢語句出現了錯誤,但是沒改代碼的情況下之前一直沒問題呢,想了不出現錯誤和出現錯誤中間就改了一個參數。
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取出。
也沒太深入瞭解,只能是先在查詢空的時候加入恢復緩存的方法來應急用了。