前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >.NET 云原生架构师训练营(模块二 基础巩固 EF Core 更新和迁移)--学习笔记

.NET 云原生架构师训练营(模块二 基础巩固 EF Core 更新和迁移)--学习笔记

作者头像
郑子铭
发布2021-01-13 15:59:42
5920
发布2021-01-13 15:59:42
举报

2.4.6 EF Core -- 更新

  • 状态
  • 自动变更检测
  • 不查询删除和更新
  • 并发

状态

  • Entity State
  • Property State

Entity State

  • Added 添加
  • Unchanged 没有变化
  • Modified 已修改
  • Deleted 已删除
  • Detached 未跟踪

Property State

  • IsModified
  • CurrentValue
  • OriginValue

自动变更检测

  • 使用自动变更检测完成确定字段的更新
  • 使用自动变更检测完成任意字段的更新

使用自动变更检测完成确定字段的更新

ProjectController

代码语言:javascript
复制
[HttpPatch]
[Route("{id}")]
public async Task<ActionResult<Project>> SetTitleAsync(string id, [FromQuery] string title, CancellationToken cancellationToken)
{
    // 查询实体信息
    var origin = await _lighterDbContext.Projects.FirstOrDefaultAsync(p => p.Id == id, cancellationToken);

    // 修改实体属性
    origin.Title = title;

    // 数据提交保存
    await _lighterDbContext.SaveChangesAsync();

    return origin;
}

修改分组信息

代码语言:javascript
复制
// 查询实体信息
var originGroup = await _lighterDbContext.ProjectGroups.Where(g => g.ProjectId == id).ToListAsync(cancellationToken: cancellationToken);

// 修改实体属性
foreach (var group in originGroup)
{
    group.Name = $"{title} - {group.Name}";
}

查询项目信息时带出分组信息

代码语言:javascript
复制
[HttpGet]
public async Task<IEnumerable<Project>> GetListAsync(CancellationToken cancellationToken)
{
    return await _lighterDbContext.Projects.Include(p => p.Groups).ToListAsync(cancellationToken);
}

使用自动变更检测完成任意字段的更新

代码语言:javascript
复制
[HttpPatch]
[Route("{id}")]
public async Task<ActionResult<Project>> SetAsync(string id, CancellationToken cancellationToken)
{
    // 查询实体信息
    var origin = await _lighterDbContext.Projects.FirstOrDefaultAsync(p => p.Id == id, cancellationToken);
    var properties = _lighterDbContext.Entry(origin).Properties.ToList();

    // 修改实体属性
    foreach (var query in HttpContext.Request.Query)
    {
        var property = properties.FirstOrDefault(p => p.Metadata.Name == query.Key);
        if (property == null)
            continue;

        var currentValue = Convert.ChangeType(query.Value.First(), property.Metadata.ClrType);

        _lighterDbContext.Entry(origin).Property(query.Key).CurrentValue = currentValue;
        _lighterDbContext.Entry(origin).Property(query.Key).IsModified = true;
    }

    // 数据提交保存
    await _lighterDbContext.SaveChangesAsync(cancellationToken);

    return origin;
}

不查询删除和更新

删除之前先查询

代码语言:javascript
复制
var id = 1;
using(var db = new entityContext())
{
    var entity = db.dbset.FirstOrDefault(e=>e.ID == id);
    if(entity != null)
    {
        db.dbset.Remove(entity);
        db.SaveChanges();
    }
}

不查询删除

代码语言:javascript
复制
var id = 1;
using(var db = new entityContext())
{
    var entity = new Entity{ID = id};
    
    db.dbset.Attach(entity);
    db.dbset.Remove(entity);
    db.SaveChanges();
}

不查询更新

代码语言:javascript
复制
try
{
    using(var db = new dbContext())
    {
        var entity = new myEntity{PageID = pageid};
        db.Pages.Attach(entity);// added
        
        entity.Title = "new title";// modified, isModified=true
        entity.Url = "new-url";
        
        db.SaveChanges();
    }
}
catch(DataException)
{
    
}

并发

乐观处理:系统认为数据的更新在大多数情况下是不会产生冲突的,只在数据库更新操作提交的时候才对数据作冲突检测(推荐)

悲观处理:根据命名即对数据库进行操作更新时,对操作持悲观保守的态度,认为产生数据冲突的可能性很大,需要先对请求的数据加锁再进行相关操作

在 Entity 中添加行版本号字段

代码语言:javascript
复制
/// <summary>
/// 行版本号
/// </summary>
[Timestamp]
public byte[] RowVersion { get; set; }

每次对数据进行更新的时候,都会产生最新的版本号,如果更新的时候查询的版本号与之前的版本号不一致,就会报错

在 UpdateAsync 方法中的查询和更新中间如果数据库的行版本号发生了修改,就会报错

ProjectController

代码语言:javascript
复制
[HttpPut]
[Route("{id")]
public async Task<ActionResult<Project>> UpdateAsync(string id, [FromBody] Project project, CancellationToken cancellationToken)
{
    var origin = await _lighterDbContext.Projects.FirstOrDefaultAsync(p => p.Id == id, cancellationToken);

    if (origin == null)
        return NotFound();

    _lighterDbContext.Entry(origin).CurrentValues.SetValues(project);

    await _lighterDbContext.SaveChangesAsync(cancellationToken);
    return origin;
}

通过客户端传入行版本号,解决前端浏览器数据覆盖问题

代码语言:javascript
复制
_lighterDbContext.Entry(origin).Property(p => p.RowVersion).OriginalValue = project.RowVersion;

2.4.7 EF Core -- 迁移

生成 SQL 脚本

代码语言:javascript
复制
从空白开始生成sql脚本  
dotnet ef migrations script


生成指定版本到最新版本的sql 
dotnet ef migrations script AddNewTables


从A-B版本生成迁移SQL脚本 
dotnet ef migrations script AddNewTables AddAuditTable

2.4.8 EF Core -- 其他

database-first

代码语言:javascript
复制
dotnet ef dbcontext scaffold "server=172.0.0.1;port=7306;user=root;password=root123456@;database=lighter" Pomelo.EntityFrameworkCore.MySql -o Models

GitHub源码链接:

https://github.com/MINGSON666/Personal-Learning-Library/tree/main/ArchitectTrainingCamp/LighterApi

课程链接

.NET云原生架构师训练营讲什么,怎么讲,讲多久

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DotNet NB 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 2.4.6 EF Core -- 更新
    • 状态
      • Entity State
      • Property State
    • 自动变更检测
      • 使用自动变更检测完成确定字段的更新
      • 使用自动变更检测完成任意字段的更新
    • 不查询删除和更新
      • 并发
      • 2.4.7 EF Core -- 迁移
      • 2.4.8 EF Core -- 其他
        • GitHub源码链接:
        • 课程链接
        相关产品与服务
        数据库
        云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档