From 4284e9720b07cd8b63875e7eaa2eba2c1e3b57ba Mon Sep 17 00:00:00 2001 From: Marc Wittke Date: Tue, 22 Jan 2019 09:45:50 -0300 Subject: [PATCH 1/3] Requirement to create DbContexts with DbContextOptions removed. Instead, provide a factory function to decide this outside --- .../DatabaseManager.cs | 19 ++++++++--------- .../DatabaseManagerWithMigration.cs | 5 +++-- .../DatabaseManagerWithoutMigration.cs | 3 ++- .../DbContextExtensions.cs | 7 +------ .../SequenceHiLoIdGenerator.cs | 12 ++++++----- .../TenantManager.cs | 21 ++++++++++--------- .../TheDatabaseManager.cs | 4 ++-- .../TheTenantManager.cs | 5 +++-- 8 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/implementations/Backend.Fx.EfCorePersistence/DatabaseManager.cs b/src/implementations/Backend.Fx.EfCorePersistence/DatabaseManager.cs index bc373503..c48f7446 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/DatabaseManager.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/DatabaseManager.cs @@ -9,21 +9,20 @@ public abstract class DatabaseManager : IDatabaseManager where TDbContext : DbContext { + private readonly Func _dbContextFactory; private static readonly ILogger Logger = LogManager.Create>(); - - protected DatabaseManager(DbContextOptions dbContextOptions) + + protected DatabaseManager(Func dbContextFactory) { - DbContextOptions = dbContextOptions; + _dbContextFactory = dbContextFactory; } - + public bool DatabaseExists { get; protected set; } - public DbContextOptions DbContextOptions { get; } - public void EnsureDatabaseExistence() { Logger.Info("Ensuring database existence"); - using (var dbContext = DbContextOptions.CreateDbContext()) + using (var dbContext = _dbContextFactory()) { ExecuteCreationStrategy(dbContext); } @@ -44,7 +43,7 @@ private void EnsureSearchIndexExistence() .Select(t => t.GetTypeInfo()) .Where(t => t.IsClass && !t.IsAbstract && !t.IsGenericType && typeof(IFullTextSearchIndex).GetTypeInfo().IsAssignableFrom(t)); - using (var dbContext = DbContextOptions.CreateDbContext()) + using (var dbContext = _dbContextFactory()) { foreach (var fullTextSearchIndexType in fullTextSearchIndexTypes) { @@ -64,7 +63,7 @@ private void EnsureSequenceExistence() .Select(t => t.GetTypeInfo()) .Where(t => t.IsClass && !t.IsAbstract && !t.IsGenericType && typeof(ISequence).GetTypeInfo().IsAssignableFrom(t)); - using (var dbContext = DbContextOptions.CreateDbContext()) + using (var dbContext = _dbContextFactory()) { foreach (var sequenceType in sequenceTypes) { @@ -79,7 +78,7 @@ private void EnsureSequenceExistence() public virtual void DeleteDatabase() { - using (var dbContext = DbContextOptions.CreateDbContext()) + using (var dbContext = _dbContextFactory()) { Logger.Warn("Database is being deleted!"); dbContext.Database.EnsureDeleted(); diff --git a/src/implementations/Backend.Fx.EfCorePersistence/DatabaseManagerWithMigration.cs b/src/implementations/Backend.Fx.EfCorePersistence/DatabaseManagerWithMigration.cs index 90985bea..e475ced2 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/DatabaseManagerWithMigration.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/DatabaseManagerWithMigration.cs @@ -1,5 +1,6 @@ namespace Backend.Fx.EfCorePersistence { + using System; using Logging; using Microsoft.EntityFrameworkCore; @@ -7,9 +8,9 @@ public class DatabaseManagerWithMigration : DatabaseManager>(); - public DatabaseManagerWithMigration(DbContextOptions dbContextOptions) : base(dbContextOptions) + public DatabaseManagerWithMigration(Func dbContextFactory) : base(dbContextFactory) { } - + protected override void ExecuteCreationStrategy(DbContext dbContext) { Logger.Info("Migrating database to latest schema version"); diff --git a/src/implementations/Backend.Fx.EfCorePersistence/DatabaseManagerWithoutMigration.cs b/src/implementations/Backend.Fx.EfCorePersistence/DatabaseManagerWithoutMigration.cs index 9e30916a..36a13397 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/DatabaseManagerWithoutMigration.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/DatabaseManagerWithoutMigration.cs @@ -1,5 +1,6 @@ namespace Backend.Fx.EfCorePersistence { + using System; using Logging; using Microsoft.EntityFrameworkCore; @@ -7,7 +8,7 @@ public class DatabaseManagerWithoutMigration : DatabaseManager>(); - public DatabaseManagerWithoutMigration(DbContextOptions options) : base(options) + public DatabaseManagerWithoutMigration(Func dbContextFactory) : base(dbContextFactory) { } protected override void ExecuteCreationStrategy(DbContext dbContext) diff --git a/src/implementations/Backend.Fx.EfCorePersistence/DbContextExtensions.cs b/src/implementations/Backend.Fx.EfCorePersistence/DbContextExtensions.cs index 432870e5..ee0619b5 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/DbContextExtensions.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/DbContextExtensions.cs @@ -196,12 +196,7 @@ public static void TraceChangeTrackerState(this DbContext dbContext) } } } - - public static TDbContext CreateDbContext(this DbContextOptions options) where TDbContext : DbContext - { - return (TDbContext)Activator.CreateInstance(typeof(TDbContext), options); - } - + private static string GetPrimaryKeyValue(EntityEntry entry) { return (entry.Entity as Entity)?.Id.ToString(CultureInfo.InvariantCulture) ?? "?"; diff --git a/src/implementations/Backend.Fx.EfCorePersistence/SequenceHiLoIdGenerator.cs b/src/implementations/Backend.Fx.EfCorePersistence/SequenceHiLoIdGenerator.cs index a2a0417a..28858910 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/SequenceHiLoIdGenerator.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/SequenceHiLoIdGenerator.cs @@ -1,4 +1,6 @@ -namespace Backend.Fx.EfCorePersistence +using System; + +namespace Backend.Fx.EfCorePersistence { using Microsoft.EntityFrameworkCore; using Patterns.IdGeneration; @@ -6,17 +8,17 @@ public abstract class SequenceHiLoIdGenerator : HiLoIdGenerator, IEntityIdGenerator where TDbContext : DbContext { private readonly ISequence _sequence; - private readonly DbContextOptions _dbContextOptions; + private readonly Func _dbContextFactory; - protected SequenceHiLoIdGenerator(ISequence sequence, DbContextOptions dbContextOptions) + protected SequenceHiLoIdGenerator(ISequence sequence, Func dbContextFactory) { _sequence = sequence; - _dbContextOptions = dbContextOptions; + _dbContextFactory = dbContextFactory; } protected override int GetNextBlockStart() { - using (var dbContext = _dbContextOptions.CreateDbContext()) + using (var dbContext = _dbContextFactory()) { return _sequence.GetNextValue(dbContext); } diff --git a/src/implementations/Backend.Fx.EfCorePersistence/TenantManager.cs b/src/implementations/Backend.Fx.EfCorePersistence/TenantManager.cs index 10c98e49..888ad532 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/TenantManager.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/TenantManager.cs @@ -1,25 +1,26 @@ -namespace Backend.Fx.EfCorePersistence +using System.Linq; +using Backend.Fx.Extensions; + +namespace Backend.Fx.EfCorePersistence { using System; - using System.Linq; using Environment.MultiTenancy; - using Extensions; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; public class TenantManager : TenantManager where TDbContext : DbContext { - private readonly DbContextOptions _dbContextOptions; + private readonly Func _dbContextFactory; - public TenantManager(ITenantInitializer tenantInitializer, DbContextOptions dbContextOptions) + public TenantManager(ITenantInitializer tenantInitializer, Func dbContextFactory) : base(tenantInitializer) { - _dbContextOptions = dbContextOptions; + _dbContextFactory = dbContextFactory; } public override TenantId[] GetTenantIds() { - using (var dbContext = _dbContextOptions.CreateDbContext()) + using (var dbContext = _dbContextFactory()) { return dbContext.Set().Select(t => new TenantId(t.Id)).ToArray(); } @@ -27,7 +28,7 @@ public override TenantId[] GetTenantIds() public override Tenant[] GetTenants() { - using (var dbContext = _dbContextOptions.CreateDbContext()) + using (var dbContext = _dbContextFactory()) { return dbContext.Set().ToArray(); } @@ -36,7 +37,7 @@ public override Tenant[] GetTenants() [CanBeNull] public override Tenant FindTenant(TenantId tenantId) { - using (var dbContext = _dbContextOptions.CreateDbContext()) + using (var dbContext = _dbContextFactory()) { return dbContext.Set().Find(tenantId.Value); } @@ -44,7 +45,7 @@ public override Tenant FindTenant(TenantId tenantId) protected override void SaveTenant(Tenant tenant) { - using (var dbContext = _dbContextOptions.CreateDbContext()) + using (var dbContext = _dbContextFactory()) { var existingTenant = dbContext.Set().Find(tenant.Id); if (existingTenant == null) diff --git a/tests/Backend.Fx.EfCorePersistence.Tests/TheDatabaseManager.cs b/tests/Backend.Fx.EfCorePersistence.Tests/TheDatabaseManager.cs index 3e00a318..96fb179b 100644 --- a/tests/Backend.Fx.EfCorePersistence.Tests/TheDatabaseManager.cs +++ b/tests/Backend.Fx.EfCorePersistence.Tests/TheDatabaseManager.cs @@ -19,13 +19,13 @@ public TheDatabaseManager() { _dbFilePath = Path.GetTempFileName(); _dbContextOptions = new DbContextOptionsBuilder().UseSqlite("Data Source=" + _dbFilePath).Options; - _sut = new DatabaseManagerWithoutMigration(_dbContextOptions); + _sut = new DatabaseManagerWithoutMigration(() => new TestDbContext(_dbContextOptions)); } [Fact] public void CreatesDatabase() { - Assert.Throws(()=>new TestDbContext(_dbContextOptions).Tenants.ToArray()); + Assert.Throws(() => new TestDbContext(_dbContextOptions).Tenants.ToArray()); _sut.EnsureDatabaseExistence(); Assert.Empty(new TestDbContext(_dbContextOptions).Tenants); } diff --git a/tests/Backend.Fx.EfCorePersistence.Tests/TheTenantManager.cs b/tests/Backend.Fx.EfCorePersistence.Tests/TheTenantManager.cs index 03572fbb..cff360c7 100644 --- a/tests/Backend.Fx.EfCorePersistence.Tests/TheTenantManager.cs +++ b/tests/Backend.Fx.EfCorePersistence.Tests/TheTenantManager.cs @@ -63,7 +63,7 @@ public void CanGetTenants() Assert.Contains(tenants, t => t.Id == 4711); Assert.Contains(tenants, t => t.Id == 4712); Assert.Contains(tenants, t => t.Id == 4713); - + Assert.Contains(tenants, t => t.Id == 4714); } @@ -85,7 +85,8 @@ public void CanGetTenantIds() private class MyTenantManager : TenantManager { - public MyTenantManager(ITenantInitializer tenantInitializer, DbContextOptions dbContextOptions) : base(tenantInitializer, dbContextOptions) + public MyTenantManager(ITenantInitializer tenantInitializer, DbContextOptions dbContextOptions) + : base(tenantInitializer, () => new TestDbContext(dbContextOptions)) { } public Tenant FindTenantX(TenantId tenantId) From 46ad99bdec31551f11230f98e50296c505567fc6 Mon Sep 17 00:00:00 2001 From: Marc Wittke Date: Tue, 22 Jan 2019 10:23:16 -0300 Subject: [PATCH 2/3] ISequence is now relying on an IDbConnection instead of a DbContext instance --- .../DatabaseManager.cs | 2 +- .../Backend.Fx.EfCorePersistence/ISequence.cs | 10 +-- .../Mssql/MsSqlFullTextSearchService.cs | 3 + .../Mssql/MsSqlSequence.cs | 64 +++++++------- .../Oracle/OracleSequence.cs | 84 +++++++++++-------- .../Postgres/PostgresSequence.cs | 68 +++++++-------- .../SequenceHiLoIdGenerator.cs | 2 +- 7 files changed, 125 insertions(+), 108 deletions(-) diff --git a/src/implementations/Backend.Fx.EfCorePersistence/DatabaseManager.cs b/src/implementations/Backend.Fx.EfCorePersistence/DatabaseManager.cs index c48f7446..ca47208d 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/DatabaseManager.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/DatabaseManager.cs @@ -68,7 +68,7 @@ private void EnsureSequenceExistence() foreach (var sequenceType in sequenceTypes) { ISequence sequence = (ISequence)Activator.CreateInstance(sequenceType.AsType()); - sequence.EnsureSequence(dbContext); + sequence.EnsureSequence(dbContext.Database.GetDbConnection()); } } diff --git a/src/implementations/Backend.Fx.EfCorePersistence/ISequence.cs b/src/implementations/Backend.Fx.EfCorePersistence/ISequence.cs index 1c051304..79e2488b 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/ISequence.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/ISequence.cs @@ -1,11 +1,11 @@ -namespace Backend.Fx.EfCorePersistence -{ - using Microsoft.EntityFrameworkCore; +using System.Data; +namespace Backend.Fx.EfCorePersistence +{ public interface ISequence { - void EnsureSequence(DbContext dbContext); - int GetNextValue(DbContext dbContext); + void EnsureSequence(IDbConnection dbConnection); + int GetNextValue(IDbConnection dbConnection); int Increment { get; } } } diff --git a/src/implementations/Backend.Fx.EfCorePersistence/Mssql/MsSqlFullTextSearchService.cs b/src/implementations/Backend.Fx.EfCorePersistence/Mssql/MsSqlFullTextSearchService.cs index 88deb9ac..81fba67c 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/Mssql/MsSqlFullTextSearchService.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/Mssql/MsSqlFullTextSearchService.cs @@ -36,6 +36,9 @@ public MsSqlFullTextSearchService( public IQueryable Search(string searchQuery) { + // mitigate SQL injection + searchQuery = searchQuery.Replace("\'", ""); + string ftsQuery = _easyFts.ToFtsQuery(searchQuery); IQueryable queryable; diff --git a/src/implementations/Backend.Fx.EfCorePersistence/Mssql/MsSqlSequence.cs b/src/implementations/Backend.Fx.EfCorePersistence/Mssql/MsSqlSequence.cs index 0a388a70..008e6562 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/Mssql/MsSqlSequence.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/Mssql/MsSqlSequence.cs @@ -1,60 +1,58 @@ namespace Backend.Fx.EfCorePersistence.Mssql { using System; - using System.Data.Common; + using System.Data; using Logging; - using Microsoft.EntityFrameworkCore; public abstract class MsSqlSequence : ISequence { private static readonly ILogger Logger = LogManager.Create(); - public void EnsureSequence(DbContext dbContext) + public void EnsureSequence(IDbConnection dbConnection) { Logger.Info($"Ensuring existence of mssql sequence {SequenceName}"); - using (var dbConnection = dbContext.Database.GetDbConnection()) + if (dbConnection.State == ConnectionState.Closed) { dbConnection.Open(); + } - bool sequenceExists; - using (var cmd = dbConnection.CreateCommand()) - { - cmd.CommandText = $"SELECT count(*) FROM sys.sequences WHERE name = '{SequenceName}'"; - sequenceExists = (int)cmd.ExecuteScalar() == 1; - } + bool sequenceExists; + using (IDbCommand cmd = dbConnection.CreateCommand()) + { + cmd.CommandText = $"SELECT count(*) FROM sys.sequences WHERE name = '{SequenceName}'"; + sequenceExists = (int)cmd.ExecuteScalar() == 1; + } - if (sequenceExists) - { - Logger.Info($"Sequence {SequenceName} exists"); - } - else + if (sequenceExists) + { + Logger.Info($"Sequence {SequenceName} exists"); + } + else + { + Logger.Info($"Sequence {SequenceName} does not exist yet and will be created now"); + using (var cmd = dbConnection.CreateCommand()) { - Logger.Info($"Sequence {SequenceName} does not exist yet and will be created now"); - using (var cmd = dbConnection.CreateCommand()) - { - cmd.CommandText = $"CREATE SEQUENCE {SequenceName} START WITH 1 INCREMENT BY {Increment}"; - cmd.ExecuteNonQuery(); - Logger.Info($"Sequence {SequenceName} created"); - } + cmd.CommandText = $"CREATE SEQUENCE {SequenceName} START WITH 1 INCREMENT BY {Increment}"; + cmd.ExecuteNonQuery(); + Logger.Info($"Sequence {SequenceName} created"); } - } } - public int GetNextValue(DbContext dbContext) + public int GetNextValue(IDbConnection dbConnection) { - using (DbConnection dbConnection = dbContext.Database.GetDbConnection()) + if (dbConnection.State == ConnectionState.Closed) { dbConnection.Open(); - int nextValue; - using (DbCommand selectNextValCommand = dbConnection.CreateCommand()) - { - selectNextValCommand.CommandText = $"SELECT next value FOR {SequenceName}"; - nextValue = Convert.ToInt32(selectNextValCommand.ExecuteScalar()); - Logger.Debug($"{SequenceName} served {nextValue} as next value"); - } - return nextValue; } + int nextValue; + using (IDbCommand selectNextValCommand = dbConnection.CreateCommand()) + { + selectNextValCommand.CommandText = $"SELECT next value FOR {SequenceName}"; + nextValue = Convert.ToInt32(selectNextValCommand.ExecuteScalar()); + Logger.Debug($"{SequenceName} served {nextValue} as next value"); + } + return nextValue; } public abstract int Increment { get; } diff --git a/src/implementations/Backend.Fx.EfCorePersistence/Oracle/OracleSequence.cs b/src/implementations/Backend.Fx.EfCorePersistence/Oracle/OracleSequence.cs index 1ad642af..37d9d19e 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/Oracle/OracleSequence.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/Oracle/OracleSequence.cs @@ -1,60 +1,76 @@ namespace Backend.Fx.EfCorePersistence.Oracle { using System; - using System.Data.Common; + using System.Data; using Logging; - using Microsoft.EntityFrameworkCore; public abstract class OracleSequence : ISequence { private static readonly ILogger Logger = LogManager.Create(); - - public void EnsureSequence(DbContext dbContext) + + public void EnsureSequence(IDbConnection dbConnection) { - Logger.Info($"Ensuring existence of oracle sequence {SequenceName}"); - using (DbConnection dbConnection = dbContext.Database.GetDbConnection()) + Logger.Info($"Ensuring existence of oracle sequence {SchemaPrefix}{SequenceName}"); + + if (dbConnection.State == ConnectionState.Closed) { dbConnection.Open(); - bool sequenceExists; - using (DbCommand command = dbConnection.CreateCommand()) - { - command.CommandText = $"SELECT count(*) FROM user_sequences WHERE sequence_name = '{SequenceName}'"; - sequenceExists = (decimal)command.ExecuteScalar() == 1; - } - if (sequenceExists) - { - Logger.Info($"Sequence {SequenceName} exists"); - } - else + } + + bool sequenceExists; + using (IDbCommand command = dbConnection.CreateCommand()) + { + command.CommandText = $"SELECT count(*) FROM user_sequences WHERE sequence_name = '{SequenceName}'"; + sequenceExists = (decimal)command.ExecuteScalar() == 1; + } + if (sequenceExists) + { + Logger.Info($"Sequence {SchemaPrefix}{SequenceName} exists"); + } + else + { + Logger.Info($"Sequence {SchemaPrefix}{SequenceName} does not exist yet and will be created now"); + using (var cmd = dbConnection.CreateCommand()) { - Logger.Info($"Sequence {SequenceName} does not exist yet and will be created now"); - using (var cmd = dbConnection.CreateCommand()) - { - cmd.CommandText = $"CREATE SEQUENCE {SequenceName} START WITH 1 INCREMENT BY {Increment}"; - cmd.ExecuteNonQuery(); - Logger.Info($"Sequence {SequenceName} created"); - } + cmd.CommandText = $"CREATE SEQUENCE {SchemaPrefix}{SequenceName} START WITH 1 INCREMENT BY {Increment}"; + cmd.ExecuteNonQuery(); + Logger.Info($"Sequence {SchemaPrefix}{SequenceName} created"); } } } - public int GetNextValue(DbContext dbContext) + public int GetNextValue(IDbConnection dbConnection) { - using (DbConnection dbConnection = dbContext.Database.GetDbConnection()) + if (dbConnection.State == ConnectionState.Closed) { dbConnection.Open(); - int nextValue; - using (DbCommand command = dbConnection.CreateCommand()) - { - command.CommandText = $"SELECT {SequenceName}.NEXTVAL FROM dual"; - nextValue = Convert.ToInt32(command.ExecuteScalar()); - Logger.Debug($"{SequenceName} served {nextValue} as next value"); - } - return nextValue; } + + int nextValue; + using (IDbCommand command = dbConnection.CreateCommand()) + { + command.CommandText = $"SELECT {SchemaPrefix}{SequenceName}.NEXTVAL FROM dual"; + nextValue = Convert.ToInt32(command.ExecuteScalar()); + Logger.Debug($"{SchemaPrefix}{SequenceName} served {nextValue} as next value"); + } + return nextValue; } public abstract int Increment { get; } protected abstract string SequenceName { get; } + protected abstract string SchemaName { get; } + + private string SchemaPrefix + { + get + { + if (string.IsNullOrEmpty(SchemaName)) + { + return string.Empty; + } + + return SchemaName + "."; + } + } } } diff --git a/src/implementations/Backend.Fx.EfCorePersistence/Postgres/PostgresSequence.cs b/src/implementations/Backend.Fx.EfCorePersistence/Postgres/PostgresSequence.cs index b6426bb4..da2f617a 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/Postgres/PostgresSequence.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/Postgres/PostgresSequence.cs @@ -1,57 +1,57 @@ namespace Backend.Fx.EfCorePersistence.Postgres { using System; - using System.Data.Common; + using System.Data; using Logging; - using Microsoft.EntityFrameworkCore; - + public abstract class PostgresSequence : ISequence { private static readonly ILogger Logger = LogManager.Create(); - - public void EnsureSequence(DbContext dbContext) + + public void EnsureSequence(IDbConnection dbConnection) { Logger.Info($"Ensuring existence of postgres sequence {SequenceName}"); - using (DbConnection dbConnection = dbContext.Database.GetDbConnection()) + + if (dbConnection.State == ConnectionState.Closed) { dbConnection.Open(); - bool sequenceExists; - using (DbCommand command = dbConnection.CreateCommand()) - { - command.CommandText = $"SELECT count(*) FROM information_schema.sequences WHERE sequence_name = '{SequenceName}'"; - sequenceExists = (long)command.ExecuteScalar() == 1L; - } - if (sequenceExists) - { - Logger.Info($"Sequence {SequenceName} exists"); - } - else + } + bool sequenceExists; + using (IDbCommand command = dbConnection.CreateCommand()) + { + command.CommandText = $"SELECT count(*) FROM information_schema.sequences WHERE sequence_name = '{SequenceName}'"; + sequenceExists = (long)command.ExecuteScalar() == 1L; + } + if (sequenceExists) + { + Logger.Info($"Sequence {SequenceName} exists"); + } + else + { + Logger.Info($"Sequence {SequenceName} does not exist yet and will be created now"); + using (var cmd = dbConnection.CreateCommand()) { - Logger.Info($"Sequence {SequenceName} does not exist yet and will be created now"); - using (var cmd = dbConnection.CreateCommand()) - { - cmd.CommandText = $"CREATE SEQUENCE {SequenceName} START WITH 1 INCREMENT BY {Increment}"; - cmd.ExecuteNonQuery(); - Logger.Info($"Sequence {SequenceName} created"); - } + cmd.CommandText = $"CREATE SEQUENCE {SequenceName} START WITH 1 INCREMENT BY {Increment}"; + cmd.ExecuteNonQuery(); + Logger.Info($"Sequence {SequenceName} created"); } } } - public int GetNextValue(DbContext dbContext) + public int GetNextValue(IDbConnection dbConnection) { - using (DbConnection dbConnection = dbContext.Database.GetDbConnection()) + if (dbConnection.State == ConnectionState.Closed) { dbConnection.Open(); - int nextValue; - using (DbCommand command = dbConnection.CreateCommand()) - { - command.CommandText = $"SELECT nextval('{SequenceName}');"; - nextValue = Convert.ToInt32(command.ExecuteScalar()); - Logger.Debug($"{SequenceName} served {nextValue} as next value"); - } - return nextValue; } + int nextValue; + using (IDbCommand command = dbConnection.CreateCommand()) + { + command.CommandText = $"SELECT nextval('{SequenceName}');"; + nextValue = Convert.ToInt32(command.ExecuteScalar()); + Logger.Debug($"{SequenceName} served {nextValue} as next value"); + } + return nextValue; } public abstract int Increment { get; } diff --git a/src/implementations/Backend.Fx.EfCorePersistence/SequenceHiLoIdGenerator.cs b/src/implementations/Backend.Fx.EfCorePersistence/SequenceHiLoIdGenerator.cs index 28858910..dc951ae9 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/SequenceHiLoIdGenerator.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/SequenceHiLoIdGenerator.cs @@ -20,7 +20,7 @@ protected override int GetNextBlockStart() { using (var dbContext = _dbContextFactory()) { - return _sequence.GetNextValue(dbContext); + return _sequence.GetNextValue(dbContext.Database.GetDbConnection()); } } From 921e0014aad35d9bd748fac142d44546d2a4b919 Mon Sep 17 00:00:00 2001 From: Marc Wittke Date: Tue, 22 Jan 2019 10:30:55 -0300 Subject: [PATCH 3/3] Sequences do not depend on EF any more --- .../Patterns/IdGeneration/HiLoIdGenerator.cs | 4 ++-- .../SequenceHiLoIdGenerator.cs | 23 ++++++++----------- .../IdGeneration/TheHiLoIdGenerator.cs | 6 ++--- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/abstractions/Backend.Fx/Patterns/IdGeneration/HiLoIdGenerator.cs b/src/abstractions/Backend.Fx/Patterns/IdGeneration/HiLoIdGenerator.cs index 892525c2..37cd55a8 100644 --- a/src/abstractions/Backend.Fx/Patterns/IdGeneration/HiLoIdGenerator.cs +++ b/src/abstractions/Backend.Fx/Patterns/IdGeneration/HiLoIdGenerator.cs @@ -34,12 +34,12 @@ private void EnsureValidLowAndHiId() { // first fetch from sequence in life time _lowId = GetNextBlockStart(); - _highId = _lowId + Increment- 1; + _highId = _lowId + BlockSize- 1; } } protected abstract int GetNextBlockStart(); - protected abstract int Increment { get; } + protected abstract int BlockSize { get; } } } \ No newline at end of file diff --git a/src/implementations/Backend.Fx.EfCorePersistence/SequenceHiLoIdGenerator.cs b/src/implementations/Backend.Fx.EfCorePersistence/SequenceHiLoIdGenerator.cs index dc951ae9..59e99378 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/SequenceHiLoIdGenerator.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/SequenceHiLoIdGenerator.cs @@ -1,29 +1,24 @@ -using System; - -namespace Backend.Fx.EfCorePersistence +namespace Backend.Fx.EfCorePersistence { - using Microsoft.EntityFrameworkCore; + using System.Data; using Patterns.IdGeneration; - public abstract class SequenceHiLoIdGenerator : HiLoIdGenerator, IEntityIdGenerator where TDbContext : DbContext + public abstract class SequenceHiLoIdGenerator : HiLoIdGenerator, IEntityIdGenerator { private readonly ISequence _sequence; - private readonly Func _dbContextFactory; - - protected SequenceHiLoIdGenerator(ISequence sequence, Func dbContextFactory) + private readonly IDbConnection _dbConnection; + + protected SequenceHiLoIdGenerator(ISequence sequence, IDbConnection dbConnection) { _sequence = sequence; - _dbContextFactory = dbContextFactory; + _dbConnection = dbConnection; } protected override int GetNextBlockStart() { - using (var dbContext = _dbContextFactory()) - { - return _sequence.GetNextValue(dbContext.Database.GetDbConnection()); - } + return _sequence.GetNextValue(_dbConnection); } - protected override int Increment => _sequence.Increment; + protected override int BlockSize => _sequence.Increment; } } \ No newline at end of file diff --git a/tests/Backend.Fx.Tests/Patterns/IdGeneration/TheHiLoIdGenerator.cs b/tests/Backend.Fx.Tests/Patterns/IdGeneration/TheHiLoIdGenerator.cs index 90609090..c5500bb5 100644 --- a/tests/Backend.Fx.Tests/Patterns/IdGeneration/TheHiLoIdGenerator.cs +++ b/tests/Backend.Fx.Tests/Patterns/IdGeneration/TheHiLoIdGenerator.cs @@ -61,7 +61,7 @@ public class InMemoryHiLoIdGenerator : HiLoIdGenerator public InMemoryHiLoIdGenerator(int start, int increment) { _nextBlockStart = start; - Increment = increment; + BlockSize = increment; } protected override int GetNextBlockStart() @@ -70,11 +70,11 @@ protected override int GetNextBlockStart() { // this simulates the behavior of a SQL sequence for example int result = _nextBlockStart; - _nextBlockStart += Increment; + _nextBlockStart += BlockSize; return result; } } - protected override int Increment { get; } + protected override int BlockSize { get; } } }