如何使用Fluent API和Code First Migrations设置外键名称?

我正在尝试使用EF6.4上的Code First Migrations设置外键名称(而不是外键列)。​​

我知道可以通过更新生成的迁移代码来进行设置,例如:

.ForeignKey("Documents",Function(t) t.DocumentId,cascadeDelete:=True,name:="FK_Sections_Documents")

...但是我想使用Fluent API在添加迁移之前完成。

我似乎想起了关于HasForeignKey()调用接受Func的某些事情,该调用在其主体中包含对匿名类型的调用,例如我们发现的here。但是,如果我能找到任何讨论该类型的一般结构的东西,我会很惊讶。

官方文档未对此进行讨论:

也不做这些类似的问答以完全解决问题:

这个问题是几个月前here问的,但到目前为止还没有收到答案。

我正在使用EntityTypeConfiguration(Of T)。这是我的代码:

Namespace Configuration
  Friend Class Sectionconfig
    Inherits EntityTypeConfiguration(Of Db.Section)

    Public Sub New()
      Me.HasRequired(Function(Section) Section.Document).WithMany.HasForeignKey(Function(Section) Section.DocumentId)

      Me.Property(Function(Section) Section.DocumentId).isrequired()
      Me.Property(Function(Section) Section.SectionId).isrequired()
      Me.Property(Function(Section) Section.IsSent).isrequired()
      Me.Property(Function(Section) Section.Markup).isrequired.IsMaxLength()
      Me.Property(Function(Section) Section.Title).isrequired.HasMaxLength(60)

      Me.HasIndex(Function(Section) Section.DocumentId).Hasname("IX_Sections_DocumentId")
      Me.HasIndex(Function(Section) Section.SectionId).Hasname("IX_Sections_SectionId")
      Me.HasIndex(Function(Section) Section.Title).Hasname("IX_Sections_Title")

      Me.Ignore(Function(Section) Section.Subject)
    End Sub
  End Class
End Namespace

如何设置外键名称,或者(更具体的说,假设我没记错的话)该匿名类型的一般结构应该是什么?

-更新-

我尝试过:

Me.HasRequired(Function(Section) Section.Document).WithMany.HasForeignKey(Function(Section) New With {.DependentKeyExpression = Section.DocumentId,.Name = "FK_Sections_Documents"})

...但是尝试进行迁移创建的答案如下:

  

System.Reflection.TargetinvocationException:调用的目标引发了异常。 ---> System.InvalidOperationException:属性表达式'Section => new VB $ AnonymousType_0`2(DependentKeyExpression = Section.DocumentId,Name =“ FK_Sections_Documents”)'是无效的。该表达式应表示一个属性:C#:'t => t.MyProperty'VB.Net:'Function(t)t.MyProperty'。指定多个属性时,请使用匿名类型:C#:'t => new {t.MyProperty1,t.MyProperty2}'VB.Net:'Function(t)New with {t.MyProperty1,t.MyProperty2}'。>

因此,鉴于匿名类型构造用于指定键列,所以这不是指定外键名称的方法。

问题仍然存在:我们如何使用EF6.4中的Fluent API指定外键名称?

ayihaimin 回答:如何使用Fluent API和Code First Migrations设置外键名称?

不幸的是,在EF6中,没有内置的方法可以做到这一点。为了澄清您的问题,您要问的是如何指定基于模型中指定的外键创建的基础数据库约束的名称。对于迁移生成器而言,这将是一项工作。尽管EF6迁移中提供了传递约束名称的功能,但是如果您探索源代码,您会发现它实际上从未使用过,并且所有方法都是私有的和内部的。

在EFCore中已对此进行了陈述,您现在可以执行以下操作: Me.HasRequired(Function(Section) Section.Document).WithMany().HasForeignKey(Function(Section) Section.DocumentId).HasConstraintName("FK_Sections_Documents"),但这对您没有帮助。

因此,您需要编写一个自定义迁移生成器,该生成器将执行您想要的操作。在这篇文章中回答了这个确切的问题(C#中的代码,数据库是SQL Server):Change foreign key constraint naming convention

,

使用Fluent映射,ForeignKey attibute希望在您的类中使用属​​性名称作为参数。

受保护的覆盖无效OnModelCreating(DbModelBuilder modelBuilder) {

modelBuilder.Entity<WidgetEntity>()
 .HasRequired(w => w.Sequence)
 .WithMany()
 .Map(m => m.MapKey("FK_Sections_Documents"));

}

LookupData配置:

HasRequired(p => p.LookupType).WithMany(p=>p.LookupData).HasForeignKey(p=>p.LookupTypeId).WillCascadeOnDelete(false);

名称配置:

HasOptional(p => p.Gender).WithMany(p=>p.Name).HasForeignKey(p=>p.GenderLookupId).WillCascadeOnDelete(false);

如果您不想使用流利的语法,也可以使用InversePropertyAttribute,因为“逆属性”更易于阅读,并且正好写在它们所影响的属性之上。

更新

  

将ForeignKey与关联的属性一起使用

示例1:

[Table("ENTITIES")]
public class Entity {

    [Column("ENTITY_NO")]
    public int No { set; get; }

    [Column("SEQUENCE_NO")]
    public int SequenceNo { set; get; }

    [ForeignKey("SequenceNo")] //Has to be a property name,not table column name
    public Sequence Sequence { set; get; }

    // and other properties that map correctly
}

[Table("SEQUENCES")]
public class Sequence { 

    [Column("SEQUENCE_NO")]
    public int No { set; get; }

    [Column("NUMBER")]
    public int Number { set; get; }
}

示例2:

[Table("ENTITIES")]
public class Entity {

    [Column("ENTITY_NO")]
    public int No { set; get; }

    [ForeignKey("Sequence")] //Has to be a property name,not table column name
    [Column("SEQUENCE_NO")]
    public int SequenceNo { set; get; }

    public Sequence Sequence { set; get; }

    // and other properties that map correctly
}

[Table("SEQUENCES")]
public class Sequence { 

    [Column("SEQUENCE_NO")]
    public int No { set; get; }

    [Column("NUMBER")]
    public int Number { set; get; }
}
本文链接:https://www.f2er.com/2910664.html

大家都在问