7
I have my application divided into layers with Class Library
and my layer with the Entity Framework
, where I set up the DbContext
, is the Repository
.
My inherited Dbcontext class:
public class Context : DbContext
{
private static string connectionString = "Data Source=(local); Initial Catalog=CRM; Integrated Security=True;";
public Context() : base(connectionString)
{
// Set the auto versioning
Database.SetInitializer(new MigrateDatabaseToLatestVersion<Context, Migrations.Configuration>());
// Gets or sets the database initialization strategy.
Database.SetInitializer<Context>(new Repository.DatabaseAdditionalConfigurations<Context>());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Pluralizing
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
// Non delete cascade
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
// Configure Pessoa
modelBuilder.Configurations.Add<Domain.Pessoa>(new Domain.PessoaTypeConfiguration());
base.OnModelCreating(modelBuilder);
}
#region DbSet´s ...
}
Note that the first line of the constructor is for auto database migration using the Migrations
: Database.SetInitializer(new MigrateDatabaseToLatestVersion<Context, Migrations.Configuration>());
.
Is this a good time in the class life cycle for this line to be? Or should it be out in another context?
And I also created the class UniqueKeyAttribute
to configure the fields that are unique
in my database:
using System;
namespace Domain.Attributes
{
///<summary>
///A unique attribute
///</summary>
public class UniqueKeyAttribute : Attribute { }
}
And for that attribute to be translated into the database I added the following class, which unfortunately I can’t remember the source:
public class DatabaseAdditionalConfigurations<T> : IDatabaseInitializer<T> where T : DbContext
{
public void InitializeDatabase(T context)
{
var created = false;
if (context.Database.Exists())
created = true;
else
context.Database.CreateIfNotExists();
if (!created)
CreateUniqueKeys(context);
}
public void CreateUniqueKeys(T context)
{
//Fetch all the father class's public properties
var masterProperties = typeof(DbContext).GetProperties().Select(x => x.Name).ToList();
//Percorre cada DBSet<> do DbContext
foreach (var item in typeof(T).GetProperties().Where(p => masterProperties.IndexOf(p.Name) < 0).Select(x => x))
{
//busca o tipo de "T"
Type entityType = item.PropertyType.GetGenericArguments()[0];
// Cria as chaves únicas
var fields = from f in entityType.GetProperties()
where f.GetCustomAttributes(typeof(Domain.Attributes.UniqueKeyAttribute), true).Count() > 0
select f.Name;
var uniqueKeys = "";
foreach (string s in fields)
{
if (string.IsNullOrEmpty(uniqueKeys) || string.IsNullOrWhiteSpace(uniqueKeys))
uniqueKeys = s;
else
uniqueKeys += ", " + s;
}
if (!string.IsNullOrEmpty(uniqueKeys) && !string.IsNullOrWhiteSpace(uniqueKeys))
context.Database.ExecuteSqlCommand("alter table " + entityType.Name + " add unique(" + uniqueKeys + ")");
}
}
}
Well, first I have a problem. Now that I’ve added control with Migrations
i don’t know at what point I can put the setting Database.SetInitializer<Repository.Context>(new Repository.DatabaseAdditionalConfigurations<Repository.Context>());
so that the method CreateUniqueKeys
can create unique keys in the bank. How could I treat this? It would be in the method Seed
class Configuration
of Migrations
?
Another issue is that my database was created automatically only when AutomaticMigrationsEnabled = true;
Migrations Configuration class constructor was set to true
. Do you really need this, or am I doing something wrong? Going down this path is good practice?
Remembering here about the question of the ideal location for: Database.SetInitializer(new MigrateDatabaseToLatestVersion<Context, Migrations.Configuration>());
.