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");
Esempio n. 7
0
        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);
                }
            });
        }