关于一般性意见,请。
我不知道要对 EF 进行更改,但处理类似问题在 EF 中并不罕见。
EF 并不支持所有标准类型。
您可以在 POCO 类中拥有一个辅助字段。
因此,其中一个字段是实际的数据库字段,但在 POCO 之外不使用。
帮助字段在 Fluent API 中未映射或被忽略。
您可以通过助手访问数据库并执行任何所需的转换。
一个简单的例子。或者相反,如果我将助手和数据库字段类型放在前面。
[NotMapped]
public virtual bool IsVisible { set; get; } // Helper Field NOT on DB
public int Test { get { return IsVisible ? 1 : 0; } // on DB, but set and get via helper only.
set { IsVisible = (value != 0); } }
编辑:Power Fluent API下面的代码片段概述了如何以一致的方式为每个映射的 poco 运行代码。
public class MyDbContext : DbContext
// model building, set breakpoint so you know when this is triggered
// it is important this ISNT called everytime, only on model cache.
// in my case that is app pool recycle.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
// use the CONFIG add feature to better organize and allow use of inheritance when mapping
// I will use snippets and statics to keep it simple.
modelBuilder.Configurations.Add(XYZMap.Map()); // POCO map
modelBuilder.Configurations.Add(ABCMAP.Map()); // poco map
modelBuilder.Configurations.Add(XXXMap.MAP()); // poco map
// etc for your POCO set
// Note, no need to declare DBset<xyz> XYZs {get;set;} !!!!
public static class XYZMap {
public static BaseEntityIntConfiguration<PocoXYZ> Map() {
//see return object !
var entity = new BaseEntityLongConfiguration<PocoXYZ>();
//entity.Property()... // map away as usual POCO specifc
///entity.HasRequired()...// property and relationships as required
// do nothing for default
return entity;
}
}
}
// all tables with int key use this base config. do it once never again
public class BaseEntityIntConfiguration<T> : BaseEntityConfiguration<T> where T : BaseObjectInt {
public BaseEntityIntConfiguration(DatabaseGeneratedOption DGO = DatabaseGeneratedOption.Identity) {
// Primary Key
this.HasKey(t => t.Id);
// Properties
//Id is an int allocated by DB
this.Property(t => t.Id).HasDatabaseGeneratedOption(DGO); // default to db generated
// optimistic lock is also added here, Specific to out poco design
this.Property(t => t.RowVersion)
.IsRequired()
.IsFixedLength()
.HasMaxLength(8)
.IsRowVersion();
// any other common mappings/ rules ??
}
}
public class BaseEntityConfiguration<T> : EntityTypeConfiguration<T> where T : BaseObject {
public BaseEntityConfiguration() {
this.ApplyAttributeRules(); // <<<<< Here is where I apply SYSTEM WIDE rules
}
}
public static void ApplyAttributeRules<T>(this EntityTypeConfiguration<T> entity) where T : BaseObject {
// so this will be called for each mapped type
foreach (var propertyInfo in typeof (T).GetProperties()) {
// I use reflection to look for properties that meet certain criteria.
// eg string. I want as NVARCHAR 4000 not NVCAHR max so i can index it.
if (propertyInfo.UnderLyingType().FullName == "System.String") {
SetStringLength(BosTypeTool.StringLengthIndexable, propertyInfo.Name, entity);
continue;
}
SetStringLength(4000, propertyInfo.Name, entity);
}
}
private static void SetStringLength<TModelPoco>(int length, string propertyName,
EntityTypeConfiguration<TModelPoco> entity) where TModelPoco : BaseObject {
var propLambda = DynamicExpression.ParseLambda<TModelPoco, String>(propertyName);
entity.Property(propLambda).HasMaxLength(length);
// dynamic library from Microsoft.... http://msdn.microsoft.com/en-US/vstudio/bb894665.aspx
}
// get underlying type incase it is nullable
public static Type UnderLyingType(this PropertyInfo propertyInfo) {
return Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType;
}