我通过迭代从EntityBase继承的任何实体并将它们添加到我的Context中来动态创建我的DbContext:
private void AddEntities(DbModelBuilder modelBuilder)
{
var entityMethod = typeof(DbModelBuilder).GetMethod("Entity");
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
var entityTypes = assembly.GetTypes()
.Where(x => x.IsSubclassOf(typeof(EntityBase)) && !x.IsAbstract);
foreach (var type in entityTypes)
{
dynamic entityConfiguration = entityMethod.MakeGenericMethod(type).Invoke(modelBuilder, new object[] { });
EntityBase entity = (EntityBase)Activator.CreateInstance(type);
//Add any specific mappings that this class has defined
entity.OnModelCreating(entityConfiguration);
}
}
}
这样,我可以拥有许多名称空间,但在我的基本名称空间中只有一个通用存储库,它随处可见。此外,在使用多个名称空间的应用程序中,基本存储库已经设置为使用所有加载的名称空间中的所有实体。我的问题是,我不想让EntityFramework.dll成为公司中每个命名空间的依赖项。所以我调用OnModelCreating并将EntityTypeConfiguration传递给类,以便它可以添加任何映射。这工作正常,这是我如何添加映射来告诉模型我的“描述”属性来自名为“描述符”的列:
class Widget... {
public override void OnModelCreating(dynamic entity)
{
System.Linq.Expressions.Expression<Func<Widget, string>> tmp =
x => x.Description;
entity.Property(tmp).HasColumnName("Descriptor");
}
好处是,我的实体类没有引用EF,这个方法只被调用一次,当创建上下文时,如果我们废弃EF并在将来转到别的东西,我的类将不会全部其中特定于EF的各种属性。
问题是,它非常丑陋。如何让模型以更简单的方式了解列映射和键,而不是创建这些Expressions
以获取要映射的属性,而无需在我的poco类中对EF进行硬编码引用?
答案 0 :(得分:1)
您可以定义自己的属性并使用它们来控制OnModelCreating()
中的配置。您应该能够在一个linq查询中获得(使用反射)列映射所需的所有详细信息,以获得创建密钥的第二个查询。
public class DatabaseNameAttribute : Attribute
{
private readonly string _name;
public DatabaseNameAttribute(string name)
{
_name = name;
}
public string Name
{
get
{
return _name;
}
}
}
public class KeySequenceAttribute : Attribute
{
private readonly int _sequence;
public KeySequenceAttribute(int sequence)
{
_sequence = sequence;
}
public int Sequence
{
get
{
return _sequence;
}
}
}
[DatabaseName("BlogEntry")]
public class Post
{
[DatabaseName("BlogId")]
[KeySequence(1)]
public int id { get; set; }
[DatabaseName("Description")]
public string text { get; set; }
}