53 votes

Améliorer les noms de propriété de navigation lors du reverse engineering d'une base de données

Je suis en utilisant Entity Framework 5 avec Visual Studio avec Entity Framework, Outils électriques Bêta 2 à désosser taille moyenne des bases de données (~100 tables).

Malheureusement, les propriétés de navigation n'ont pas des noms significatifs. Par exemple, si il y a deux tables:

CREATE TABLE Contacts (
    ContactID INT IDENTITY (1, 1) NOT NULL,
    ...
    CONSTRAINT PK_Contacts PRIMARY KEY CLUSTERED (ContactID ASC)
}

CREATE TABLE Projects (
    ProjectID INT IDENTITY (1, 1) NOT NULL,
    TechnicalContactID INT NOT NULL,
    SalesContactID INT NOT NULL,
    ...
    CONSTRAINT PK_Projects PRIMARY KEY CLUSTERED (ProjectID ASC),
    CONSTRAINT FK_Projects_TechnicalContact FOREIGN KEY (TechnicalContactID)
        REFERENCES Contacts (ContactID),
    CONSTRAINT FK_Projects_SalesContact FOREIGN KEY (SalesContactID)
        REFERENCES Contacts (ContactID),
    ...
}

Cela va générer des classes comme ceci:

public class Contact
{
     public Contact()
     {
          this.Projects = new List<Project>();
          this.Projects1 = new List<Project>();
     }
     public int ContactID { get; set; }
     // ...
     public virtual ICollection<Project> Projects { get; set; }
     public virtual ICollection<Project> Projects1 { get; set; }
}

public class Project
{
     public Project()
     {

     }
     public int ProjectID { get; set; }
     public int TechnicalContactID { get; set; }
     public int SalesContactID { get; set; }
     // ...
     public virtual Contact Contact { get; set; }
     public virtual Contact Contact1 { get; set; }
}

Je vois plusieurs variantes qui doivent toutes être mieux que cela:

  • Utiliser le nom de la clé étrangère: Par exemple, tout ce qui est après le dernier caractère de soulignement (FK_Projects_TechnicalContact --> TechnicalContact). Mais ce serait sans doute la solution avec le plus de contrôle, cela peut être plus difficile à intégrer avec les modèles existants.
  • Utiliser le nom de la propriété correspondant à la colonne de la clé étrangère: enlever le suffixe ID (TechnicalContactID --> TechnicalContact)
  • Utiliser la concaténation du nom de la propriété et de la solution existante: Exemple TechnicalContactIDProjects (collection) et TechnicalContactIDContact

Heureusement, il est possible de modifier les modèles en les incluant dans le projet.

Les modifications devront être apportées à l' Entity.tt et Mapping.tt. Je trouve cela difficile à cause du manque d'intellisense et de déboguer des possibilités pour faire ces changements.


La concaténation des noms de propriété (la troisième dans la liste ci-dessus) est probablement la solution la plus simple à mettre en œuvre.

Comment faire pour modifier la création de navigation propriétés en Entity.tt et Mapping.tt pour atteindre le résultat suivant:

public class Contact
{
     public Contact()
     {
          this.TechnicalContactIDProjects = new List<Project>();
          this.SalesContactIDProjects = new List<Project>();
     }
     public int ContactID { get; set; }
     // ...
     public virtual ICollection<Project> TechnicalContactIDProjects { get; set; }
     public virtual ICollection<Project> SalesContactIDProjects { get; set; }
}

public class Project
{
     public Project()
     {

     }
     public int ProjectID { get; set; }
     public int TechnicalContactID { get; set; }
     public int SalesContactID { get; set; }
     // ...
     public virtual Contact TechnicalContactIDContact { get; set; }
     public virtual Contact SalesContactIDContact { get; set; }
}

48voto

Rikkos Points 2165

Il y a quelques choses que vous devez changer à l'intérieur de l' .tt fichier. Je choisis d'utiliser la troisième solution vous l'avez suggéré, mais cela nécessite d'être formatés comme FK_CollectionName_RelationName. J'ai divisé avec le '_' et l'utilisation de la dernière chaîne dans le tableau. J'utilise le RelationName avec le ToEndMember propriété pour créer un nom de propriété. FK_Projects_TechnicalContact entraînera

//Plularized because of EF. 
public virtual Contacts TechnicalContactContacts { get; set; }

et vos projets seront comme ça.

public virtual ICollection<Projects> SalesContactProjects { get;  set; }
public virtual ICollection<Projects> TechnicalContactProjects { get;  set; }

Maintenant le code, vous pouvez le demander. Ive a ajouté 2 fonctions à l' CodeStringGenerator de la classe dans le fichier T4. Celui qui construit le propertyName recevoir un NavigationProperty. et l'autre, de générer le code pour le bien recevoir un NavigationProperty et le nom de la propriété.

//CodeStringGenerator class
public string GetPropertyNameForNavigationProperty(NavigationProperty navigationProperty)
{
    var ForeignKeyName = navigationProperty.RelationshipType.Name.Split('_');
    var propertyName = ForeignKeyName[ForeignKeyName.Length-1] + navigationProperty.ToEndMember.Name;
    return propertyName;
}

public string NavigationProperty(NavigationProperty navigationProperty, string name)
{
    var endType = _typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType());
    return string.Format(
        CultureInfo.InvariantCulture,
        "{0} {1} {2} {{ {3}get; {4}set; }}",
        AccessibilityAndVirtual(Accessibility.ForProperty(navigationProperty)),
        navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType,
        name,
        _code.SpaceAfter(Accessibility.ForGetter(navigationProperty)),
        _code.SpaceAfter(Accessibility.ForSetter(navigationProperty)));
}

Si vous placez le code ci-dessus dans la classe que vous avez encore besoin de changer les 2 parties. Vous devez trouver l'endroit où le constructeur de la partie et la navigation de la partie de la propriété sont en train de construire de l'entité. Dans le constructeur de la partie (autour de la ligne 60), vous devez remplacer le code existant par l'appel de la méthode GetPropertyNameForNavigationProperty et en la passant à la méthode d'échappement.

      var propName = codeStringGenerator.GetPropertyNameForNavigationProperty(navigationProperty);
#>
      this.<#=code.Escape(propName)#> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>();
<#

Et dans le NavigationProperties partie (autour de la ligne 100), vous aurez également besoin de remplacer le code par le suivant.

    var propName = codeStringGenerator.GetPropertyNameForNavigationProperty(navigationProperty);
#>
    <#=codeStringGenerator.NavigationProperty(navigationProperty, propName)#>
<#

J'espère que cette aide, et vous pouvez toujours déboguer l' GetPropertyNameForNavigationProperty de la fonction et de jouer un peu avec la désignation de la propriété.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X