将实体框架与我的POCO类分离

时间:2013-02-12 17:04:21

标签: entity-framework linq-expressions

我通过迭代从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进行硬编码引用?

1 个答案:

答案 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; }
}