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; }
修改分組信息git
// 查詢實體信息 var originGroup = await _lighterDbContext.ProjectGroups.Where(g => g.ProjectId == id).ToListAsync(cancellationToken: cancellationToken); // 修改實體屬性 foreach (var group in originGroup) { group.Name = $"{title} - {group.Name}"; }
查詢項目信息時帶出分組信息github
[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; }
刪除以前先查詢sql
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) { }
樂觀處理:系統認爲數據的更新在大多數狀況下是不會產生衝突的,只在數據庫更新操做提交的時候纔對數據做衝突檢測(推薦)併發
悲觀處理:根據命名即對數據庫進行操做更新時,對操做持悲觀保守的態度,認爲產生數據衝突的可能性很大,須要先對請求的數據加鎖再進行相關操做async
在 Entity 中添加行版本號字段url
/// <summary> /// 行版本號 /// </summary> [Timestamp] public byte[] RowVersion { get; set; }
每次對數據進行更新的時候,都會產生最新的版本號,若是更新的時候查詢的版本號與以前的版本號不一致,就會報錯code
在 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;
生成 SQL 腳本
從空白開始生成sql腳本 dotnet ef migrations script 生成指定版本到最新版本的sql dotnet ef migrations script AddNewTables 從A-B版本生成遷移SQL腳本 dotnet ef migrations script AddNewTables AddAuditTable
database-first
dotnet ef dbcontext scaffold "server=172.0.0.1;port=7306;user=root;password=root123456@;database=lighter" Pomelo.EntityFrameworkCore.MySql -o Models
https://github.com/MINGSON666/Personal-Learning-Library/tree/main/ArchitectTrainingCamp/LighterApi
本做品採用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。
歡迎轉載、使用、從新發布,但務必保留文章署名 鄭子銘 (包含連接: http://www.cnblogs.com/MingsonZheng/ ),不得用於商業目的,基於本文修改後的做品務必以相同的許可發佈。
若有任何疑問,請與我聯繫 (MingsonZheng@outlook.com) 。