一、新增
- 先校验参数
- db查询所需要的基础数据
- 基础数据非空验证
-
组装Entity报错
/// <summary> /// 新增数据 /// </summary> /// <returns></returns> public async Task AddAsync(CreateOrderRequest request) { _ = request.Order ?? throw new UserFriendlyException("order is null"); _ = request.Items ?? throw new UserFriendlyException("items is null"); if (!request.Items.Any()) throw new UserFriendlyException("items is null"); //职责单一,只进行参数数据校验 foreach (var salesOrderDetail in request.Items) { if (salesOrderDetail.SaleNum <= 0) throw new UserFriendlyException("error"); if (salesOrderDetail.GoodsId.Equals(default)) throw new UserFriendlyException("error"); if (salesOrderDetail.ExpressMoney < 0) throw new UserFriendlyException("error"); } var goodsIds = request.Items.Select(item => item.GoodsId); //只查询使用到的字段 var goods = _secDbContext.Goods.Where(good => goodsIds.Contains(good.Id)).Select(good => new { good.Title, good.Id, good.Inventory, }).ToList(); //职责单一,只进行基础数据校验 foreach (var salesOrderDetail in request.Items) { var good = goods.Find(good => good.Id == salesOrderDetail.GoodsId); if (good == null) throw new UserFriendlyException("商品不存在"); if (good.Inventory < salesOrderDetail.SaleNum) throw new UserFriendlyException("库存不足"); } var order = new Mapping<SalesOrder, SalesOrder>().ReverseMap(request.Order); var orderItems = request.Items.Select(item => { return new Mapping<SalesOrderDetail, SalesOrderDetail>().ReverseMap(item); }); await _secDbContext.AddAsync(order); await _secDbContext.AddRangeAsync(orderItems); }
二、查询优化
- FirstOrDefaultAsync 和 FindAsync 区别
- FirstOrDefaultAsync (表达树)直接查询数据 PS:两个方法同时查询了一条数据,进行Update 会提示异常:xxxxx Id 重复
- FindAsync (主键Id)会先默认查询DbContext缓存,查不到查询数据 PS:两个方法同时查询了一条数据,公用一条 数据缓存
- 判断数据库是否存在某条数据时,请使用Any(),不要使用Count()
- Where查询不要有转换语句:where(x = x.CteateTime > = new DateTime(""))
-
Linq 优化
- 查询方式
var orders = _secDbContext.SalesOrders.Take(10).ToList(); //低级的错误 foreach (var item in orders) { var salesOrderDetail = await _secDbContext.SalesOrderDetails.FirstOrDefaultAsync(details=>details.SalesOrderId==item.Id); //TODO:业务逻辑 } //正确写法 var orderIds = orders.Select(order => order.Id); var salesOrderDetails = _secDbContext.SalesOrderDetails.Where(details => orderIds.Contains(details.SalesOrderId)).ToList(); //TODO:业务逻辑
2.连表查询优化
- 感觉Linq写的不好可以先写Sql分析执行计划和效率,借助SQL转Linq工具的使用——Linqer(http://www.sqltolinq.com/)
- 有数据量比较大的表尽量不要使用 left join,索引掌控不好会导致全表扫描(表结构数据大会很明显效率下降)
- 百度
三、更新
- 表结构添加版本号(乐观锁)
- 只更新指定字段(EF Core 默认有这个功能,需要先查出来数据)PS:this.ChangeTracker.AutoDetectChangesEnabled = false; 会导致此功能失效
- 不查询更新
-
db.Set<T>().Attach(entity);//将数据用未更改的状态放在上下文中,相当于从数据库读取了该实体 entity.ModifyDate = DateTime.Now; entity.ModifyId = loginUser.Id; entity.ModifyName = loginUser.UserName; db.Entry(entity).State = EntityState.Modified; db.Entry(entity).Property("CreateId").IsModified = false; db.Entry(entity).Property("CreateName").IsModified = false; db.Entry(entity).Property("CreateDate").IsModified = false; db.SaveChanges();
写代码注意细节,时刻想着还有咩有优化空间,如何写到最优,而不是实现了能用就行。