private static void AppendAccessorIsolateableString(DbContextAccessorBase accessor, StringBuilder builder, char connector, Type designTimeType = null) { if (designTimeType.IsNull()) { var dataBuilder = accessor.GetService <IDataBuilder>(); designTimeType = dataBuilder.DatabaseDesignTimeType; } builder.Append(accessor.CurrentType.GetDisplayName(true) .TrimEnd("DbContextAccessor").TrimEnd("Accessor")); builder.Append(connector); builder.Append(designTimeType.GetDisplayName(true) .TrimEnd("DesignTimeServices")); builder.Append(connector); builder.Append(accessor.GetCurrentConnectionDescription() .TrimEnd("ConnectionString")); builder.Append(connector); builder.Append(accessor.CurrentTenant.Name); builder.Append(connector); builder.Append(accessor.CurrentTenant.Host); }
public static FilePathCombiner GenerateAccessorFilePath(DbContextAccessorBase accessor, string extension, string basePath = null, Type designTimeType = null) { accessor.NotNull(nameof(accessor)); extension.NotEmpty(nameof(extension)); var filePath = new FilePathCombiner(GetAccessorFileName(), basePath); filePath.CreateDirectory(); return(filePath); // GetAccessorFileName string GetAccessorFileName() { var connector = DataSettings.Preference.AccessorIsolateableStringConnector; var builder = new StringBuilder(); AppendAccessorIsolateableString(accessor, builder, connector, designTimeType); builder.Append(extension); return(builder.ToString()); } }
public static string GenerateAccessorKey(DbContextAccessorBase accessor, string invokeTypeName, Type designTimeType = null, params string[] partialKeys) { accessor.NotNull(nameof(accessor)); invokeTypeName.NotNull(nameof(invokeTypeName)); var connector = DataSettings.Preference.AccessorIsolateableStringConnector; var builder = new StringBuilder(); builder.Append(invokeTypeName); builder.Append(connector); AppendAccessorIsolateableString(accessor, builder, connector, designTimeType); partialKeys.ForEach((key, index) => { builder.Append(key); if (index < partialKeys.Length - 1) { builder.Append(connector); } }); return(builder.ToString()); }
/// <summary> /// 生成访问器(持久化)文件路径组合器(支持访问器、设计时、连接字符串、租户隔离)。 /// </summary> /// <param name="accessor">给定的 <see cref="DbContextAccessorBase"/>。</param> /// <param name="extension">给定的文件扩展名。</param> /// <param name="basePathFactory">给定的基础路径工厂方法。</param> /// <param name="designTimeType">给定的设计时类型(可选)。</param> /// <returns>返回 <see cref="FilePathCombiner"/>。</returns> public static FilePathCombiner GenerateAccessorFilePath(DbContextAccessorBase accessor, string extension, Func <DataBuilderDependency, string> basePathFactory, Type designTimeType = null) { var basePath = basePathFactory?.Invoke(accessor?.Dependency); return(GenerateAccessorFilePath(accessor, extension, basePath, designTimeType)); }
public static string GenerateAccessorKey(DbContextAccessorBase accessor, Type invokeType, Type designTimeType = null, params string[] partialKeys) => GenerateAccessorKey(accessor, invokeType.GetDisplayName(true), designTimeType, partialKeys);
/// <summary> /// 获取迁移缓存键。 /// </summary> /// <param name="dbContextAccessor">给定的数据库上下文访问器。</param> /// <returns>返回字符串。</returns> public static string GetMigrationCacheKey(DbContextAccessorBase dbContextAccessor) => GenerateAccessorKey(dbContextAccessor, "MigrationAccessorService");
public static void ConfigureDataStores <TAudit, TAuditProperty, TMigration, TTabulation, TTenant, TGenId, TIncremId, TCreatedBy> (this ModelBuilder modelBuilder, DbContextAccessorBase accessor) where TAudit : DataAudit <TGenId, TCreatedBy> where TAuditProperty : DataAuditProperty <TIncremId, TGenId> where TMigration : DataMigration <TGenId, TCreatedBy> where TTabulation : DataTabulation <TGenId, TCreatedBy> where TTenant : DataTenant <TGenId, TCreatedBy> where TGenId : IEquatable <TGenId> where TIncremId : IEquatable <TIncremId> where TCreatedBy : IEquatable <TCreatedBy> { modelBuilder.NotNull(nameof(modelBuilder)); accessor.NotNull(nameof(accessor)); var maxLength = accessor.Dependency.Options.Stores.MaxLengthForProperties; var protectPrivacyData = accessor.Dependency.Options.Stores.ProtectPrivacyData; var tables = accessor.Dependency.Options.Tables; var isGenIdString = typeof(TGenId).IsStringType(); if (tables.DefaultSchema.IsNotEmpty()) { modelBuilder.HasDefaultSchema(tables.DefaultSchema); } // 审计 modelBuilder.Entity <TAudit>(b => { b.ToTable(t => { if (tables.UseDataPrefix) { t.InsertDataPrefix(); } t.Configure(tables.Audit); }); b.HasIndex(i => new { i.TableName, i.EntityId, i.State }).HasName().IsUnique(); b.HasKey(k => k.Id); b.Property(p => p.Id).ValueGeneratedNever(); if (maxLength > 0) { if (isGenIdString) { b.Property(p => p.Id).HasMaxLength(maxLength); } b.Property(p => p.EntityId).HasMaxLength(maxLength).IsRequired(); b.Property(p => p.TableName).HasMaxLength(maxLength).IsRequired(); b.Property(p => p.StateName).HasMaxLength(maxLength); // 在 MySQL 中如果长度超出 255 会被转换为不能作为主键或唯一性约束 的 BLOB/TEXT 类型 b.Property(p => p.EntityTypeName).HasMaxLength(maxLength); } }); // 审计属性 modelBuilder.Entity <TAuditProperty>(b => { b.ToTable(t => { if (tables.UseDataPrefix) { t.InsertDataPrefix(); } // 按年月分表 t.AppendYearAndMonthSuffix(accessor.CurrentTimestamp) .Configure(tables.AuditProperty); }); b.HasIndex(i => new { i.AuditId }).HasName(); b.HasKey(k => k.Id); b.Property(x => x.Id).ValueGeneratedOnAdd(); if (maxLength > 0) { b.Property(p => p.AuditId).HasMaxLength(maxLength).IsRequired(); b.Property(p => p.PropertyName).HasMaxLength(maxLength); b.Property(p => p.PropertyTypeName).HasMaxLength(maxLength); } // MaxLength b.Property(p => p.OldValue); b.Property(p => p.NewValue); }); // 迁移 modelBuilder.Entity <TMigration>(b => { b.ToTable(t => { if (tables.UseDataPrefix) { t.InsertDataPrefix(); } t.Configure(tables.Migration); }); b.HasIndex(i => i.ModelHash).HasName().IsUnique(); b.HasKey(k => k.Id); b.Property(p => p.Id).ValueGeneratedNever(); if (maxLength > 0) { if (isGenIdString) { b.Property(p => p.Id).HasMaxLength(maxLength); } b.Property(p => p.ModelHash).HasMaxLength(maxLength).IsRequired(); b.Property(p => p.AccessorName).HasMaxLength(maxLength); b.Property(p => p.ModelSnapshotName).HasMaxLength(maxLength); } }); // 表格 modelBuilder.Entity <TTabulation>(b => { b.ToTable(t => { if (tables.UseDataPrefix) { t.InsertDataPrefix(); } t.Configure(tables.Tabulation); }); b.HasIndex(i => new { i.Schema, i.TableName }).HasName().IsUnique(); b.HasKey(k => k.Id); b.Property(p => p.Id).ValueGeneratedNever(); if (maxLength > 0) { if (isGenIdString) { b.Property(p => p.Id).HasMaxLength(maxLength); } b.Property(p => p.Schema).HasMaxLength(maxLength).IsRequired(); b.Property(p => p.TableName).HasMaxLength(maxLength).IsRequired(); b.Property(p => p.EntityName).HasMaxLength(maxLength); b.Property(p => p.AssemblyName).HasMaxLength(maxLength); b.Property(p => p.Description).HasMaxLength(maxLength); } b.Property(p => p.IsSharding).HasDefaultValue(false); }); // 租户 modelBuilder.Entity <TTenant>(b => { b.ToTable(t => { if (tables.UseDataPrefix) { t.InsertDataPrefix(); } t.Configure(tables.Tenant); }); b.HasIndex(i => new { i.Name, i.Host }).HasName().IsUnique(); b.HasKey(k => k.Id); b.Property(p => p.Id).ValueGeneratedNever(); if (maxLength > 0) { if (isGenIdString) { b.Property(p => p.Id).HasMaxLength(maxLength); } b.Property(p => p.Name).HasMaxLength(maxLength).IsRequired(); b.Property(p => p.Host).HasMaxLength(maxLength).IsRequired(); b.Property(p => p.DefaultConnectionString).HasMaxLength(maxLength).IsRequired(); b.Property(p => p.WritingConnectionString).HasMaxLength(maxLength); } if (protectPrivacyData) { var protector = accessor.GetService <IPrivacyDataProtector>(); b.ConfigurePrivacyData(protector); } }); }