请考虑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
而非Desc1
或Desc2
,并且始终会创建此内容:
Base_Id INT NOT NULL
Base_Foo VARCHAR(MAX) NULL
Base_Foo1 INT NULL
我调查了EdmModel
类,但我找不到一种方法来获取源自表中字段的类名!
答案 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".