merge from AddDbContextBase to dev

This commit is contained in:
Оля Бизюкова 2024-12-10 11:27:22 +05:00
commit bd8a440aa6
14 changed files with 180 additions and 215 deletions

View File

@ -59,7 +59,7 @@ public class Startup
using var scope = host.Services.CreateScope(); using var scope = host.Services.CreateScope();
var provider = scope.ServiceProvider; var provider = scope.ServiceProvider;
var context = provider.GetRequiredService<PersistenceDbContext>(); var context = provider.GetRequiredService<PersistencePostgresContext>();
context.Database.EnsureCreatedAndMigrated(); context.Database.EnsureCreatedAndMigrated();
} }

View File

@ -11,10 +11,10 @@ public static class DependencyInjection
{ {
string connectionStringName = "DefaultConnection"; string connectionStringName = "DefaultConnection";
services.AddDbContext<PersistenceDbContext>(options => services.AddDbContext<PersistencePostgresContext>(options =>
options.UseNpgsql(configuration.GetConnectionString(connectionStringName))); options.UseNpgsql(configuration.GetConnectionString(connectionStringName)));
services.AddScoped<DbContext>(provider => provider.GetRequiredService<PersistenceDbContext>()); services.AddScoped<DbContext>(provider => provider.GetRequiredService<PersistencePostgresContext>());
return services; return services;
} }

View File

@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Npgsql;
using Persistence.Database.Model;
namespace Persistence.Database.Postgres;
/// <summary>
/// Фабрика контекста для dotnet ef миграций
/// </summary>
public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<PersistencePostgresContext>
{
public PersistencePostgresContext CreateDbContext(string[] args)
{
var connectionStringBuilder = new NpgsqlConnectionStringBuilder();
connectionStringBuilder.Host = "localhost";
connectionStringBuilder.Database = "persistence";
connectionStringBuilder.Username = "postgres";
connectionStringBuilder.Password = "q";
connectionStringBuilder.PersistSecurityInfo = true;
var connectionString = connectionStringBuilder.ToString();
var optionsBuilder = new DbContextOptionsBuilder<PersistencePostgresContext>();
optionsBuilder.UseNpgsql(connectionString);
var context = new PersistencePostgresContext(optionsBuilder.Options);
return context;
}
}

View File

@ -49,10 +49,13 @@ public static class EFExtensionsInitialization
var migrations = db.GetPendingMigrations() var migrations = db.GetPendingMigrations()
.Select(migration => $" ('{migration}', '{efVersionString}')"); .Select(migration => $" ('{migration}', '{efVersionString}')");
var sqlAddLastMigration = if (migrations.Any())
$"INSERT INTO public.\"__EFMigrationsHistory\" " + {
$"(\"MigrationId\", \"ProductVersion\") " + var sqlAddLastMigration =
$"VALUES {string.Join(',', migrations)};"; $"INSERT INTO public.\"__EFMigrationsHistory\" " +
db.ExecuteSqlRaw(sqlAddLastMigration); $"(\"MigrationId\", \"ProductVersion\") " +
$"VALUES {string.Join(',', migrations)};";
db.ExecuteSqlRaw(sqlAddLastMigration);
}
} }
} }

View File

@ -1,115 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Persistence.Database.Model;
#nullable disable
namespace Persistence.Database.Postgres.Migrations
{
[DbContext(typeof(PersistenceDbContext))]
[Migration("20241122074646_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.UseCollation("Russian_Russia.1251")
.HasAnnotation("ProductVersion", "8.0.10")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack");
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Persistence.Database.Model.DataSaub", b =>
{
b.Property<DateTimeOffset>("Date")
.HasColumnType("timestamp with time zone")
.HasColumnName("date");
b.Property<double?>("AxialLoad")
.HasColumnType("double precision")
.HasColumnName("axialLoad");
b.Property<double?>("BitDepth")
.HasColumnType("double precision")
.HasColumnName("bitDepth");
b.Property<double?>("BlockPosition")
.HasColumnType("double precision")
.HasColumnName("blockPosition");
b.Property<double?>("BlockSpeed")
.HasColumnType("double precision")
.HasColumnName("blockSpeed");
b.Property<double?>("Flow")
.HasColumnType("double precision")
.HasColumnName("flow");
b.Property<double?>("HookWeight")
.HasColumnType("double precision")
.HasColumnName("hookWeight");
b.Property<int>("IdFeedRegulator")
.HasColumnType("integer")
.HasColumnName("idFeedRegulator");
b.Property<int?>("Mode")
.HasColumnType("integer")
.HasColumnName("mode");
b.Property<double?>("Mse")
.HasColumnType("double precision")
.HasColumnName("mse");
b.Property<short>("MseState")
.HasColumnType("smallint")
.HasColumnName("mseState");
b.Property<double?>("Pressure")
.HasColumnType("double precision")
.HasColumnName("pressure");
b.Property<double?>("Pump0Flow")
.HasColumnType("double precision")
.HasColumnName("pump0Flow");
b.Property<double?>("Pump1Flow")
.HasColumnType("double precision")
.HasColumnName("pump1Flow");
b.Property<double?>("Pump2Flow")
.HasColumnType("double precision")
.HasColumnName("pump2Flow");
b.Property<double?>("RotorSpeed")
.HasColumnType("double precision")
.HasColumnName("rotorSpeed");
b.Property<double?>("RotorTorque")
.HasColumnType("double precision")
.HasColumnName("rotorTorque");
b.Property<string>("User")
.HasColumnType("text")
.HasColumnName("user");
b.Property<double?>("WellDepth")
.HasColumnType("double precision")
.HasColumnName("wellDepth");
b.HasKey("Date");
b.ToTable("DataSaub");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -11,9 +11,9 @@ using Persistence.Database.Model;
namespace Persistence.Database.Postgres.Migrations namespace Persistence.Database.Postgres.Migrations
{ {
[DbContext(typeof(PersistenceDbContext))] [DbContext(typeof(PersistencePostgresContext))]
[Migration("20241118052225_SetpointMigration")] [Migration("20241126100631_Init")]
partial class SetpointMigration partial class Init
{ {
/// <inheritdoc /> /// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder) protected override void BuildTargetModel(ModelBuilder modelBuilder)
@ -27,14 +27,34 @@ namespace Persistence.Database.Postgres.Migrations
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack"); NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack");
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Persistence.Database.Entity.TimestampedSet", b =>
{
b.Property<Guid>("IdDiscriminator")
.HasColumnType("uuid")
.HasComment("Дискриминатор ссылка на тип сохраняемых данных");
b.Property<DateTimeOffset>("Timestamp")
.HasColumnType("timestamp with time zone")
.HasComment("Отметка времени, строго в UTC");
b.Property<string>("Set")
.IsRequired()
.HasColumnType("jsonb")
.HasComment("Набор сохраняемых данных");
b.HasKey("IdDiscriminator", "Timestamp");
b.ToTable("TimestampedSets", t =>
{
t.HasComment("Общая таблица данных временных рядов");
});
});
modelBuilder.Entity("Persistence.Database.Model.DataSaub", b => modelBuilder.Entity("Persistence.Database.Model.DataSaub", b =>
{ {
b.Property<int>("Id") b.Property<DateTimeOffset>("Date")
.ValueGeneratedOnAdd() .HasColumnType("timestamp with time zone")
.HasColumnType("integer") .HasColumnName("date");
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<double?>("AxialLoad") b.Property<double?>("AxialLoad")
.HasColumnType("double precision") .HasColumnType("double precision")
@ -100,10 +120,6 @@ namespace Persistence.Database.Postgres.Migrations
.HasColumnType("double precision") .HasColumnType("double precision")
.HasColumnName("rotorTorque"); .HasColumnName("rotorTorque");
b.Property<int>("TimeStamp")
.HasColumnType("integer")
.HasColumnName("timestamp");
b.Property<string>("User") b.Property<string>("User")
.HasColumnType("text") .HasColumnType("text")
.HasColumnName("user"); .HasColumnName("user");
@ -112,7 +128,7 @@ namespace Persistence.Database.Postgres.Migrations
.HasColumnType("double precision") .HasColumnType("double precision")
.HasColumnName("wellDepth"); .HasColumnName("wellDepth");
b.HasKey("Id"); b.HasKey("Date");
b.ToTable("DataSaub"); b.ToTable("DataSaub");
}); });
@ -125,7 +141,7 @@ namespace Persistence.Database.Postgres.Migrations
b.Property<DateTimeOffset>("Created") b.Property<DateTimeOffset>("Created")
.HasColumnType("timestamp with time zone") .HasColumnType("timestamp with time zone")
.HasComment("Дата изменения уставки"); .HasComment("Дата создания уставки");
b.Property<int>("IdUser") b.Property<int>("IdUser")
.HasColumnType("integer") .HasColumnType("integer")

View File

@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
namespace Persistence.Database.Postgres.Migrations namespace Persistence.Database.Postgres.Migrations
{ {
/// <inheritdoc /> /// <inheritdoc />
public partial class InitialCreate : Migration public partial class Init : Migration
{ {
/// <inheritdoc /> /// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
@ -42,6 +42,34 @@ namespace Persistence.Database.Postgres.Migrations
{ {
table.PrimaryKey("PK_DataSaub", x => x.date); table.PrimaryKey("PK_DataSaub", x => x.date);
}); });
migrationBuilder.CreateTable(
name: "Setpoint",
columns: table => new
{
Key = table.Column<Guid>(type: "uuid", nullable: false, comment: "Ключ"),
Created = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, comment: "Дата создания уставки"),
Value = table.Column<object>(type: "jsonb", nullable: false, comment: "Значение уставки"),
IdUser = table.Column<int>(type: "integer", nullable: false, comment: "Id автора последнего изменения")
},
constraints: table =>
{
table.PrimaryKey("PK_Setpoint", x => new { x.Key, x.Created });
});
migrationBuilder.CreateTable(
name: "TimestampedSets",
columns: table => new
{
IdDiscriminator = table.Column<Guid>(type: "uuid", nullable: false, comment: "Дискриминатор ссылка на тип сохраняемых данных"),
Timestamp = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, comment: "Отметка времени, строго в UTC"),
Set = table.Column<string>(type: "jsonb", nullable: false, comment: "Набор сохраняемых данных")
},
constraints: table =>
{
table.PrimaryKey("PK_TimestampedSets", x => new { x.IdDiscriminator, x.Timestamp });
},
comment: "Общая таблица данных временных рядов");
} }
/// <inheritdoc /> /// <inheritdoc />
@ -49,6 +77,12 @@ namespace Persistence.Database.Postgres.Migrations
{ {
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "DataSaub"); name: "DataSaub");
migrationBuilder.DropTable(
name: "Setpoint");
migrationBuilder.DropTable(
name: "TimestampedSets");
} }
} }
} }

View File

@ -11,8 +11,8 @@ using Persistence.Database.Model;
namespace Persistence.Database.Postgres.Migrations namespace Persistence.Database.Postgres.Migrations
{ {
[DbContext(typeof(PersistenceDbContext))] [DbContext(typeof(PersistencePostgresContext))]
partial class PersistenceDbContextModelSnapshot : ModelSnapshot partial class PersistencePostgresContextModelSnapshot : ModelSnapshot
{ {
protected override void BuildModel(ModelBuilder modelBuilder) protected override void BuildModel(ModelBuilder modelBuilder)
{ {

View File

@ -1,58 +0,0 @@
using Microsoft.EntityFrameworkCore;
using Persistence.Database.Entity;
namespace Persistence.Database.Model;
public partial class PersistenceDbContext : DbContext
{
public DbSet<DataSaub> DataSaub => Set<DataSaub>();
public DbSet<ChangeLog> ChangeLog => Set<ChangeLog>();
public DbSet<Setpoint> Setpoint => Set<Setpoint>();
public DbSet<TechMessage> TechMessage => Set<TechMessage>();
public DbSet<TimestampedSet> TimestampedSets => Set<TimestampedSet>();
public PersistenceDbContext()
: base()
{
}
public PersistenceDbContext(DbContextOptions<PersistenceDbContext> options)
: base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
optionsBuilder.UseNpgsql("Host=localhost;Database=persistence;Username=postgres;Password=q;Persist Security Info=True;Include Error Detail=True;"
//, builder=>builder.EnableRetryOnFailure(2, System.TimeSpan.FromMinutes(1))
);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasPostgresExtension("adminpack")
.HasAnnotation("Relational:Collation", "Russian_Russia.1251");
modelBuilder.Entity<TimestampedSet>()
.Property(e => e.Set)
.HasJsonConversion();
modelBuilder.Entity<TechMessage>(entity =>
{
entity.HasOne(t => t.System)
.WithMany()
.HasForeignKey(t => t.SystemId)
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity<ChangeLog>()
.Property(e => e.Value)
.HasJsonConversion();
}
}

View File

@ -0,0 +1,23 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure.Internal;
namespace Persistence.Database.Model;
/// <summary>
/// EF êîíòåêñò äëÿ ÁÄ Postgres
/// </summary>
public partial class PersistencePostgresContext : PersistenceDbContext
{
public PersistencePostgresContext(DbContextOptions options)
: base(options)
{}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasPostgresExtension("adminpack")
.HasAnnotation("Relational:Collation", "Russian_Russia.1251");
base.OnModelCreating(modelBuilder);
}
}

View File

@ -0,0 +1,36 @@
using Microsoft.EntityFrameworkCore;
using Persistence.Database.Entity;
using Persistence.Database.Model;
namespace Persistence.Database;
/// <summary>
/// EF контекст для любых БД поддерживаемых в EF
/// </summary>
public class PersistenceDbContext : DbContext
{
public DbSet<DataSaub> DataSaub => Set<DataSaub>();
public DbSet<Setpoint> Setpoint => Set<Setpoint>();
public DbSet<TimestampedSet> TimestampedSets => Set<TimestampedSet>();
public DbSet<ChangeLog> ChangeLog => Set<ChangeLog>();
public PersistenceDbContext(DbContextOptions options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TimestampedSet>()
.Property(e => e.Set)
.HasJsonConversion();
modelBuilder.Entity<ChangeLog>()
.Property(e => e.Value)
.HasJsonConversion();
}
}

View File

@ -1,10 +1,7 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Persistence.Database;
using Persistence.Database.Model; using Persistence.Database.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit; using Xunit;
namespace Persistence.IntegrationTests; namespace Persistence.IntegrationTests;
@ -19,7 +16,7 @@ public abstract class BaseIntegrationTest : IClassFixture<WebAppFactoryFixture>,
{ {
scope = factory.Services.CreateScope(); scope = factory.Services.CreateScope();
dbContext = scope.ServiceProvider.GetRequiredService<PersistenceDbContext>(); dbContext = scope.ServiceProvider.GetRequiredService<PersistencePostgresContext>();
} }
public void Dispose() public void Dispose()

View File

@ -1,10 +1,11 @@
using Persistence.Database.Model; using Persistence.Database;
using Persistence.Database.Model;
namespace Persistence.IntegrationTests.Extensions; namespace Persistence.IntegrationTests.Extensions;
public static class EFCoreExtensions public static class EFCoreExtensions
{ {
public static void CleanupDbSet<T>(this PersistenceDbContext dbContext) public static void CleanupDbSet<T>(this PersistenceDbContext dbContext)
where T : class where T : class
{ {
var dbset = dbContext.Set<T>(); var dbset = dbContext.Set<T>();

View File

@ -5,7 +5,6 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using Persistence.API; using Persistence.API;
using Persistence.Database;
using Persistence.Client; using Persistence.Client;
using Persistence.Database.Model; using Persistence.Database.Model;
using Persistence.Database.Postgres; using Persistence.Database.Postgres;
@ -28,10 +27,11 @@ public class WebAppFactoryFixture : WebApplicationFactory<Startup>
builder.ConfigureServices(services => builder.ConfigureServices(services =>
{ {
var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<PersistenceDbContext>)); var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<PersistencePostgresContext>));
if (descriptor != null) if (descriptor != null)
services.Remove(descriptor); services.Remove(descriptor);
services.AddDbContext<PersistenceDbContext>(options =>
services.AddDbContext<PersistencePostgresContext>(options =>
options.UseNpgsql(connectionString)); options.UseNpgsql(connectionString));
services.RemoveAll<IHttpClientFactory>(); services.RemoveAll<IHttpClientFactory>();
@ -47,7 +47,7 @@ public class WebAppFactoryFixture : WebApplicationFactory<Startup>
using var scope = serviceProvider.CreateScope(); using var scope = serviceProvider.CreateScope();
var scopedServices = scope.ServiceProvider; var scopedServices = scope.ServiceProvider;
var dbContext = scopedServices.GetRequiredService<PersistenceDbContext>(); var dbContext = scopedServices.GetRequiredService<PersistencePostgresContext>();
dbContext.Database.EnsureCreatedAndMigrated(); dbContext.Database.EnsureCreatedAndMigrated();
dbContext.SaveChanges(); dbContext.SaveChanges();
}); });
@ -55,8 +55,8 @@ public class WebAppFactoryFixture : WebApplicationFactory<Startup>
public override async ValueTask DisposeAsync() public override async ValueTask DisposeAsync()
{ {
var dbContext = new PersistenceDbContext( var dbContext = new PersistencePostgresContext(
new DbContextOptionsBuilder<PersistenceDbContext>() new DbContextOptionsBuilder<PersistencePostgresContext>()
.UseNpgsql(connectionString) .UseNpgsql(connectionString)
.Options); .Options);