0

我有一个 MVC4 项目,其中已经创建了 DB (Sql2008) 和 Models (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");
4

2 回答 2

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");
    }
}
于 2013-03-06T10:34:34.040 回答
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;
        }

    }



}

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

    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...
        }
    }

随意添加您的评论!

谢谢!

于 2013-03-06T17:36:14.623 回答