VzCommonDbContext.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. #nullable enable
  2. using Abp.Domain.Entities;
  3. using Abp.EntityFrameworkCore;
  4. using Abp.Notifications;
  5. using Abp.Webhooks;
  6. using Microsoft.EntityFrameworkCore;
  7. using Microsoft.EntityFrameworkCore.Metadata;
  8. using System.ComponentModel.DataAnnotations.Schema;
  9. using System.Reflection;
  10. using VberZero.BaseSystem;
  11. using VberZero.BaseSystem.Organizations;
  12. using VberZero.BaseSystem.Roles;
  13. using VberZero.BaseSystem.Users;
  14. using VberZero.EntityHistory;
  15. namespace VberZero.EntityFramework;
  16. public abstract class VzCommonDbContext<TSelf> : AbpDbContext
  17. where TSelf : VzCommonDbContext<TSelf>
  18. {
  19. public virtual DbSet<Role> Roles { get; set; }
  20. public virtual DbSet<User> Users { get; set; }
  21. public virtual DbSet<SysFunction> SysFunctions { get; set; }
  22. public virtual DbSet<SysHelp> SysHelps { get; set; }
  23. public virtual DbSet<SysAttach> SysAttaches { get; set; }
  24. public virtual DbSet<SysState> SysStates { get; set; }
  25. public virtual DbSet<SysCalendar> SysCalendars { get; set; }
  26. public virtual DbSet<SysAutoCompleteQuery> SysAutoCompleteQueries { get; set; }
  27. public virtual DbSet<SysSetting> SysSettings { get; set; }
  28. public virtual DbSet<UserLogin> UserLogins { get; set; }
  29. public virtual DbSet<UserLoginAttempt> UserLoginAttempts { get; set; }
  30. public virtual DbSet<UserRole> UserRoles { get; set; }
  31. public virtual DbSet<UserClaim> UserClaims { get; set; }
  32. public virtual DbSet<UserToken> UserTokens { get; set; }
  33. public virtual DbSet<RoleClaim> RoleClaims { get; set; }
  34. public virtual DbSet<PermissionSetting> Permissions { get; set; }
  35. public virtual DbSet<RolePermissionSetting> RolePermissions { get; set; }
  36. public virtual DbSet<UserPermissionSetting> UserPermissions { get; set; }
  37. public virtual DbSet<AuditLog> AuditLogs { get; set; }
  38. public virtual DbSet<OrganizationUnit> OrganizationUnits { get; set; }
  39. public virtual DbSet<UserOrganizationUnit> UserOrganizationUnits { get; set; }
  40. public virtual DbSet<OrganizationUnitRole> OrganizationUnitRoles { get; set; }
  41. public virtual DbSet<TenantNotificationInfo> TenantNotifications { get; set; }
  42. public virtual DbSet<UserNotificationInfo> UserNotifications { get; set; }
  43. public virtual DbSet<NotificationSubscriptionInfo> NotificationSubscriptions { get; set; }
  44. public virtual DbSet<WebhookEvent> WebhookEvents { get; set; }
  45. public virtual DbSet<WebhookSubscriptionInfo> WebhookSubscriptions { get; set; }
  46. public virtual DbSet<WebhookSendAttempt> WebhookSendAttempts { get; set; }
  47. //public virtual DbSet<EntityChange> EntityChanges { get; set; }
  48. //public virtual DbSet<EntityChangeSet> EntityChangeSets { get; set; }
  49. //public virtual DbSet<EntityPropertyChange> EntityPropertyChanges { get; set; }
  50. //public virtual DbSet<ApplicationLanguage> Languages { get; set; }
  51. //public virtual DbSet<ApplicationLanguageText> LanguageTexts { get; set; }
  52. //public virtual DbSet<DynamicProperty> DynamicProperties { get; set; }
  53. //public virtual DbSet<DynamicPropertyValue> DynamicPropertyValues { get; set; }
  54. //public virtual DbSet<DynamicEntityProperty> DynamicEntityProperties { get; set; }
  55. //public virtual DbSet<DynamicEntityPropertyValue> DynamicEntityPropertyValues { get; set; }
  56. public IEntityHistoryHelper EntityHistoryHelper { get; set; }
  57. /// <summary>
  58. ///
  59. /// </summary>
  60. /// <param name="options"></param>
  61. protected VzCommonDbContext(DbContextOptions<TSelf> options)
  62. : base(options)
  63. {
  64. }
  65. public override int SaveChanges()
  66. {
  67. //var changeSet = EntityHistoryHelper.CreateEntityChangeSet(ChangeTracker.Entries().ToList());
  68. var result = base.SaveChanges();
  69. //EntityHistoryHelper.Save(changeSet);
  70. return result;
  71. }
  72. public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken))
  73. {
  74. //var changeSet = EntityHistoryHelper.CreateEntityChangeSet(ChangeTracker.Entries().ToList());
  75. var result = await base.SaveChangesAsync(cancellationToken);
  76. //if (EntityHistoryHelper != null)
  77. //{
  78. // await EntityHistoryHelper.SaveAsync(changeSet);
  79. //}
  80. return result;
  81. }
  82. protected override void OnModelCreating(ModelBuilder modelBuilder)
  83. {
  84. //base.OnModelCreating(modelBuilder);
  85. //取消删除级联
  86. SetForeignKeyDeleteBehaviors(modelBuilder);
  87. //全局配置
  88. foreach (var entityType in modelBuilder.Model.GetEntityTypes())
  89. {
  90. ConfigureGlobalFiltersMethodInfo?.MakeGenericMethod(entityType.ClrType)
  91. .Invoke(this, new object[] { modelBuilder, entityType });
  92. ConfigureGlobalValueConverterMethodInfo?.MakeGenericMethod(entityType.ClrType)
  93. .Invoke(this, new object[] { modelBuilder, entityType });
  94. }
  95. modelBuilder.Entity<User>(b =>
  96. {
  97. b.Property(u => u.ConcurrencyStamp).IsConcurrencyToken();
  98. b.HasOne(p => p.DeleterUser)
  99. .WithMany()
  100. .HasForeignKey(p => p.DeleterUserId).OnDelete(DeleteBehavior.Restrict);
  101. b.HasOne(p => p.CreatorUser)
  102. .WithMany()
  103. .HasForeignKey(p => p.CreatorUserId).OnDelete(DeleteBehavior.Restrict);
  104. b.HasOne(p => p.LastModifierUser)
  105. .WithMany()
  106. .HasForeignKey(p => p.LastModifierUserId).OnDelete(DeleteBehavior.Restrict);
  107. b.HasIndex(e => new { e.TenantId, e.NormalizedUserName });
  108. b.HasIndex(e => new { e.TenantId, e.NormalizedEmailAddress });
  109. });
  110. modelBuilder.Entity<Role>(b =>
  111. {
  112. b.Property(r => r.ConcurrencyStamp).IsConcurrencyToken();
  113. b.HasIndex(e => new { e.TenantId, e.NormalizedName });
  114. });
  115. modelBuilder.Entity<AuditLog>(b =>
  116. {
  117. b.HasIndex(e => new { e.TenantId, e.UserId });
  118. b.HasIndex(e => new { e.TenantId, e.ExecutionTime });
  119. b.HasIndex(e => new { e.TenantId, e.ExecutionDuration });
  120. });
  121. modelBuilder.Entity<NotificationSubscriptionInfo>(b =>
  122. {
  123. b.HasIndex(e => new { e.NotificationName, e.EntityTypeName, e.EntityId, e.UserId });
  124. b.HasIndex(e => new { e.TenantId, e.NotificationName, e.EntityTypeName, e.EntityId, e.UserId });
  125. });
  126. modelBuilder.Entity<OrganizationUnit>(b =>
  127. {
  128. b.HasIndex(e => new { e.TenantId, e.Code }).IsUnique(false);
  129. });
  130. modelBuilder.Entity<PermissionSetting>(b =>
  131. {
  132. b.HasIndex(e => new { e.TenantId, e.Name });
  133. });
  134. modelBuilder.Entity<RoleClaim>(b =>
  135. {
  136. b.HasIndex(e => new { e.RoleId });
  137. b.HasIndex(e => new { e.TenantId, e.ClaimType });
  138. });
  139. modelBuilder.Entity<SysSetting>(b =>
  140. {
  141. b.HasIndex(e => new { e.TenantId, e.Name, e.UserId }).IsUnique().HasFilter(null);
  142. });
  143. modelBuilder.Entity<TenantNotificationInfo>(b =>
  144. {
  145. b.HasIndex(e => new { e.TenantId });
  146. });
  147. modelBuilder.Entity<UserClaim>(b =>
  148. {
  149. b.HasIndex(e => new { e.TenantId, e.ClaimType });
  150. });
  151. modelBuilder.Entity<UserLoginAttempt>(b =>
  152. {
  153. b.HasIndex(e => new { e.TenancyName, e.UserNameOrEmailOrPhone, e.Result });
  154. b.HasIndex(ula => new { ula.UserId, ula.TenantId });
  155. });
  156. modelBuilder.Entity<UserLogin>(b =>
  157. {
  158. b.HasIndex(e => new { e.TenantId, e.LoginProvider, e.ProviderKey });
  159. b.HasIndex(e => new { e.TenantId, e.UserId });
  160. b.HasIndex(e => new { e.ProviderKey, e.TenantId }).IsUnique();
  161. });
  162. modelBuilder.Entity<UserNotificationInfo>(b =>
  163. {
  164. b.HasIndex(e => new { e.UserId, e.State, e.CreationTime });
  165. });
  166. modelBuilder.Entity<UserOrganizationUnit>(b =>
  167. {
  168. b.HasIndex(e => new { e.TenantId, e.UserId });
  169. b.HasIndex(e => new { e.TenantId, e.OrganizationUnitId });
  170. });
  171. modelBuilder.Entity<OrganizationUnitRole>(b =>
  172. {
  173. b.HasIndex(e => new { e.TenantId, e.RoleId });
  174. b.HasIndex(e => new { e.TenantId, e.OrganizationUnitId });
  175. });
  176. modelBuilder.Entity<UserRole>(b =>
  177. {
  178. b.HasIndex(e => new { e.TenantId, e.UserId });
  179. b.HasIndex(e => new { e.TenantId, e.RoleId });
  180. });
  181. modelBuilder.Entity<UserToken>(b =>
  182. {
  183. b.HasIndex(e => new { e.TenantId, e.UserId });
  184. });
  185. //modelBuilder.Entity<DynamicProperty>(b =>
  186. //{
  187. // b.HasIndex(e => new { e.PropertyName, e.TenantId }).IsUnique();
  188. //});
  189. //modelBuilder.Entity<DynamicEntityProperty>(b =>
  190. //{
  191. // b.HasIndex(e => new { e.EntityFullName, e.DynamicPropertyId, e.TenantId }).IsUnique();
  192. //});
  193. //modelBuilder.Entity<ApplicationLanguage>(b =>
  194. //{
  195. // b.HasIndex(e => new { e.TenantId, e.Name });
  196. //});
  197. //modelBuilder.Entity<ApplicationLanguageText>(b =>
  198. //{
  199. // b.HasIndex(e => new { e.TenantId, e.Source, e.LanguageName, e.Key });
  200. //});
  201. //modelBuilder.Entity<EntityChange>(b =>
  202. //{
  203. // b.HasMany(p => p.PropertyChanges)
  204. // .WithOne()
  205. // .HasForeignKey(p => p.EntityChangeId);
  206. // b.HasIndex(e => new { e.EntityChangeSetId });
  207. // b.HasIndex(e => new { e.EntityTypeFullName, e.EntityId });
  208. //});
  209. //modelBuilder.Entity<EntityChangeSet>(b =>
  210. //{
  211. // b.HasMany(p => p.EntityChanges)
  212. // .WithOne()
  213. // .HasForeignKey(p => p.EntityChangeSetId);
  214. // b.HasIndex(e => new { e.TenantId, e.UserId });
  215. // b.HasIndex(e => new { e.TenantId, e.CreationTime });
  216. // b.HasIndex(e => new { e.TenantId, e.Reason });
  217. //});
  218. //modelBuilder.Entity<EntityPropertyChange>(b =>
  219. //{
  220. // b.HasIndex(e => e.EntityChangeId);
  221. //});
  222. }
  223. private static readonly MethodInfo? ConfigureGlobalFiltersMethodInfo = typeof(VzCommonDbContext<TSelf>).GetMethod(nameof(ConfigureGlobalFilters), BindingFlags.Instance | BindingFlags.NonPublic);
  224. private static readonly MethodInfo? ConfigureGlobalValueConverterMethodInfo = typeof(VzCommonDbContext<TSelf>).GetMethod(nameof(VzConfigureGlobalValueConverter), BindingFlags.Instance | BindingFlags.NonPublic);
  225. /// <summary>
  226. /// 全局配置
  227. /// </summary>
  228. /// <typeparam name="TEntity"></typeparam>
  229. /// <param name="modelBuilder"></param>
  230. /// <param name="entityType"></param>
  231. protected void VzConfigureGlobalValueConverter<TEntity>(ModelBuilder modelBuilder, IMutableEntityType entityType)
  232. where TEntity : class
  233. {
  234. ConfigureGlobalValueConverter<TEntity>(modelBuilder, entityType);
  235. if (entityType.BaseType == null && !typeof(TEntity).IsDefined(typeof(OwnedAttribute), true) &&
  236. !entityType.IsOwned())
  237. {
  238. if (typeof(IEntity<string>).IsAssignableFrom(typeof(TEntity)))
  239. {
  240. //Console.WriteLine(typeof(TEntity).Name);
  241. //定义主键为string的长度
  242. modelBuilder
  243. .Entity<TEntity>()
  244. .Property("Id").HasMaxLength(VzConsts.PrimaryKey);
  245. }
  246. //定义外键为string的长度
  247. var propertyInfos = typeof(TEntity).GetProperties();
  248. foreach (var info in propertyInfos)
  249. {
  250. var name = info.GetCustomAttribute<ForeignKeyAttribute>()?.Name;
  251. //Console.WriteLine(typeof(TEntity).Name + "====>" + info.Name + "====>" + name);
  252. if (name != null && typeof(TEntity).GetProperty(name)?.PropertyType == typeof(string))
  253. {
  254. //Console.WriteLine("YYYY");
  255. modelBuilder
  256. .Entity<TEntity>()
  257. .Property(name).HasMaxLength(VzConsts.PrimaryKey);
  258. Console.WriteLine(typeof(TEntity).Name + "====>" + info.Name + "====>" + name + "====>长度设为" + VzConsts.PrimaryKey);
  259. }
  260. }
  261. var userId = propertyInfos.FirstOrDefault(a => a.Name == "UserId");
  262. var tenantId = propertyInfos.FirstOrDefault(a => a.Name == "TenantId");
  263. if (userId != null && tenantId != null)
  264. {
  265. modelBuilder
  266. .Entity<TEntity>().HasIndex("UserId", "TenantId");
  267. }
  268. else if (userId != null)
  269. {
  270. modelBuilder
  271. .Entity<TEntity>().HasIndex("UserId");
  272. }
  273. else if (tenantId != null)
  274. {
  275. modelBuilder
  276. .Entity<TEntity>().HasIndex("TenantId");
  277. }
  278. }
  279. }
  280. /// <summary>
  281. /// 取消级联删除
  282. /// </summary>
  283. /// <param name="modelBuilder"></param>
  284. protected virtual void SetForeignKeyDeleteBehaviors(ModelBuilder modelBuilder)
  285. {
  286. var foreignKeys = modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()).Where(fk => fk.DeleteBehavior == DeleteBehavior.Cascade);
  287. foreach (var fk in foreignKeys)
  288. {
  289. fk.DeleteBehavior = DeleteBehavior.Restrict;
  290. }
  291. }
  292. }