Skip to content

Commit

Permalink
Automated DBCTools.CreateDatabase
Browse files Browse the repository at this point in the history
This now will scan DBC folder and create all the tables and upload all
the data. No longer manual.
  • Loading branch information
HelloKitty committed Jun 19, 2018
1 parent 244df22 commit 5a311ef
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 43 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"DatabaseConnectionString": "Server=localhost;Database=client.dbc;Uid=root;Pwd=test;",
"LoggingEnabled": "True",
"LoggingLevel": "Debug"
"LoggingLevel": "Information"
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ public Task<int> InsertEntriesAsync(IReadOnlyCollection<TDBCEntryType> entries)
{
if(entries == null) throw new ArgumentNullException(nameof(entries));

if(Logger.IsEnabled(LogLevel.Debug))
Logger.LogDebug($"Adding: {entries.Count} Type: {typeof(TDBCEntryType).Name}");
if(Logger.IsEnabled(LogLevel.Information))
Logger.LogInformation($"Adding: {entries.Count} Type: {typeof(TDBCEntryType).Name}");

//TODO: Is this the best way to insert?
Context.Set<TDBCEntryType>().AddRange(entries);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.2" />
<PackageReference Include="fasterflect" Version="2.1.3" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.1.0" />
<PackageReference Include="Serilog.Extensions.Logging.File" Version="1.1.0" />
</ItemGroup>

<ItemGroup>
Expand Down
120 changes: 81 additions & 39 deletions src/FreecraftCore.DBC.CreateDatabase/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,7 @@ public static IServiceProvider BuildServiceContainerForDbcType(string dbcType)
.AsImplementedInterfaces();

RegisterDatabaseServices(serviceCollection);

//We can scan for the DBC model type knowing the file name.
Type dbcModelType = typeof(DBCHeader)
.Assembly
.GetExportedTypes()
.First(t => t.GetCustomAttribute<TableAttribute>()?.Name == dbcType);
Type dbcModelType = ComputeDBCType(dbcType);

//TODO: Generic handling
//We have to do special handling for generic models
Expand Down Expand Up @@ -85,14 +80,30 @@ public static IServiceProvider BuildServiceContainerForDbcType(string dbcType)
.As<IReadOnlyDictionary<uint, string>>();

//TODO: Make logging optional
RegisterLoggingServices(builder);
RegisterLoggingServices(serviceCollection);

//This takes the ASP/Core service collection and pushes it all into AutoFac.
builder.Populate(serviceCollection);

return new AutofacServiceProvider(builder.Build());
}

private static Type ComputeDBCType([NotNull] string dbcType)
{
if(string.IsNullOrEmpty(dbcType)) throw new ArgumentException("Value cannot be null or empty.", nameof(dbcType));

//We can scan for the DBC model type knowing the file name.
return typeof(DBCHeader)
.Assembly
.GetExportedTypes()
.FirstOrDefault(t => t.GetCustomAttribute<TableAttribute>()?.Name == dbcType);
}

private static bool IsDbcTypeImplemented(string dbcType)
{
return ComputeDBCType(dbcType) != null;
}

/// <summary>
/// Similar to <see cref="RegisterNonGenericDbcModelServices"/> but handles the cases
/// where a TStringType generic type arg may need to be handled and dealt with.
Expand Down Expand Up @@ -176,18 +187,22 @@ private static void RegisterEntryInserter([NotNull] ContainerBuilder builder, [N
}

//TODO: make this more configurable
private static ContainerBuilder RegisterLoggingServices(ContainerBuilder builder)
private static IServiceCollection RegisterLoggingServices(IServiceCollection serviceCollection)
{
//ILoggerFactory loggerFactory = new LoggerFactory()
// .AddFile($"{"Logs/Dump-{Date}"}-{Guid.NewGuid()}.txt", LogLevel.Trace);

ILoggerFactory loggerFactory = new LoggerFactory()
.AddConsole(LogLevel.Debug);
serviceCollection.AddLogging(loggingBuilder =>
{
//TODO: Is the correct way to set level?
loggingBuilder.SetMinimumLevel(Config.LoggingLevel);
builder.RegisterInstance(loggerFactory)
.As<ILoggerFactory>();
//This gets rid of the query spam.
loggingBuilder.AddFilter("Microsoft", LogLevel.Warning);
loggingBuilder.AddConsole();
});

return builder;
return serviceCollection;
}

private static IServiceCollection RegisterDatabaseServices(IServiceCollection serviceCollection)
Expand Down Expand Up @@ -219,36 +234,53 @@ static async Task Main(string[] args)
Config = BuildConfigFile();

//TODO: This is just test code, we want to handle inputs better.
Console.Write($"Enter DBC Type (without extension; Ex. \"Item\"): ");
string dbcType = Console.ReadLine();
IServiceProvider provider = BuildServiceContainerForDbcType(dbcType);
Console.WriteLine($"Will create tables and database if they do not exist.");

Stopwatch watch = new Stopwatch();
watch.Start();
using(var scope = provider.CreateScope())
{
try
{
//TODO: We shouldn't check everytime we create a DBC table. Do this elsewhere
await CreateDatabaseIfNotCreated(scope.ServiceProvider.GetService<DbContext>());
//TODO: We shouldn't check everytime we create a DBC table. Do this elsewhere
await CreateDatabaseIfNotCreated();

//This may look silly but we want to support the 50+ DBC types so
//it needs to be handle magically otherwise we'd have to write code for each one.
ITableFillable tableFiller = scope.ServiceProvider.GetService<ITableFillable>();
foreach(string dbcFile in Directory.GetFiles("DBC").Select(Path.GetFileNameWithoutExtension))
{
//We should check if we know a DBC file of this type.
IServiceProvider provider = BuildServiceContainerForDbcType(dbcFile);

await tableFiller.FillAsync();
}
catch(Exception e)
Stopwatch watch = new Stopwatch();
watch.Start();
using(var scope = provider.CreateScope())
{
Console.WriteLine(e);
throw;
ILogger<Program> logger = scope.ServiceProvider.GetService<ILogger<Program>>();

try
{
if(!IsDbcTypeImplemented(dbcFile))
{
if(logger.IsEnabled(LogLevel.Warning))
logger.LogWarning($"Encountered unknown DBC Type: {dbcFile}. Will skip.");

continue;
}

if(logger.IsEnabled(LogLevel.Information))
logger.LogInformation($"Populating table for DBC: {dbcFile}");

//This may look silly but we want to support the 50+ DBC types so
//it needs to be handle magically otherwise we'd have to write code for each one.
ITableFillable tableFiller = scope.ServiceProvider.GetService<ITableFillable>();

await tableFiller.FillAsync();
}
catch(Exception e)
{
Console.WriteLine(e);
throw;
}
}
}

watch.Stop();
Console.WriteLine($"Created Table In Milliseconds: {watch.ElapsedMilliseconds}");
watch.Stop();
Console.WriteLine($"Created Table: {dbcFile} In Milliseconds: {watch.ElapsedMilliseconds}");
}

Console.WriteLine("Press any key!");
Console.WriteLine("Finished. Press any key!");
Console.ReadKey();
}

Expand All @@ -270,10 +302,20 @@ private static ApplicationConfiguration BuildConfigFile()
return JsonConvert.DeserializeObject<ApplicationConfiguration>(configData);
}

private static async Task CreateDatabaseIfNotCreated(DbContext context)
private static async Task CreateDatabaseIfNotCreated()
{
await context.Database.MigrateAsync();
await context.Database.EnsureCreatedAsync();
ContainerBuilder builder = new ContainerBuilder();
ServiceCollection serviceCollection = new ServiceCollection();

RegisterDatabaseServices(serviceCollection);
builder.Populate(serviceCollection);

using(IServiceScope scope = new AutofacServiceProvider(builder.Build()).CreateScope())
using(DbContext context = scope.ServiceProvider.GetService<DbContext>())
{
await context.Database.MigrateAsync();
await context.Database.EnsureCreatedAsync();
}
}
}
}

0 comments on commit 5a311ef

Please sign in to comment.