随着平台数据的积累,对于数据访问的速度要求愈来愈高。优化后台访问性能,将是之后的一个重点任务。
但是,后台在项目开发初期采用的是Abp(Lite DDD)框架,集成EnityFramework。因为之前的项目经验有用过EF,对于开发者编码来说,着实高效。但是之前所处传统行业,对于数据访问的性能要求并不高。因此也就没有在意EF的性能问题。然后,有句话叫做“出来混,早晚要还的”。这不,现在的Web项目对于数据访问性能有些吃力了,尤其是涉及使用Linq拼写出的组合查询且数据量大时,查询速度慢了下来。
最近也是在一边完成新功能的开发,一边通过优化语法进而优化查询速度。但是,这两天后台仓储层调用自带Api查询数据的奇葩表现令我甚是无奈。在新功能(使用websocket实时推动数据)的界面中,调用后台一个查询设备信息的接口,死活查不到实体数据。然后,调用同样的接口在其他界面却可以实现。不禁令我对该框架产生了很大的疑惑,Why?
不过现在的主要任务是尽快交付功能,我把问题记下了。
为了实现在当前界面调用查询设备信息的接口可以查到数据,我注释掉了Services层对Repository层的调用Abp.EnityFramework自带的API查询数据,改用组织SQL语句执行查询、删除、新增。结果则是正常的可以得到你想要的数据。不禁感慨啊,那些个ORM不是万能的,纯碎的Sql是那么的简单高效。
下面贴出EF中使用SQL执行查询、删除及新增的用法:
A,查询,
var parameter = new SqlParameter("@DeviceId", id); var sqlDeviceInfo = string.Format(@"Select * from dbo.DeviceInfos where dbo.DeviceInfos.Id=@DeviceId"); var deviceInfo = await Context.Database.SqlQuery<DeviceInfo>(sqlDeviceInfo, new SqlParameter("@DeviceId", id)).FirstOrDefaultAsync();
B。删除
var deviceIdParamter = new SqlParameter("@DeviceId", deviceId); var sqlDeleteId = string.Format(@"Delete from dbo.DeviceAndHiddenTroubleLinks where DeviceId=@DeviceId"); var result = await Context.Database.ExecuteSqlCommandAsync(sqlDeleteId, deviceIdParamter);
C、新增
var sqlAddId = string.Format(@"Insert into dbo.DeviceAndHiddenTroubleLinks(DeviceId,DeviceHiddenTrouble_Id) values (@DeviceId,@HiddenTroubleId)"); foreach (var hiddenTroubleId in deviceHiddenTroubleIds) { var deviceIdAndHiddenTroubleIdParamter = new DbParameter[] { new SqlParameter { ParameterName = "DeviceId", Value = deviceId }, new SqlParameter { ParameterName = "HiddenTroubleId", Value = hiddenTroubleId } }; await Context.Database.ExecuteSqlCommandAsync(sqlAddId, deviceIdAndHiddenTroubleIdParamter); }
改完之后发现,直接使用SQL挺爽的。看来后台性能优化又多了条路子。
墨匠