Skip to content

Commit

Permalink
Merge pull request #54 from marcwittke/feature/forelab
Browse files Browse the repository at this point in the history
Improvements for Oracle Sequences and Id Generation
  • Loading branch information
marcwittke committed Jan 22, 2019
2 parents 7af4518 + 921e001 commit 038a134
Show file tree
Hide file tree
Showing 15 changed files with 168 additions and 156 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
}
}
21 changes: 10 additions & 11 deletions src/implementations/Backend.Fx.EfCorePersistence/DatabaseManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,20 @@

public abstract class DatabaseManager<TDbContext> : IDatabaseManager where TDbContext : DbContext
{
private readonly Func<TDbContext> _dbContextFactory;
private static readonly ILogger Logger = LogManager.Create<DatabaseManager<TDbContext>>();

protected DatabaseManager(DbContextOptions<TDbContext> dbContextOptions)
protected DatabaseManager(Func<TDbContext> dbContextFactory)
{
DbContextOptions = dbContextOptions;
_dbContextFactory = dbContextFactory;
}

public bool DatabaseExists { get; protected set; }

public DbContextOptions<TDbContext> DbContextOptions { get; }

public void EnsureDatabaseExistence()
{
Logger.Info("Ensuring database existence");
using (var dbContext = DbContextOptions.CreateDbContext())
using (var dbContext = _dbContextFactory())
{
ExecuteCreationStrategy(dbContext);
}
Expand All @@ -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)
{
Expand All @@ -64,12 +63,12 @@ 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)
{
ISequence sequence = (ISequence)Activator.CreateInstance(sequenceType.AsType());
sequence.EnsureSequence(dbContext);
sequence.EnsureSequence(dbContext.Database.GetDbConnection());
}
}

Expand All @@ -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();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
namespace Backend.Fx.EfCorePersistence
{
using System;
using Logging;
using Microsoft.EntityFrameworkCore;

public class DatabaseManagerWithMigration<TDbContext> : DatabaseManager<TDbContext> where TDbContext : DbContext
{
private static readonly ILogger Logger = LogManager.Create<DatabaseManagerWithMigration<TDbContext>>();

public DatabaseManagerWithMigration(DbContextOptions<TDbContext> dbContextOptions) : base(dbContextOptions)
public DatabaseManagerWithMigration(Func<TDbContext> dbContextFactory) : base(dbContextFactory)
{ }

protected override void ExecuteCreationStrategy(DbContext dbContext)
{
Logger.Info("Migrating database to latest schema version");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
namespace Backend.Fx.EfCorePersistence
{
using System;
using Logging;
using Microsoft.EntityFrameworkCore;

public class DatabaseManagerWithoutMigration<TDbContext> : DatabaseManager<TDbContext> where TDbContext : DbContext
{
private static readonly ILogger Logger = LogManager.Create<DatabaseManagerWithoutMigration<TDbContext>>();

public DatabaseManagerWithoutMigration(DbContextOptions<TDbContext> options) : base(options)
public DatabaseManagerWithoutMigration(Func<TDbContext> dbContextFactory) : base(dbContextFactory)
{ }

protected override void ExecuteCreationStrategy(DbContext dbContext)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,7 @@ public static void TraceChangeTrackerState(this DbContext dbContext)
}
}
}

public static TDbContext CreateDbContext<TDbContext>(this DbContextOptions<TDbContext> 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) ?? "?";
Expand Down
10 changes: 5 additions & 5 deletions src/implementations/Backend.Fx.EfCorePersistence/ISequence.cs
Original file line number Diff line number Diff line change
@@ -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; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ public class MsSqlFullTextSearchService<TAggregateRoot> : IFullTextSearchService

public IQueryable<TAggregateRoot> Search(string searchQuery)
{
// mitigate SQL injection
searchQuery = searchQuery.Replace("\'", "");

string ftsQuery = _easyFts.ToFtsQuery(searchQuery);

IQueryable<TAggregateRoot> queryable;
Expand Down
Original file line number Diff line number Diff line change
@@ -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<MsSqlSequence>();

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; }
Expand Down
Original file line number Diff line number Diff line change
@@ -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<OracleSequence>();
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 + ".";
}
}
}
}

0 comments on commit 038a134

Please sign in to comment.