Skip to content

CustomConventions

Marcin Sulecki edited this page Sep 12, 2017 · 4 revisions

Tworzenie własnych konwencji

Zmiana typu domyślnego na przykładzie datetime2

Zamiast stosowania w każdym przypadku konfiguracji w stylu:

modelBuilder.Properties<DateTime>()
                .Configure(c => c.HasColumnType("datetime2"));

Można utworzyć konwencję, która dla wszystkich pól z typem datetime w modelu będzie stosować datetime2 w bazie danych.

public class DateTime2Convention : Convention
    {
        public DateTime2Convention()
        {
            this.Properties<DateTime>()
                .Configure(c => c.HasColumnType("datetime2"));        
        }
    }

Następnie dodajemy utworzoną konwencję do kolekcji:

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

Przykład konwencji, która sprawdza nazwę właściwości

public class KeyConvention : Convention
    {
        public KeyConvention()
        {
            this.Properties<int>()
                 .Where(p => p.Name.EndsWith("Key"))
                 .Configure(p => p.IsKey());
        }
    }

Implementacja IStoreModelConvention

    public class ForeignKeyNamingConvention : IStoreModelConvention<AssociationType>
    {
        public void Apply(AssociationType association, DbModel model)
        {
            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 + "Id";
                }
                properties[i].Name = newPropertyName;
            }
        }

    }
Clone this wiki locally