我的项目中有多个类(包括 TPT)。每个 POCO 都有一个 BaseClass
,它有一个 GUID
(称为 GlobalKey
)作为主键。
首先,我使用 DataAnnotations
创建正确的外键。但随后我在将相应的 GUID 与对象本身同步时遇到了问题。
现在我只想拥有一个虚拟导航属性,以便数据库中的 GUID 字段由 NamingConvention
创建。但字段名称总是添加一个下划线,后跟单词 GlobalKey
(这是正确的)。当我想删除下划线时,我不想遍历 Fluent API 中的所有 POCO 来执行此操作:
// Remove underscore from Navigation-Field
modelBuilder.Entity<Person>()
.HasOptional(x => x.Address)
.WithMany()
.Map(a => a.MapKey("AddressGlobalKey"));
有什么想法可以通过覆盖约定来为所有 POCOS 做到这一点吗?
提前致谢。
安德烈亚斯
最佳答案
我终于通过编写自定义约定找到了这个问题的答案。此约定在 EF 6.0 RC1(上周的代码)中有效,因此我认为在 EF 6.0 发布后它可能会继续有效。
通过这种方法,标准 EF 约定可识别独立关联 (IA),然后为外键字段创建 EdmProperty。然后这个约定出现并重命名外键字段。
/// <summary>
/// Provides a convention for fixing the independent association (IA) foreign key column names.
/// </summary>
public class ForeignKeyNamingConvention : IStoreModelConvention<AssociationType>
{
public void Apply(AssociationType association, DbModel model)
{
// Identify a ForeignKey properties (including IAs)
if (association.IsForeignKey)
{
// rename FK columns
var constraint = association.Constraint;
if (DoPropertiesHaveDefaultNames(constraint.FromProperties, constraint.ToRole.Name, constraint.ToProperties))
{
NormalizeForeignKeyProperties(constraint.FromProperties);
}
if (DoPropertiesHaveDefaultNames(constraint.ToProperties, constraint.FromRole.Name, constraint.FromProperties))
{
NormalizeForeignKeyProperties(constraint.ToProperties);
}
}
}
private bool DoPropertiesHaveDefaultNames(ReadOnlyMetadataCollection<EdmProperty> properties, string roleName, ReadOnlyMetadataCollection<EdmProperty> otherEndProperties)
{
if (properties.Count != otherEndProperties.Count)
{
return false;
}
for (int i = 0; i < properties.Count; ++i)
{
if (!properties[i].Name.EndsWith("_" + otherEndProperties[i].Name))
{
return false;
}
}
return true;
}
private void NormalizeForeignKeyProperties(ReadOnlyMetadataCollection<EdmProperty> properties)
{
for (int i = 0; i < properties.Count; ++i)
{
string defaultPropertyName = properties[i].Name;
int ichUnderscore = defaultPropertyName.IndexOf('_');
if (ichUnderscore <= 0)
{
continue;
}
string navigationPropertyName = defaultPropertyName.Substring(0, ichUnderscore);
string targetKey = defaultPropertyName.Substring(ichUnderscore + 1);
string newPropertyName;
if (targetKey.StartsWith(navigationPropertyName))
{
newPropertyName = targetKey;
}
else
{
newPropertyName = navigationPropertyName + targetKey;
}
properties[i].Name = newPropertyName;
}
}
}
请注意,该约定已添加到 DbContext.OnModelCreating
覆盖中的 DbContext
中,使用:
modelBuilder.Conventions.Add(new ForeignKeyNamingConvention());
关于entity-framework - 如何按照约定首先删除代码中外键字段的下划线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15684555/