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

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

问题描述

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

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

首先我使用 DataAnnotations 创建正确的外键.但是我在将相应的 GUID 与对象本身同步时遇到了问题.

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

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

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"));

有什么想法可以通过覆盖约定来为所有 POCOS 执行此操作?

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

提前致谢.

安德烈亚斯

推荐答案

我终于通过编写自定义约定找到了答案.这个约定在 EF 6.0 RC1(上周的代码)中有效,所以我认为在 EF 6.0 发布后它可能会继续有效.

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.

使用这种方法,标准 EF 约定识别独立关联 (IA),然后为外键字段创建 EdmProperty.然后这个约定出现并重命名外键字段.

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

}

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

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

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

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

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