Toggle navigation
首页
技术
骑行
羽毛球
资讯
联络我
登录
ASP.NET Core 使用EF更新资料时仅更新变更的字段
2017-05-23
.NET Core
# 默认生成的CRUD代码的问题 如果我们建立了Model,然后通过vs code generation出CRUD的代码,Edit的代码类似下面这样: ```c# public async Task<IActionResult> Edit(string id, [FromForm] Article article) { if (id != article.Id) { return NotFound(); } if (ModelState.IsValid) { _dbContext.Update(item); await _dbContext.SaveChangesAsync(); return RedirectToAction("Index"); } return View(article); } ``` 如果查看log,会发现生成的update sql更新了所有字段,即使我们只更新了某一个字段: ```sql UPDATE `Article` SET `Body` = @p2, `CategoryId` = @p4, `Clicks` = @p6, `DatePublished` = @p8, `Image` = @p10, `IsPublished` = @p12, ` Slug` = @p14, `Summary` = @p16, `Tags` = @p18, `Title` = @p20 WHERE `Id` = @p0; ``` # 如果只更新变更的字段? 将代码调整一下,从context中取得既有的entity,赋值之后再更新: ```c# var existItem = await _dbContext.Article.FirstAsync(r => r.Id == id); existItem.Title = article.Title; existItem.Summary = article.Summary; existItem.Body = article.Body; existItem.Slug = article.Slug; existItem.IsPublished = article.IsPublished; existItem.DatePublished = article.DatePublished; existItem.CategoryId = article.CategoryId; await _dbContext.SaveChangesAsync(); ``` 仅更新Summary字段,查看log,发现生成的sql仅更新Summary字段: ```sql UPDATE `Article` SET `Summary` = @p2 WHERE `Id` = @p0; ``` # 为什么每个字段有重新赋值但是却只更新了修改的字段? 查看entity framework的源码可以看到,ChangeDetector已经做好了字段的比对,只有和原值不相等的属性才会被标记为修改状态,才会被更新: ```c# public virtual void DetectChanges(InternalEntityEntry entry) { var entityType = entry.EntityType; foreach (var property in entityType.GetProperties()) { if (property.GetOriginalValueIndex() >= 0 && !Equals(entry[property], entry.GetOriginalValue(property))) { entry.SetPropertyModified(property); } } foreach (var property in entityType.GetProperties()) { DetectKeyChange(entry, property); } if (entry.HasRelationshipSnapshot) { foreach (var navigation in entityType.GetNavigations()) { DetectNavigationChange(entry, navigation); } } } ``` 文件在这里: https://github.com/aspnet/EntityFramework/blob/ab9c919d2496ae7e655331328483b634dc3a4f7b/src/EFCore/ChangeTracking/Internal/ChangeDetector.cs#L121 # 有没有什么更简单的方法? 上面的方法,要对entity的每个属性都进行赋值,操作比较繁琐,也不是一个优秀码农想要的。 这里可以使用 AutoMapper 包来简化操作,它可以帮助我们将一个对象映射到另一个对象,简化后的代码如下(Initialize方法可以放入statup.cs中,执行一次就好): ```c# AutoMapper.Mapper.Initialize(cfg => cfg.CreateMap<Article, Article>()); AutoMapper.Mapper.Map(item, existItem); ``` AutoMapper 的 github 地址如下: https://github.com/AutoMapper/AutoMapper
×
本文为博主原创,如需转载,请注明出处:
http://www.supperxin.com
返回博客列表