How do I remove underscore of foreign key fields in code first by convention

code-first entity-framework entity-framework-6 naming-conventions

Question

In my project, I have several classes (including TPT). One POCO has aBaseClass which features aGUID (called GlobalKey (as the main key).

I began by usingDataAnnotations to correctly produce foreign keys Then again, syncing the matching GUID with the item itself is a difficulty for me.

So that the GUID field in the database is established by having just one virtual navigation attribute,NamingConvention . However, the field name always follows the word with an underscore.GlobalKey (Which is accurate.) I don't want to go through all of my POCOs in the Fluent API to do this when I want to remove the underscore:

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

Any thoughts about how to overwrite a convention to accomplish this for all POCOS?

I appreciate it.

Andreas

1
51
4/10/2013 1:08:48 PM

Accepted Answer

I ultimately came up with a solution for this by creating a unique convention. This convention continues to function in EF 6.0 RC1 (code from last week), therefore I anticipate that it will also function once EF 6.0 is made available.

In this method, the independent associations (IAs) are identified using the standard EF procedures, and the EdmProperty is then created for the foreign key field. The foreign key fields are then given a new name thanks to this convention.

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

}

Keep in mind that the Convention has been added to yourDbContext in theDbContext.OnModelCreating supplant using:

modelBuilder.Conventions.Add(new ForeignKeyNamingConvention());
68
8/15/2013 1:59:32 AM

Popular Answer

Although it's a little dated, here is an example of how I set mapping columns in my fluent configuration (OnModelCreating):

modelBuilder.Entity<Application>()
            .HasOptional(c => c.Account)
                .WithMany()
                .Map(c => c.MapKey("AccountId"));

Hope this is helpful.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow