实例化类对象及类的属性set方法使用不当
类的属性中set方法操作数据库,新建类对象并给其赋值时总会触发该set方法,而导致不期望的错乱:
库位类Storage,其中传感器状态SensorStatus和逻辑状态LogicStatus有一定的关联关系:
SensorStatus的值变化时,触发该字段的set方法,set方法中会将该库位的LogicStatus也赋同样的值,并更新到数据库。
public class Storage { public static ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public Storage() { } public int ID { get; set; } public string UpdateBy { get; set; } public DateTime UpdateTime { get; set; } public string OrderNo { get; set; } public int CellNo { get; set; } public string StorageNo { get; set; } public StorageType StorageType { get; set; } public int ItemNo { get; set; } public string ItemType { get; set; } public int ProductNo { get; set; } public string OpcNodeId { get; set; } public int Quantity { get; set; } public StorageLogicStatus LogicStatus { get; set; } private StorageSensorStatus _sensorStatus; public StorageSensorStatus SensorStatus { get { return _sensorStatus; } set { if (value == StorageSensorStatus.Empty) { LogicStatus = StorageLogicStatus.Empty; SqlServerUtil.UpdateStorageLogicStatus(StorageNo, StorageLogicStatus.Empty); } if (value == StorageSensorStatus.Occupied) { LogicStatus = StorageLogicStatus.Occupied; SqlServerUtil.UpdateStorageLogicStatus(StorageNo, StorageLogicStatus.Occupied); } _sensorStatus = value; } } }
而使用时遇到问题:
某个库位的初始状态1:LogicStatus=1;SensorStatus=1
状态2:LogicStatus=3;SensorStatus=1
此时程序执行了下述代码(本意是想获取该库位当前的信息):
Storage storage = SqlServerUtil.GetStorage(targetLocation); //新建一个Storage对象变量,使用数据库查询该库位信息后赋给该变量
// 获取库位信息 (该方法会实例化Storage对象) public static Storage GetStorage(string storageNo) { string sql = $"Select * From T_Storage Where StorageNo='{storageNo}'"; return SqlServerBase.Find<Storage>(sql, null); }
但给storage赋值的过程中,给字段SensorStatus赋值,触发了其set方法,进而改变了LogicStatus,该变化更新到了数据库中,重新变回状态1:LogicStatus=1;SensorStatus=1
因为数据库的Find方法内部实例化了一个类对象:
public static T Find<T>(string sql, Object param) { using (IDbConnection conn = GetConnection()) { T datas = conn.Query<T>(sql, param).SingleOrDefault<T>(); return datas; } }
该意外变化导致程序逻辑受到干扰和错乱,目前解决办法为不新建Storage对象,而是只取要用的字段:
int storageItemNo = SqlServerUtil.GetStorageItemNo(targetLocation);