Beispiel #1
0
        public IReadOnlyList <MigrationCommand> FilterExecuted(DbContextAccessorBase accessor,
                                                               IEnumerable <MigrationCommand> commands)
        {
            accessor.NotNull(nameof(accessor));
            commands.NotNull(nameof(commands));

            var filePath   = GetFilePathCombiner(accessor);
            var cacheInfos = MemoryCache.GetOrCreate(GetCacheKey(filePath), entry =>
            {
                if (filePath.Exists())
                {
                    return(filePath.ReadJson <List <MigrationCommandInfo> >(_defaultEncoding));
                }

                return(new List <MigrationCommandInfo>());
            });

            var execCommands = new List <MigrationCommand>();

            foreach (var command in commands)
            {
                var info = new MigrationCommandInfo(command.CommandText)
                           .SetConnectionString(accessor);

                if (!cacheInfos.Contains(info))
                {
                    cacheInfos.Add(info);
                    execCommands.Add(command);
                }
            }

            return(execCommands);
        }
        public static void ConfigurePortalStores <TEditor, TInternalUser, TGenId, TUserId, TCreatedBy>
            (this ModelBuilder modelBuilder, DbContextAccessorBase accessor)
            where TEditor : PortalEditor <TGenId, TUserId, TCreatedBy>
            where TInternalUser : PortalInternalUser <TGenId, TCreatedBy>
            where TGenId : IEquatable <TGenId>
            where TUserId : IEquatable <TUserId>
            where TCreatedBy : IEquatable <TCreatedBy>
        {
            modelBuilder.NotNull(nameof(modelBuilder));
            accessor.NotNull(nameof(accessor));

            var options = accessor.GetService <IOptions <PortalBuilderOptions> >().Value;

            var mapRelationship = options.Stores?.MapRelationship ?? true;
            var usePortalPrefix = options.Tables.UsePortalPrefix;

            modelBuilder.Entity <TEditor>(b =>
            {
                b.ToTable(table =>
                {
                    if (usePortalPrefix)
                    {
                        table.InsertPortalPrefix();
                    }

                    table.Configure(options.Tables.Editor);
                });

                b.HasKey(k => k.Id);

                b.HasIndex(i => new { i.UserId, i.Name }).HasName().IsUnique();

                b.Property(p => p.Name).HasMaxLength(256);
                b.Property(p => p.Description).HasMaxLength(256);
                b.Property(p => p.Portrait).HasMaxLength(256);
            });

            modelBuilder.Entity <TInternalUser>(b =>
            {
                b.ToTable(table =>
                {
                    if (usePortalPrefix)
                    {
                        table.InsertPortalPrefix();
                    }

                    table.Configure(options.Tables.InternalUser);
                });

                b.HasKey(k => k.Id);

                b.HasIndex(i => i.Name).HasName().IsUnique();

                b.Property(p => p.Name).HasMaxLength(256);
            });
        }
Beispiel #3
0
        public IReadOnlyList <MigrationCommandInfo> SaveExecuted(DbContextAccessorBase accessor)
        {
            accessor.NotNull(nameof(accessor));

            var filePath = GetFilePathCombiner(accessor);

            var cacheInfos = MemoryCache.Get <List <MigrationCommandInfo> >(GetCacheKey(filePath));

            filePath.WriteJson(cacheInfos, _defaultEncoding);

            return(cacheInfos);
        }
Beispiel #4
0
        protected virtual (byte[] body, string hash) CreateModelSnapshot(DbContextAccessorBase dbContextAccessor,
                                                                         out TypeNameCombiner modelSnapshotTypeName)
        {
            var typeName = ModelSnapshotCompiler.GenerateTypeName(dbContextAccessor.CurrentType);

            var result = ExtensionSettings.Preference.RunLocker(() =>
            {
                return(ModelSnapshotCompiler.CompileInMemory(dbContextAccessor,
                                                             dbContextAccessor.Model, typeName));
            });

            modelSnapshotTypeName = typeName;

            return(result);
        }
Beispiel #5
0
        public static FilePathCombiner CompileInFile(DbContextAccessorBase accessor,
                                                     IModel model, DataBuilderOptions options, FilePathCombiner filePath)
        {
            accessor.NotNull(nameof(accessor));
            model.NotNull(nameof(model));

            var accessorType = accessor.GetType();
            var typeName     = GenerateTypeName(accessorType);

            var generator  = accessor.GetService <IMigrationsCodeGenerator>();
            var sourceCode = generator.GenerateSnapshot(typeName.Namespace, accessorType,
                                                        typeName.Name, model);

            var references = GetMetadataReferences(options, accessorType);

            return(CSharpCompiler.CompileInFile(filePath, references, sourceCode));
        }
Beispiel #6
0
        public static (byte[] body, string hash) CompileInMemory(DbContextAccessorBase accessor,
                                                                 IModel model, TypeNameCombiner typeName)
        {
            accessor.NotNull(nameof(accessor));
            model.NotNull(nameof(model));
            typeName.NotNull(nameof(typeName));

            var generator = accessor.GetService <IMigrationsCodeGenerator>();

            var sourceCode = generator.GenerateSnapshot(typeName.Namespace, accessor.CurrentType,
                                                        typeName.Name, model);

            var references = GetMetadataReferences(accessor.Dependency.Options, accessor.CurrentType);

            var buffer   = CSharpCompiler.CompileInMemory(references, sourceCode);
            var encoding = ExtensionSettings.Preference.DefaultEncoding;

            return(StoreAssembly(buffer), sourceCode.Sha256Base64String(encoding));
        }
 private static FilePathCombiner GetReportFilePath(DbContextAccessorBase accessor)
 => DbContextAccessorHelper.GenerateAccessorFilePath(accessor,
                                                     ".txt", d => d.DatabasesReportDirectory);
        public static void ConfigureContentStores <TCategory, TSource, TClaim, TTag, TUnit, TUnitClaim, TUnitTag, TUnitVisitCount, TPane, TPaneClaim, TGenId, TIncremId, TPublishedBy>
            (this ModelBuilder modelBuilder, DbContextAccessorBase accessor)
            where TCategory : ContentCategory <TIncremId, TPublishedBy>
            where TSource : ContentSource <TIncremId, TPublishedBy>
            where TClaim : ContentClaim <TIncremId, TIncremId, TPublishedBy>
            where TTag : ContentTag <TIncremId, TPublishedBy>
            where TUnit : ContentUnit <TGenId, TIncremId, TIncremId, TIncremId, TPublishedBy>
            where TUnitClaim : ContentUnitClaim <TIncremId, TGenId, TIncremId, TPublishedBy>
            where TUnitTag : ContentUnitTag <TIncremId, TGenId, TIncremId>
            where TUnitVisitCount : ContentUnitVisitCount <TGenId>
            where TPane : ContentPane <TIncremId, TPublishedBy>
            where TPaneClaim : ContentPaneClaim <TIncremId, TIncremId, TIncremId, TPublishedBy>
            where TGenId : IEquatable <TGenId>
            where TIncremId : IEquatable <TIncremId>
            where TPublishedBy : IEquatable <TPublishedBy>
        {
            modelBuilder.NotNull(nameof(modelBuilder));
            accessor.NotNull(nameof(accessor));

            var options = accessor.GetService <IOptions <ContentBuilderOptions> >().Value;

            var mapRelationship  = options.Stores?.MapRelationship ?? true;
            var useContentPrefix = options.Tables.UseContentPrefix;

            modelBuilder.Entity <TCategory>(b =>
            {
                b.ToTable(table =>
                {
                    if (useContentPrefix)
                    {
                        table.InsertContentPrefix();
                    }

                    table.Configure(options.Tables.Category);
                });

                b.HasKey(k => k.Id);

                b.HasIndex(i => new { i.ParentId, i.Name }).HasName().IsUnique();

                b.Property(p => p.Id).ValueGeneratedOnAdd();
                b.Property(p => p.ParentId).HasDefaultValue(default(TIncremId));
                b.Property(p => p.Name).HasMaxLength(50).IsRequired();
                b.Property(p => p.Description).HasMaxLength(256);

                if (mapRelationship)
                {
                    b.HasMany <TUnit>().WithOne().HasForeignKey(fk => fk.CategoryId).IsRequired();
                }
            });

            modelBuilder.Entity <TSource>(b =>
            {
                b.ToTable(table =>
                {
                    if (useContentPrefix)
                    {
                        table.InsertContentPrefix();
                    }

                    table.Configure(options.Tables.Source);
                });

                b.HasKey(k => k.Id);

                b.HasIndex(i => new { i.ParentId, i.Name }).HasName().IsUnique();

                b.Property(p => p.Id).ValueGeneratedOnAdd();
                b.Property(p => p.ParentId).HasDefaultValue(default(TIncremId));
                b.Property(p => p.Name).HasMaxLength(50).IsRequired();
                b.Property(p => p.Description).HasMaxLength(256);
                b.Property(p => p.Website).HasMaxLength(256);
                b.Property(p => p.Weblogo).HasMaxLength(256);

                if (mapRelationship)
                {
                    b.HasMany <TUnit>().WithOne().HasForeignKey(fk => fk.SourceId).IsRequired();
                }
            });

            modelBuilder.Entity <TClaim>(b =>
            {
                b.ToTable(table =>
                {
                    if (useContentPrefix)
                    {
                        table.InsertContentPrefix();
                    }

                    table.Configure(options.Tables.Claim);
                });

                b.HasKey(k => k.Id);

                b.HasIndex(i => i.Name).HasName().IsUnique();

                b.Property(p => p.Id).ValueGeneratedOnAdd();
                b.Property(p => p.Name).HasMaxLength(50).IsRequired();
                b.Property(p => p.Description).HasMaxLength(256);

                if (mapRelationship)
                {
                    b.HasMany <TPaneClaim>().WithOne().HasForeignKey(fk => fk.ClaimId).IsRequired();
                    b.HasMany <TUnitClaim>().WithOne().HasForeignKey(fk => fk.ClaimId).IsRequired();
                }
            });

            modelBuilder.Entity <TTag>(b =>
            {
                b.ToTable(table =>
                {
                    if (useContentPrefix)
                    {
                        table.InsertContentPrefix();
                    }

                    table.Configure(options.Tables.Tag);
                });

                b.HasKey(k => k.Id);

                b.HasIndex(i => i.Name).HasName().IsUnique();

                b.Property(p => p.Id).ValueGeneratedOnAdd();
                b.Property(p => p.Name).HasMaxLength(50).IsRequired();

                if (mapRelationship)
                {
                    b.HasMany <TUnitTag>().WithOne().HasForeignKey(fk => fk.TagId).IsRequired();
                }
            });

            modelBuilder.Entity <TUnit>(b =>
            {
                b.ToTable(table =>
                {
                    if (useContentPrefix)
                    {
                        table.InsertContentPrefix();
                    }

                    // 按季度分表
                    table.AppendYearAndQuarterSuffix(accessor.CurrentTimestamp);
                    table.Configure(options.Tables.Unit);
                });

                b.HasKey(k => k.Id);

                b.HasIndex(i => new { i.CategoryId, i.Title }).HasName().IsUnique();
                b.HasIndex(i => new { i.PublishedBy, i.PublishedTime }).HasName();

                b.Property(p => p.Title).HasMaxLength(256).IsRequired();
                b.Property(p => p.Subtitle).HasMaxLength(256);
                b.Property(p => p.Reference).HasMaxLength(256);
                b.Property(p => p.PublishedAs).HasMaxLength(256);

                if (mapRelationship)
                {
                    b.HasMany <TCategory>().WithOne().HasForeignKey(fk => fk.Id).IsRequired();
                    b.HasMany <TPane>().WithOne().HasForeignKey(fk => fk.Id).IsRequired();
                    b.HasMany <TSource>().WithOne().HasForeignKey(fk => fk.Id).IsRequired();
                    b.HasMany <TUnitClaim>().WithOne().HasForeignKey(fk => fk.UnitId).IsRequired();
                    b.HasMany <TUnitVisitCount>().WithOne().HasForeignKey(fk => fk.UnitId).IsRequired();
                }
            });

            modelBuilder.Entity <TUnitClaim>(b =>
            {
                b.ToTable(table =>
                {
                    if (useContentPrefix)
                    {
                        table.InsertContentPrefix();
                    }

                    table.Configure(options.Tables.UnitClaim);
                });

                b.HasKey(k => k.Id);

                b.HasIndex(i => new { i.UnitId, i.ClaimId }).HasName();

                b.Property(p => p.Id).ValueGeneratedOnAdd();
                b.Property(p => p.ClaimValue).IsRequired(); // 不限长度

                if (mapRelationship)
                {
                    b.HasMany <TClaim>().WithOne().HasForeignKey(fk => fk.Id).IsRequired();
                    b.HasMany <TUnit>().WithOne().HasForeignKey(fk => fk.Id).IsRequired();
                }
            });

            modelBuilder.Entity <TUnitTag>(b =>
            {
                b.ToTable(table =>
                {
                    if (useContentPrefix)
                    {
                        table.InsertContentPrefix();
                    }

                    table.Configure(options.Tables.UnitTag);
                });

                b.HasKey(k => k.Id);

                b.HasIndex(i => new { i.UnitId, i.TagId }).HasName();

                b.Property(p => p.Id).ValueGeneratedOnAdd();

                if (mapRelationship)
                {
                    b.HasMany <TTag>().WithOne().HasForeignKey(fk => fk.Id).IsRequired();
                    b.HasMany <TUnit>().WithOne().HasForeignKey(fk => fk.Id).IsRequired();
                }
            });

            modelBuilder.Entity <TUnitVisitCount>(b =>
            {
                b.ToTable(table =>
                {
                    if (useContentPrefix)
                    {
                        table.InsertContentPrefix();
                    }

                    table.Configure(options.Tables.UnitVisitCount);
                });

                b.HasKey(k => k.UnitId);

                b.Property(p => p.SupporterCount).HasDefaultValue(0);
                b.Property(p => p.ObjectorCount).HasDefaultValue(0);
                b.Property(p => p.FavoriteCount).HasDefaultValue(0);
                b.Property(p => p.RetweetCount).HasDefaultValue(0);

                b.Property(p => p.VisitCount).HasDefaultValue(0);
                b.Property(p => p.VisitorCount).HasDefaultValue(0);

                if (mapRelationship)
                {
                    b.HasMany <TUnit>().WithOne().HasForeignKey(fk => fk.Id).IsRequired();
                }
            });

            modelBuilder.Entity <TPane>(b =>
            {
                b.ToTable(table =>
                {
                    if (useContentPrefix)
                    {
                        table.InsertContentPrefix();
                    }

                    table.Configure(options.Tables.Pane);
                });

                b.HasKey(k => k.Id);

                b.HasIndex(i => new { i.ParentId, i.Name }).HasName().IsUnique();

                b.Property(p => p.Id).ValueGeneratedOnAdd();
                b.Property(p => p.ParentId).HasDefaultValue(default(TIncremId));
                b.Property(p => p.Name).HasMaxLength(256);
                b.Property(p => p.Description).HasMaxLength(256);
                b.Property(p => p.Icon).HasMaxLength(256);
                b.Property(p => p.More).HasMaxLength(256);

                if (mapRelationship)
                {
                    b.HasMany <TPaneClaim>().WithOne().HasForeignKey(fk => fk.PaneId).IsRequired();
                    b.HasMany <TUnit>().WithOne().HasForeignKey(fk => fk.PaneId).IsRequired();
                }
            });

            modelBuilder.Entity <TPaneClaim>(b =>
            {
                b.ToTable(table =>
                {
                    if (useContentPrefix)
                    {
                        table.InsertContentPrefix();
                    }

                    table.Configure(options.Tables.PaneClaim);
                });

                b.HasKey(k => k.Id);

                b.HasIndex(i => new { i.PaneId, i.ClaimId }).HasName();

                b.Property(p => p.Id).ValueGeneratedOnAdd();
                b.Property(p => p.ClaimValue).IsRequired(); // 不限长度

                if (mapRelationship)
                {
                    b.HasMany <TClaim>().WithOne().HasForeignKey(fk => fk.Id).IsRequired();
                    b.HasMany <TPane>().WithOne().HasForeignKey(fk => fk.Id).IsRequired();
                }
            });
        }
Beispiel #9
0
 private static FilePathCombiner GetFilePathCombiner(DbContextAccessorBase accessor)
 => DbContextAccessorHelper.GenerateAccessorFilePath(accessor, ".json",
                                                     dependency => dependency.MigrationsConfigDirectory);