I have my application layered with Class Library
and my layer with Entity Framework
, where I set DbContext
, it's Repository
.
My class inherited from DbContext:
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 ...
}
Notice that the first line of the constructor is for auto-database migration using 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 left out in another context?
And I also created the UniqueKeyAttribute
class 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 this attribute to be translated into the database I've added the following class, which unfortunately can not 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 the control with Migrations
I do not know when I can set the Database.SetInitializer<Repository.Context>(new Repository.DatabaseAdditionalConfigurations<Repository.Context>());
setting so that the CreateUniqueKeys
method can create the unique keys in the database. How could I treat this? Would it be in method Seed
of class Configuration
of Migrations
?
Another issue is that my base was automatically created only when% of the builder of the Migrations Configuration class was set to AutomaticMigrationsEnabled = true;
. Do you need this, or am I doing something wrong? Is going this route a good practice?
Remembering here the ideal place question for: true
.