DbContextExt.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. using Microsoft.EntityFrameworkCore;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Linq.Expressions;
  7. using System.Reflection;
  8. using System.Text;
  9. namespace Masuit.Tools.Core
  10. {
  11. public static class DbContextExt
  12. {
  13. /// <summary>
  14. /// 获取变化的实体信息
  15. /// </summary>
  16. /// <typeparam name="T"></typeparam>
  17. /// <param name="db"></param>
  18. /// <returns></returns>
  19. public static IEnumerable<ChangeEntry> GetChanges<T>(this DbContext db)
  20. {
  21. return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Modified && e.Entity is T).Select(e =>
  22. {
  23. var originalObject = e.OriginalValues.ToObject();
  24. var currentObject = e.CurrentValues.ToObject();
  25. return new ChangeEntry
  26. {
  27. EntityState = e.State,
  28. Entity = e.Entity,
  29. EntityType = e.OriginalValues.EntityType.ClrType,
  30. ChangeProperties = e.OriginalValues.Properties.Select(p => (Property: p, Value: p.PropertyInfo.GetValue(originalObject))).Zip(e.CurrentValues.Properties.Select(p => (Property: p, Value: p.PropertyInfo.GetValue(currentObject))), (t1, t2) => new ChangePropertyInfo()
  31. {
  32. PropertyInfo = t1.Property.PropertyInfo,
  33. OriginalValue = t1.Value,
  34. CurrentValue = t2.Value,
  35. IsPrimaryKey = t1.Property.IsPrimaryKey(),
  36. IsForeignKey = t1.Property.IsForeignKey()
  37. }).Where(t => Comparer.Default.Compare(t.OriginalValue, t.CurrentValue) != 0).ToList()
  38. };
  39. });
  40. }
  41. /// <summary>
  42. /// 获取变化的实体信息
  43. /// </summary>
  44. /// <param name="db"></param>
  45. /// <returns></returns>
  46. public static IEnumerable<ChangeEntry> GetChanges(this DbContext db)
  47. {
  48. return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Modified).Select(e =>
  49. {
  50. var originalObject = e.OriginalValues.ToObject();
  51. var currentObject = e.CurrentValues.ToObject();
  52. return new ChangeEntry()
  53. {
  54. EntityState = e.State,
  55. Entity = e.Entity,
  56. EntityType = e.OriginalValues.EntityType.ClrType,
  57. ChangeProperties = e.OriginalValues.Properties.Select(p => (Property: p, Value: p.PropertyInfo.GetValue(originalObject))).Zip(e.CurrentValues.Properties.Select(p => (Property: p, Value: p.PropertyInfo.GetValue(currentObject))), (t1, t2) => new ChangePropertyInfo()
  58. {
  59. PropertyInfo = t1.Property.PropertyInfo,
  60. OriginalValue = t1.Value,
  61. CurrentValue = t2.Value,
  62. IsPrimaryKey = t1.Property.IsPrimaryKey(),
  63. IsForeignKey = t1.Property.IsForeignKey(),
  64. }).Where(t => Comparer.Default.Compare(t.OriginalValue, t.CurrentValue) != 0).ToList()
  65. };
  66. });
  67. }
  68. /// <summary>
  69. /// 获取添加的实体信息
  70. /// </summary>
  71. /// <typeparam name="T"></typeparam>
  72. /// <param name="db"></param>
  73. /// <returns></returns>
  74. public static IEnumerable<ChangeEntry> GetAdded<T>(this DbContext db)
  75. {
  76. return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Added && e.Entity is T).Select(e =>
  77. {
  78. var currentObject = e.CurrentValues.ToObject();
  79. return new ChangeEntry
  80. {
  81. EntityState = e.State,
  82. Entity = e.Entity,
  83. EntityType = e.CurrentValues.EntityType.ClrType,
  84. ChangeProperties = e.CurrentValues.Properties.Select(p => new ChangePropertyInfo()
  85. {
  86. PropertyInfo = p.PropertyInfo,
  87. CurrentValue = p.PropertyInfo.GetValue(currentObject),
  88. IsPrimaryKey = p.IsPrimaryKey(),
  89. IsForeignKey = p.IsForeignKey(),
  90. }).ToList()
  91. };
  92. });
  93. }
  94. /// <summary>
  95. /// 获取添加的实体信息
  96. /// </summary>
  97. /// <param name="db"></param>
  98. /// <returns></returns>
  99. public static IEnumerable<ChangeEntry> GetAdded(this DbContext db)
  100. {
  101. return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Added).Select(e =>
  102. {
  103. var currentObject = e.CurrentValues.ToObject();
  104. return new ChangeEntry
  105. {
  106. EntityState = e.State,
  107. Entity = e.Entity,
  108. EntityType = e.CurrentValues.EntityType.ClrType,
  109. ChangeProperties = e.CurrentValues.Properties.Select(p => new ChangePropertyInfo()
  110. {
  111. PropertyInfo = p.PropertyInfo,
  112. CurrentValue = p.PropertyInfo.GetValue(currentObject),
  113. IsPrimaryKey = p.IsPrimaryKey(),
  114. IsForeignKey = p.IsForeignKey(),
  115. }).ToList()
  116. };
  117. });
  118. }
  119. /// <summary>
  120. /// 获取移除的实体信息
  121. /// </summary>
  122. /// <typeparam name="T"></typeparam>
  123. /// <param name="db"></param>
  124. /// <returns></returns>
  125. public static IEnumerable<ChangeEntry> GetRemoved<T>(this DbContext db)
  126. {
  127. return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Deleted && e.Entity is T).Select(e =>
  128. {
  129. var originalObject = e.OriginalValues.ToObject();
  130. return new ChangeEntry
  131. {
  132. EntityState = e.State,
  133. Entity = e.Entity,
  134. EntityType = e.OriginalValues.EntityType.ClrType,
  135. ChangeProperties = e.OriginalValues.Properties.Select(p => new ChangePropertyInfo()
  136. {
  137. PropertyInfo = p.PropertyInfo,
  138. OriginalValue = p.PropertyInfo.GetValue(originalObject),
  139. IsPrimaryKey = p.IsPrimaryKey(),
  140. IsForeignKey = p.IsForeignKey(),
  141. }).ToList()
  142. };
  143. });
  144. }
  145. /// <summary>
  146. /// 获取移除的实体信息
  147. /// </summary>
  148. /// <param name="db"></param>
  149. /// <returns></returns>
  150. public static IEnumerable<ChangeEntry> GetRemoved(this DbContext db)
  151. {
  152. return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Deleted).Select(e =>
  153. {
  154. var originalObject = e.OriginalValues.ToObject();
  155. return new ChangeEntry
  156. {
  157. EntityState = e.State,
  158. Entity = e.Entity,
  159. EntityType = e.OriginalValues.EntityType.ClrType,
  160. ChangeProperties = e.OriginalValues.Properties.Select(p => new ChangePropertyInfo()
  161. {
  162. PropertyInfo = p.PropertyInfo,
  163. OriginalValue = p.PropertyInfo.GetValue(originalObject),
  164. IsPrimaryKey = p.IsPrimaryKey(),
  165. IsForeignKey = p.IsForeignKey(),
  166. }).ToList()
  167. };
  168. });
  169. }
  170. /// <summary>
  171. /// 获取所有的变更信息
  172. /// </summary>
  173. /// <typeparam name="T"></typeparam>
  174. /// <param name="db"></param>
  175. /// <returns></returns>
  176. public static IEnumerable<ChangeEntry> GetAllChanges<T>(this DbContext db)
  177. {
  178. return GetChanges<T>(db).Union(GetAdded<T>(db)).Union(GetRemoved<T>(db));
  179. }
  180. /// <summary>
  181. /// 获取所有的变更信息
  182. /// </summary>
  183. /// <param name="db"></param>
  184. /// <returns></returns>
  185. public static IEnumerable<ChangeEntry> GetAllChanges(this DbContext db)
  186. {
  187. return GetChanges(db).Union(GetAdded(db)).Union(GetRemoved(db));
  188. }
  189. public static IQueryable<TEntity> IncludeRecursive<TEntity>(this IQueryable<TEntity> source,
  190. int levelIndex, Expression<Func<TEntity, ICollection<TEntity>>> expression) where TEntity : class
  191. {
  192. if (levelIndex < 0)
  193. throw new ArgumentOutOfRangeException(nameof(levelIndex));
  194. var member = (MemberExpression)expression.Body;
  195. var property = member.Member.Name;
  196. var sb = new StringBuilder();
  197. for (int i = 0; i < levelIndex; i++)
  198. {
  199. if (i > 0)
  200. sb.Append(Type.Delimiter);
  201. sb.Append(property);
  202. }
  203. return source.Include(sb.ToString());
  204. }
  205. }
  206. public class ChangePropertyInfo
  207. {
  208. /// <summary>
  209. /// 属性
  210. /// </summary>
  211. public PropertyInfo PropertyInfo { get; set; }
  212. /// <summary>
  213. /// 原始值
  214. /// </summary>
  215. public object OriginalValue { get; set; }
  216. /// <summary>
  217. /// 新值
  218. /// </summary>
  219. public object CurrentValue { get; set; }
  220. /// <summary>
  221. /// 是否是主键
  222. /// </summary>
  223. public bool IsPrimaryKey { get; set; }
  224. /// <summary>
  225. /// 是否是外键
  226. /// </summary>
  227. public bool IsForeignKey { get; set; }
  228. }
  229. public class ChangeEntry
  230. {
  231. /// <summary>
  232. /// 所属实体
  233. /// </summary>
  234. public object Entity { get; set; }
  235. /// <summary>
  236. /// 实体类型
  237. /// </summary>
  238. public Type EntityType { get; set; }
  239. /// <summary>
  240. /// 变更类型
  241. /// </summary>
  242. public EntityState EntityState { get; set; }
  243. /// <summary>
  244. /// 字段变更信息
  245. /// </summary>
  246. public List<ChangePropertyInfo> ChangeProperties { get; set; }
  247. }
  248. }