实体框架中的前缀列命名约定

时间:2018-03-19 15:05:51

标签: c# entity-framework entity-framework-6 ef-code-first

请考虑EF6代码优先数据库。我有:

public class Base
{
    public int Id { get; set; }
}

public class Desc1 : Base
{
    public string Foo { get; set; }
}

public class Desc2 : Base
{
    public int? Foo { get; set; }
}

我希望表Base有三列(以自动方式):

Base_Id INT NOT NULL
Desc1_Foo VARCHAR(MAX) NULL
Desc2_Foo INT NULL

我的意思是,以其类名作为前缀。我知道我可以使用EntityTypeConfiguration来做到这一点,但我的数据库有150个表,我无法配置每个列。

所以我尝试使用命名约定:

public class PrefixConvention : IStoreModelConvention<EdmProperty>
{
    public void Apply(EdmProperty property, DbModel model)
    {
        property.Name = property.DeclaringType.Name + "_" + property.Name;
    }
}

...

modelBuilder.Conventions.Add(new PrefixConvention());

property.DeclaringType.Name仅向我显示Base而非Desc1Desc2,并且始终会创建此内容:

Base_Id INT NOT NULL
Base_Foo VARCHAR(MAX) NULL
Base_Foo1 INT NULL

我调查了EdmModel类,但我找不到一种方法来获取源自表中字段的类名!

1 个答案:

答案 0 :(得分:0)

好的,我开发了自己的PrefixConvention。使用它:

PrefixConventionclass

在这里,using System.Collections.Generic; using System.Data.Entity.Core.Mapping; using System.Data.Entity.Core.Metadata.Edm; using System.Data.Entity.Infrastructure; using System.Data.Entity.ModelConfiguration.Conventions; using System.Linq; namespace Habitus.Toolkit.Database { public class PrefixConvention : IStoreModelConvention<EdmProperty> { public void Apply(EdmProperty property, DbModel model) { if (property.Name == "Id" || property.Name == "Discriminator" || property.DeclaringType.IsView()) return; var fragments = model .ConceptualToStoreMapping .EntitySetMappings .SelectMany(esm => esm.EntityTypeMappings) .SelectMany(etm => etm.Fragments) .Where(f => f.StoreEntitySet.ElementType == property.DeclaringType) .ToList(); var propertyMappings = fragments .SelectMany(f => f.PropertyMappings) .ToList(); var path = GetPropertyPath(property, propertyMappings); if (path?.Any() == false) { throw new System.Exception($"Can't process property {property.DeclaringType.FullName}.{property.Name}"); } var first = path.First(); var names = path.Select(pm => pm.Name).ToList(); property.Name = $"{first.DeclaringType.Name}__{string.Join("_", names)}"; } private List<EdmProperty> GetPropertyPath(EdmProperty property, List<PropertyMapping> propertyMappings) { var result = new List<EdmProperty>(); var scalarPropertyMapping = propertyMappings .OfType<ScalarPropertyMapping>() .Where(pm => pm.Column == property) .FirstOrDefault(); if (scalarPropertyMapping != null) { result.Add(scalarPropertyMapping.Property); } else { var complexPropertyMappings = propertyMappings .OfType<ComplexPropertyMapping>() .ToList(); foreach (var complexPropertyMapping in complexPropertyMappings) { var recursivePropertyMappings = complexPropertyMapping .TypeMappings .SelectMany(tm => tm.PropertyMappings) .ToList(); var recursiveResult = GetPropertyPath(property, recursivePropertyMappings); if (recursiveResult.Any()) { result.Add(complexPropertyMapping.Property); result.AddRange(recursiveResult); break; } } } return result; } } }

<openjpa-2.4.2-r422266:1777108 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: This configuration disallows runtime optimization, but the following listed types were not enhanced at build time or at class load time with a javaagent: "
al.das.MyProject.Entities.Entity1
al.das.MyProject.Entities.Entity2
al.das.MyProject.Entities.Entity3".