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

    2.4.6 EF Core -- 更新

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

    状态

    • Entity State
    • Property State

    Entity State

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

    Property State

    • IsModified
    • CurrentValue
    • OriginValue

    自动变更检测

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

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

    ProjectController

    [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;
    }
    

    修改分组信息

    // 查询实体信息
    var originGroup = await _lighterDbContext.ProjectGroups.Where(g => g.ProjectId == id).ToListAsync(cancellationToken: cancellationToken);
    
    // 修改实体属性
    foreach (var group in originGroup)
    {
        group.Name = $"{title} - {group.Name}";
    }
    

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

    [HttpGet]
    public async Task<IEnumerable<Project>> GetListAsync(CancellationToken cancellationToken)
    {
        return await _lighterDbContext.Projects.Include(p => p.Groups).ToListAsync(cancellationToken);
    }
    

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

    [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;
    }
    

    不查询删除和更新

    删除之前先查询

    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();
        }
    }
    

    不查询删除

    var id = 1;
    using(var db = new entityContext())
    {
        var entity = new Entity{ID = id};
        
        db.dbset.Attach(entity);
        db.dbset.Remove(entity);
        db.SaveChanges();
    }
    

    不查询更新

    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 中添加行版本号字段

    /// <summary>
    /// 行版本号
    /// </summary>
    [Timestamp]
    public byte[] RowVersion { get; set; }
    

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

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

    ProjectController

    [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;
    }
    

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

    _lighterDbContext.Entry(origin).Property(p => p.RowVersion).OriginalValue = project.RowVersion;
    

    2.4.7 EF Core -- 迁移

    生成 SQL 脚本

    从空白开始生成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

    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

    知识共享许可协议

    本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

    欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。

    如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。

  • 相关阅读:
    Best Time to Buy and Sell Stock
    Remove Nth Node From End of List
    Unique Paths
    Swap Nodes in Pairs
    Convert Sorted Array to Binary Search Tree
    Populating Next Right Pointers in Each Node
    Maximum Subarray
    Climbing Stairs
    Unique Binary Search Trees
    Remove Duplicates from Sorted Array
  • 原文地址:https://www.cnblogs.com/MingsonZheng/p/14218950.html
Copyright © 2011-2022 走看看