entity framework代码First和Firebird – 外键名称问题

我正在尝试使用EF代码优先创建包含2个表( DistrictsDatabases )的新数据库,这个简单的代码:

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

我的课程:

 public class District { [Key] public int District_id { get; set; } [Column(TypeName = "VARCHAR")] [StringLength(50)] public string District_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")] [StringLength(50)] public string DataBase_name { get; set; } public ICollection District { get; set; } public DataBase() { District = new List(); } } 

但不幸的是它抛出了一个错误:

指定的参数超出了有效值的范围。
参数名称:名称“FK_Districts_DataBases_DataBase_id”比Firebird的对象名称限制为31个字符。

我知道Firebird的31个字符限制,但如果我使用Entity Framework代码优先,我怎么能解决这个问题呢?

增加Firebird的元数据字段名称的31个字符限制一直是一个常量的function请求,并没有真正的方法来增加长度限制。

话虽如此,我们可能能够控制EF试图生成的外键约束名称的长度..这将涉及将类属性重命名为较短的名称(但仍将它们映射到它们的真实列名)

希望EF从类的属性名称生成外键约束名称,而不是实际的列。

FK_Districts_DataBases_DataBase_id是23 + 11 = 34个字符。 我们需要得到32个字符以下..

我认为这个前缀可能是不可避免的。 FK_Districts_DataBases_所以我们有一个7-8字符后缀的余地。

试试这个:

 public class District { [Key] public int District_id { get; set; } [Column(TypeName = "VARCHAR")] [StringLength(50)] public string District_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")] [StringLength(50)] public string DataBase_name { get; set; } public ICollection District { get; set; } public DataBase() { District = new List(); } } 

希望EF将约束名称设为’FK_Districts_DataBases_DbId’(27个字符)

添加迁移后,您可以修改迁移类文件以更改外键名称,如下所示:

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

只需添加名称:“your_key”,并在Down方法中添加自动生成的字段名称的错误

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

另一种解决方案是覆盖Firebird SQL生成器。

如果您不想再次为SQL生成创建整个逻辑,则可以创建一个派生自FbMigrationSqlGenerator的类,并只覆盖所需的方法。

下面我使用短表名逻辑来创建外键名称:

 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.ToString()); } } public string GenerateForeignKeyNameFromOperation(AddForeignKeyOperation foreignKeyOperation) { var depTable = GetShortNameFromTableName(CreateItemName(foreignKeyOperation.DependentTable)); foreignKeyOperation.Name = "FK_" + depTable + "_" + GetShortNameFromTableName(CreateItemName(foreignKeyOperation.PrincipalTable)) + "_" + String.Join("_", foreignKeyOperation.DependentColumns); return foreignKeyOperation.Name; } [...] } 

使用SetSqlGenerator方法将其设置为SQL Generator。 它看起来像这样:

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

额外提示:如果要调试代码以检查问题,可以在Generate方法中添加以下行:

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

这将启动一个Debug会话,您可以在另一个Visual Studio实例中捕获该会话。

其他一些可能对您有帮助的页面:Firebird Repo: https : //github.com/cincuranet/FirebirdSql.Data.FirebirdClient EF Repo: https : //github.com/aspnet/EntityFramework6

我希望它有所帮助。