Entity Framework Code First et Firebird – Problème de nom de clé étrangère

J’essaie de créer une nouvelle firebase database avec 2 tables ( Dissortingcts et Databases ) en utilisant le code EF en premier et ce code simple:

 using (var db = new FirebirdDBContext(_connectionSsortingng)) { db.Database.CreateIfNotExists(); } 

Mes classes:

 public class Dissortingct { [Key] public int Dissortingct_id { get; set; } [Column(TypeName = "VARCHAR")] [SsortingngLength(50)] public ssortingng Dissortingct_name { get; set; } [ForeignKey("DataBase")] public int DataBase_id { get; set; } public DataBase DataBase { get; set; } } public class DataBase { [Key] public int DataBase_id { get; set; } [Column(TypeName = "VARCHAR")] [SsortingngLength(50)] public ssortingng DataBase_name { get; set; } public ICollection Dissortingct { get; set; } public DataBase() { Dissortingct = new List(); } } 

Mais malheureusement, une erreur est générée:

L’argument spécifié était en dehors de la plage de valeurs valides.
Nom du paramètre: le nom ‘FK_Dissortingcts_DataBases_DataBase_id’ est plus long que la limite de 31 caractères de Firebird pour les noms d’object.

Je connais la limite de 31 caractères de Firebird, mais comment puis-je résoudre ce problème si j’utilise d’abord le code Entity Framework?

L’augmentation de la limite de 31 caractères de Firebird pour les noms de champs de métadonnées a été une demande de fonctionnalité constante, et il n’y a pas de moyen réel d’augmenter la limite de longueur.

Cela dit, nous pourrions peut-être contrôler la longueur du nom de la contrainte de clé étrangère que EF essaie de générer. Cela impliquera de renommer vos propriétés de classe en noms plus courts (tout en les associant à leur vrai nom de colonne).

Espérons que EF génère les noms de contrainte de clé étrangère à partir des noms de propriété de la classe, et non des colonnes réelles.

FK_Dissortingcts_DataBases_DataBase_id est 23 + 11 = 34 caractères. nous devons l’obtenir sous 32 caractères ..

Je pense que ce préfixe est peut-être inévitable. FK_Dissortingcts_DataBases_ nous avons donc une marge de manœuvre pour un suffixe de 7 à 8 caractères.

Essaye ça:

 public class Dissortingct { [Key] public int Dissortingct_id { get; set; } [Column(TypeName = "VARCHAR")] [SsortingngLength(50)] public ssortingng Dissortingct_name { get; set; } [ForeignKey("DataBase")] [Column("DataBase_id")] public int DbId { get; set; } // reduce the column name public DataBase DataBase { get; set; } } public class DataBase { [Key] [Column("DataBase_id")] public int DbId { get; set; } // reduce the column name [Column(TypeName = "VARCHAR")] [SsortingngLength(50)] public ssortingng DataBase_name { get; set; } public ICollection Dissortingct { get; set; } public DataBase() { Dissortingct = new List(); } } 

Espérons que EF atsortingbue le nom de contrainte à ‘FK_Dissortingcts_DataBases_DbId’ (27 caractères)

Après avoir ajouté la migration, vous pouvez modifier votre fichier de classe de migration pour modifier le nom de la clé étrangère comme suit:

 .PrimaryKey(t => t.ID) .ForeignKey("dbo.CONTESTS", t => t.CONTEST_ID, cascadeDelete: true, name:"FK_CONTESTS_ID") .Index(t => t.CONTEST_ID); 

Il suffit d’append le nom: “your_key”, et dans la méthode Down comme ceci pour éviter les erreurs de nom de champ généré automatiquement

 DropForeignKey("dbo.BIBLIO_LIST","FK_CONTESTS_ID"); 

Une autre solution consisterait à remplacer le générateur SQL de Firebird.

Si vous ne souhaitez pas créer à nouveau l’intégralité de la logique pour la génération SQL, vous pouvez créer une classe dérivée de FbMigrationSqlGenerator et simplement remplacer les méthodes souhaitées.

Ci-dessous, j’utilise une logique de nom de table courte pour créer le nom de clé étrangère:

 public class FirebirdSqlGenerator : FbMigrationSqlGenerator { protected override IEnumerable Generate(AddForeignKeyOperation operation) { // Reduce the name using this method operation.Name = GenerateForeignKeyNameFromOperation(operation); using (var writer = SqlWriter()) { writer.Write("ALTER TABLE "); writer.Write(Quote(CheckName(ExtractName(operation.DependentTable)))); writer.Write(" ADD CONSTRAINT "); writer.Write(Quote(CheckName(CreateItemName(operation.Name)))); writer.Write(" FOREIGN KEY ("); WriteColumns(writer, operation.DependentColumns.Select(Quote)); writer.Write(") REFERENCES "); writer.Write(Quote(CheckName(ExtractName(operation.PrincipalTable)))); writer.Write(" ("); WriteColumns(writer, operation.PrincipalColumns.Select(Quote)); writer.Write(")"); if (operation.CascadeDelete) { writer.Write(" ON DELETE CASCADE"); } yield return Statement(writer.ToSsortingng()); } } public ssortingng GenerateForeignKeyNameFromOperation(AddForeignKeyOperation foreignKeyOperation) { var depTable = GetShortNameFromTableName(CreateItemName(foreignKeyOperation.DependentTable)); foreignKeyOperation.Name = "FK_" + depTable + "_" + GetShortNameFromTableName(CreateItemName(foreignKeyOperation.PrincipalTable)) + "_" + Ssortingng.Join("_", foreignKeyOperation.DependentColumns); return foreignKeyOperation.Name; } [...] } 

définissez-le comme votre générateur SQL avec la méthode SetSqlGenerator. Il ressemblera à ceci:

 internal sealed class MyConfiguration : DbMigrationsConfiguration { private ssortingng firebirdProviderInvariantName = "FirebirdSql.Data.FirebirdClient"; ///  /// Initializes a new instance of the  class. ///  public MyConfiguration() { SetSqlGenerator(firebirdProviderInvariantName, new FirebirdSqlGenerator(); } } 

Conseil supplémentaire: si vous souhaitez déboguer votre code pour rechercher des problèmes, vous pouvez append les lignes suivantes dans votre méthode Generate:

  if (System.Diagnostics.Debugger.IsAttached == false) System.Diagnostics.Debugger.Launch(); System.Diagnostics.Debugger.Break(); 

Cela lancera une session de débogage que vous pourrez capturer dans une autre instance de Visual Studio.

Quelques autres pages qui pourraient vous aider: Rapport Firebird: https://github.com/cincuranet/FirebirdSql.Data.FirebirdClient Rapport EF: https://github.com/aspnet/EntityFramework6

J’espère que ça aide.