开发者

Extracting the configuration created by DbContext.OnModelCreating in IDatabaseInitializer

开发者 https://www.devze.com 2023-03-07 07:44 出处:网络
Can one access the configuration created during an implementation of DbContext.OnModelCreating in an implementation of IDatabaseInitializer.InitializeDatabase?Given an instance of DbContext, I am unab

Can one access the configuration created during an implementation of DbContext.OnModelCreating in an implementation of IDatabaseInitializer.InitializeDatabase? Given an instance of DbContext, I am unable to see how to get to that configuration.

Background:

I chose to implement a system using the code first capability of Entity Framework 4.1 as it allows me to support multiple database engines, such as SQL Server and MySQL. Like most applications, I need to ensure that some entities have properties that are unique.

I have no problem coding the additional sql statements to generate the unique constraints as suggested here and here. However, my model is growing rather large and writing the SQL statements by hand is error prone because it makes several assumptions about the underlying physical database schema in terms of TPH, TPC, table names and column names. In some scenarios, like TPH, it may not even be possible to add unique constraints and one has to use another database specific method, like unique indexes.

I have started writing the following. The idea is to walk the configuration, find the properties with the unique constraints and call a provider specific method to add the unique constraint.

public class UniqueAttribute : Attribute
{
    readonly List<string> _names = new List<string>();

    public UniqueAttribute(params string[] names)
    {
        _names.AddRange(names);
    }

    public IEnumerable<string> PropertyNames
    {
        get
        {
            return _names;
        }
    }
}

public class Party
{
    /* some properties, like id */
    public virtual ICollection<Address> Addresses { get; set; }
}

public class Person : Party
{
    /* some properties unique to a person*/
    [Unique]
    public string UserName { get; set; }
}

public class Address
{
    /* properties for addresses */
}

public class SampleDatabaseContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Party>();
        modelBuilder.Entity<Person>();
        modelBuilder.Entity<Address>();
    }
}

public abstract class SampleDatabaseInitializer : IDatabaseInitializer<SampleDatabaseContext>
{
    public void InitializeDatabase(SampleDatabaseContext context)
    {
        /* code to create the database if it doesn't exist */

        // TODO: Walk through the context configuration and find "unique" columns
        // TODO: For each unique column, call AddUniqueConstraint
    }

    public abstract void AddUniqueConstraint(SampleDatabaseContext context, params string[] names);
}

class MySqlSampleDatabaseInitializer : SampleDatabaseInitializer
{
    public override void AddUniqueConstraint(SampleDatabaseContext context, params string[] names)
    {
        /* MySQL specific code to add unique constraints */
    }
}

class SqlSampleDatabaseInitializer : SampleDatabaseInitializer
{
    public override void AddUniqueConstraint(SampleDatabaseContext context, params string[] names)
    {
        /* Sql Server specific code to add unique constraints */
  开发者_运维技巧  }
}

class OracleSampleDatabaseInitializer : SampleDatabaseInitializer
{
    public override void AddUniqueConstraint(SampleDatabaseContext context, params string[] names)
    {
        /* Oracle specific code to add unique constraints */
    }
}

Much appreciated.


Configuration is not accessible from the context. Once you get context instance configuration is already compiled and you cannot access its "classes" or attributes. Compiled model is just set of metadata used to define the mapping. These metadata doesn't contain your additional information about unique properties.

You must use reflection for this scenario. Simply load all types from assembly with your entities and look for properties marked with Unique attribute.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号