如何使用给定的约定配置实体框架?

时间:2013-03-04 18:43:27

标签: c# entity-framework entity-framework-4 entity-framework-4.1

我有一个MVC4项目,其中已经创建了DB(Sql2008)和模型(C#),因此无法更改它们的名称。我开始使用EF4.1为我正在使用的每个类使用自定义配置,因此在模型创建时,所有内容都会映射到数据库。大多数所有表都具有名称“tbl_X_”+ entityName,主键为entityName +“ ID”。其他人有“tbl ”+ entityName和其他主键。为避免重复代码,我创建了一个自定义的EntityTypeConfiguration:

    public abstract class BaseConfiguration<T> : EntityTypeConfiguration<T>
        where T: class
    {
        public BaseConfiguration()
        {
            Map(x => x.ToTable("tbl_X_" + typeof(T).Name));

            var parm = Expression.Parameter(typeof(T), typeof(T).Name);
            var propExpression = Expression.Lambda<Func<T, int>>
                (Expression.Convert(Expression.Property(parm, "Id"), typeof(int)), parm);
            Property(propExpression).HasColumnName(typeof(T).Name + "_ID");
        }
    }

这适用于大多数情况,除非表名不符合该约定,并且我使用给定名称映射表:

    public class CompanyConfiguration : BaseConfiguration<Company>
    {
        public CompanyConfiguration()
        {
            Map(x => x.ToTable("tbl_Company"));
            //Key does follow convention
        }
    }

当我构建时,我收到错误

  

“类型'公司'的属性只能映射一次。”

我绝对意识到这是因为我映射了两次,一个在基础上,另一个在派生类上。如果tableName和primaryKeyName都有第二个映射,是否可以覆盖第一个,我想知道。

提前致谢!

编辑:有些实体需要歧视。

Map(x => x.Requires("discriminatorColumn")
                            .HasValue(value)
                            .HasColumnType("dataType")
                            .IsRequired())
                            .ToTable("tbl_TableName");

2 个答案:

答案 0 :(得分:0)

BaseConfiguration上的构造函数总是在CompanyConfiguration的构造函数之前运行,因此在运行CompanyConfiguration的代码块之前总是会执行map操作。我不知道无论如何覆盖地图调用以允许它第二次被调用。但是,解决这个问题的一个选择可能是让一些重载的构造函数解决这个问题。

像孩子一样的东西:

public class CompanyConfiguration : BaseConfiguration<Company>
{
    private readonly string customTableMap = "tbl_Company"; 

    public CompanyConfiguration() : base(customTableMap) { }
}

和父母:

public abstract class BaseConfiguration<T> : EntityTypeConfiguration<T>
    where T: class
{
    private readonly string defaultTableMap = "tbl_X_" + typeof(T).Name;

    public BaseConfiguration(): this(defaultTableMap) { }

    public BaseConfiguration(string tableMap)
    {
        Map(x => x.ToTable(tableMap));

        var parm = Expression.Parameter(typeof(T), typeof(T).Name);
        var propExpression = Expression.Lambda<Func<T, int>>
            (Expression.Convert(Expression.Property(parm, "Id"), typeof(int)), parm);
        Property(propExpression).HasColumnName(typeof(T).Name + "_ID");
    }
}

答案 1 :(得分:0)

赞赏答案,但尚未满足所有要求。这是我到目前为止所获得的解决方案:

我将所有table和primaryKey映射移动到BaseConfiguration类:

public class BaseConfiguration<T> : EntityTypeConfiguration<T>
    where T : class
{
    public BaseConfiguration()
    {
        TableNameConvention();
        PrimaryKeyConvention();
    }

    private void TableNameConvention()
    {
        switch (typeof(T).Name)
        {
            case "entityA":
                ToTable("vw_entityA");
                break;
            case "entityB":
                ToTable("tbl_entityB");
                break;
            case "entityC":
                Map(x => x.Requires("discriminatorColumn")
                        .HasValue(value)
                        .HasColumnType("dataType")
                        .IsRequired())
                        .ToTable("tblentityC");
                break;

            default:
                ToTable("tbl_X_" + typeof(T).Name);
                break;
        }
    }

    private void PrimaryKeyConvention()
    {
        var type = typeof(T);
        var parm = Expression.Parameter(type, type.Name);
        var propExpression = Expression.Lambda<Func<T, int>>
                (Expression.Convert(Expression.Property(parm, "Id"), typeof(int)), parm);

        switch (type.Name)
        {
            case "entityB":
                Property(propExpression).HasColumnName("IdEntityB");
                break;
            default:

                Property(propExpression).HasColumnName(type.Name + "_ID");

                break;
        }

    }



}

然后在我的自定义配置类中,我只映射其他列,外键,关系。 e.g:

    public class EntityXConfiguration : BaseConfiguration<EntityX>
    {
        public EntityXConfiguration ()
        {
            ////Not needed here anymore. Moved to baseconfiguration
            //Property(x => x.Id).HasColumnName("EntityX_ID");
            //ToTable("tbl_X_EntityX");
            ////


            Property(x => x.ParentId).HasColumnName("EntityXParent_ID");
            Property(x => x.Name).HasColumnName("EntityXName");


            Ignore(x => x.EntityXProperty);

            ////Other mappings...
        }
    }

随意添加您的评论!

谢谢!