[英]How to configure Entity Framework with given conventions?
我有一個已經創建了DB(Sql2008)和Models(C#)的MVC4項目,因此無法同時更改它們的名稱。 我開始使用EF4.1對每個正在使用的類進行自定義配置,因此在創建模型時,所有內容都映射到數據庫。 通常,所有表的名稱均為“ tbl_X _” +實體名稱,主鍵為“實體名稱” +“ 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'的屬性只能映射一次。”
我絕對知道會發生這種情況,因為我映射了兩次,一個映射基於基,另一個映射於派生類。 我想知道,如果tableName和primaryKeyName都有第二個映射,是否可以覆蓋第一個。
提前致謝!
編輯:一些實體需要歧視。
Map(x => x.Requires("discriminatorColumn")
.HasValue(value)
.HasColumnType("dataType")
.IsRequired())
.ToTable("tbl_TableName");
BaseConfiguration上的構造函數總是要在CompanyConfiguration的構造函數之前運行,因此在CompanyConfiguration的代碼塊運行之前,總是會有一個映射動作執行。 無論如何,我不知道會覆蓋地圖調用以允許第二次調用。 但是,解決此問題的一種方法可能是讓一些重載的構造函數來解決此問題。
類似於兒童班:
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");
}
}
滿意的答案,但不能滿足所有要求。 到目前為止,這是我得到的解決方案:
我將所有表和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...
}
}
隨時添加您的評論!
謝謝!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.