如何按照惯例首先删除代码中的外键字段的下划线 [英] How do I remove underscore of foreign key fields in code first by convention

查看:151
本文介绍了如何按照惯例首先删除代码中的外键字段的下划线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的项目中有多个课程(包括TPT)。每个POCO都有一个 BaseClass ,它有一个 GUID (称为 GlobalKey )作为主键。



首先我使用 DataAnnotations 来创建正确的外键。但是,我有相应的GUID与对象本身同步的问题。



现在我只想有一个虚拟导航属性,以便数据库中的GUID字段由 NamingConvention 创建。但是字段名称总是添加一个下划线,后跟单词 GlobalKey (这是正确的)。当我想删除下划线时,我不想通过我所有的POCO流畅的API来执行此操作:

  //从Navigation-Field中删除下划线
modelBuilder.Entity< Person>()
.HasOptional(x => x.Address)
.WithMany()
.Map (a => a.MapKey(AddressGlobalKey));

通过覆盖约定,为所有POCOS做出这样的想法?



提前感谢



Andreas

解决方案

p>我终于找到了一个答案,通过写一个习惯惯例。这个惯例适用于EF 6.0 RC1(上周的代码),所以我认为在发布EF 6.0后,它可能会继续工作。



使用这种方法,标准EF约定识别独立关联(IAs),然后为外键字段创建EdmProperty。然后这个惯例来了,重命名外键字段。

  ///< summary> 
///提供修改独立关联(IA)外键列名称的约定。
///< / summary>
public class ForeignKeyNamingConvention:IStoreModelConvention< AssociationType>
{

public void Apply(AssociationType association,DbModel model)
{
//识别一个ForeignKey属性(包括IAs)
if(association。 IsForeignKey)
{
//重命名FK列
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);
}
}
}

私有bool DoPropertiesHaveDefaultNames(ReadOnlyMetadataCollection< EdmProperty>属性,字符串roleName,ReadOnlyMetadataCollection&Ed .Property> 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;
}
}
返回true;
}

private void NormalizeForeignKeyProperties(ReadOnlyMetadataCollection< EdmProperty>属性)
{
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;
}
属性[i] .Name = newPropertyName;
}
}

}

请注意该公约被添加到您的 DbContext.OnModelCreating 覆盖的 DbContext 中,使用:

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


I've got multiple classes (including TPT) in my project. Each POCO has a BaseClass, which has a GUID (called GlobalKey) as primary key.

First I used DataAnnotations to create correct foreign keys. But then I've got problems synchronizing the corresponding GUID with the object itself.

Now I want to have only one virtual navigation property so that the GUID field in the database is created by NamingConvention. But the field name always adds an underscore followed by the word GlobalKey (which is right). When I want to remove the underscore, I don't want to go thru all my POCOs in the fluent API to do this:

// Remove underscore from Navigation-Field     
modelBuilder.Entity<Person>()
            .HasOptional(x => x.Address)
            .WithMany()
            .Map(a => a.MapKey("AddressGlobalKey"));

Any ideas to do this for all POCOS by overwriting a convention?

Thanks in advance.

Andreas

解决方案

I finally found an answer for this, by writing a custom convention. This convention works in EF 6.0 RC1 (code from last week), so I think it's likely to continue to work after EF 6.0 is released.

With this approach, the standard EF conventions identify the independent associations (IAs), and then create the EdmProperty for the foreign key field. Then this convention comes along and renames the foreign key fields.

/// <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;
        }
    }

}

Note that the Convention is added to your DbContext in your DbContext.OnModelCreating override, using:

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

这篇关于如何按照惯例首先删除代码中的外键字段的下划线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆