|
5 | 5 | using System.Threading.Tasks; |
6 | 6 | using Bing.Data; |
7 | 7 | using Bing.Domain.Entities; |
| 8 | +using Bing.Exceptions; |
| 9 | +using Bing.Extensions; |
8 | 10 | using Bing.Uow; |
9 | 11 | using Microsoft.EntityFrameworkCore; |
| 12 | +using Microsoft.EntityFrameworkCore.ChangeTracking; |
10 | 13 |
|
11 | 14 | namespace Bing.Datas.EntityFramework.Core |
12 | 15 | { |
@@ -98,21 +101,49 @@ public virtual async Task AddAsync(IEnumerable<TEntity> entities, CancellationTo |
98 | 101 | /// <exception cref="ArgumentNullException"></exception> |
99 | 102 | public virtual void Update(TEntity entity) |
100 | 103 | { |
101 | | - if (entity == null) |
102 | | - throw new ArgumentNullException(nameof(entity)); |
103 | | - UnitOfWork.Entry(entity).State = EntityState.Detached; |
104 | | - var old = Find(entity.Id); |
105 | | - var oldEntry = UnitOfWork.Entry(old); |
106 | | - if (!(entity is IVersion version)) |
| 104 | + entity.CheckNull(nameof(entity)); |
| 105 | + var entry = UnitOfWork.Entry(entity); |
| 106 | + ValidateVersion(entry, entity); |
| 107 | + UpdateEntity(entry, entity); |
| 108 | + } |
| 109 | + |
| 110 | + /// <summary> |
| 111 | + /// 验证版本号 |
| 112 | + /// </summary> |
| 113 | + /// <param name="entry">输入实体</param> |
| 114 | + /// <param name="entity">实体</param> |
| 115 | + protected void ValidateVersion(EntityEntry<TEntity> entry, TEntity entity) |
| 116 | + { |
| 117 | + if (entry.State == EntityState.Detached) |
| 118 | + return; |
| 119 | + if (entity is not IVersion current) |
| 120 | + return; |
| 121 | + if (current.Version == null) |
| 122 | + return; |
| 123 | + var oldVersion = entry.OriginalValues.GetValue<byte[]>(nameof(IVersion.Version)); |
| 124 | + for (var i = 0; i < oldVersion.Length; i++) |
| 125 | + { |
| 126 | + if (current.Version[i] != oldVersion[i]) |
| 127 | + throw new ConcurrencyException($"Type:{typeof(TEntity)},Id:{entity.Id}"); |
| 128 | + } |
| 129 | + } |
| 130 | + |
| 131 | + /// <summary> |
| 132 | + /// 更新实体 |
| 133 | + /// </summary> |
| 134 | + /// <param name="entry">输入实体</param> |
| 135 | + /// <param name="entity">实体</param> |
| 136 | + protected void UpdateEntity(EntityEntry<TEntity> entry, TEntity entity) |
| 137 | + { |
| 138 | + var oldEntry = UnitOfWork.ChangeTracker.Entries<TEntity>().FirstOrDefault(x => x.Entity.Equals(entity)); |
| 139 | + if (oldEntry != null) |
107 | 140 | { |
108 | 141 | oldEntry.CurrentValues.SetValues(entity); |
109 | 142 | return; |
110 | 143 | } |
111 | 144 |
|
112 | | - oldEntry.State = EntityState.Detached; |
113 | | - oldEntry.CurrentValues[nameof(version.Version)] = version.Version; |
114 | | - oldEntry = UnitOfWork.Attach(old); |
115 | | - oldEntry.CurrentValues.SetValues(entity); |
| 145 | + if (entry.State == EntityState.Detached) |
| 146 | + UnitOfWork.Update(entity); |
116 | 147 | } |
117 | 148 |
|
118 | 149 | /// <summary> |
|
0 commit comments