0

DB (Sql2008) とモデル (C#) が既に作成されている MVC4 プロジェクトがあるため、どちらの名前も変更できません。使用している各クラスのカスタム構成で 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
        }
    }

ビルドするとエラーが発生します

「タイプ 'Company' のプロパティは、一度しかマッピングできません。」

これが発生するのは、1 つはベース、もう 1 つは派生クラスの 2 回マッピングしているためです。tableName と primaryKeyName の両方に 2 番目のマッピングがある場合、最初のマッピングをオーバーライドできるかどうかを知りたいです。

前もって感謝します!

編集: 一部のエンティティには差別が必要です。

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

2 に答える 2

0

BaseConfigurationのコンストラクターは、常にCompanyConfigurationのコンストラクターの前に実行されるため、CompanyConfigurationのコードブロックが実行される前に、常にマップアクションが実行されます。とにかく、マップ呼び出しをオーバーライドして、2回目の呼び出しを許可することに気づいていません。ただし、これを解決する1つのオプションは、これを解決するオーバーロードされたコンストラクターを使用することです。

子クラスのようなもの:

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

高く評価された回答ですが、すべての要件を満たしているわけではありません。これは私がこれまでに得た解決策です:

すべてのテーブルと 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 に答える