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

How can I set the foreign key name using the Fluent API with Code First Migrations?(如何使用 Fluent API 和 Code First 迁移设置外键名称?)

本文介绍了如何使用 Fluent API 和 Code First 迁移设置外键名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我知道可以通过更新生成的迁移代码来设置,像这样:

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

...但我想在添加迁移之前使用 Fluent API 执行此操作.

我似乎记得关于 HasForeignKey() 调用接受 Func 的一些事情,该调用在其主体中包含对匿名类型的调用,例如我们发现 这里.但是,如果我能找到任何讨论该类型的一般结构应该是什么的东西,我会被诅咒的.

官方文档没有讨论:

  • 带有 VB.NET 的 Fluent API
  • HasForeignKey(TKey)

这些类似的问答也没有完全解决这个问题:

  • EF Code First Fluent API 指定外键属性
  • Entity Framework Code First Mapping Foreign Key Using Fluent API
  • 先指定外键实体框架代码,Fluent Api

几个月前此处提出了同样的问题,但到目前为止还没有得到答复.p>

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

命名空间配置朋友类SectionConfig继承 EntityTypeConfiguration(Of Db.Section)公共子新()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(函数(Section) Section.Subject)结束子结束类结束命名空间

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

--更新--

我试过了:

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 指定外键名称?

解决方案

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

这已在 EFCore 中得到纠正,您现在可以执行以下操作:Me.HasRequired(Function(Section) Section.Document).WithMany().HasForeignKey(Function(Section) Section.DocumentId).HasConstraintName("FK_Sections_Documents") 但这对你没有帮助.

因此,您需要编写一个自定义迁移生成器来满足您的需求.在这篇文章中回答了这个确切的问题(C# 中的代码,数据库是 SQL Server):更改外键约束命名约定

I'm trying to set the foreign key name (not the foreign key column) using Code First Migrations on EF6.4.

I know that it can be set by updating the generated migration code, like so:

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

...but I'd like to do it before the migration is added, using the Fluent API.

I seem to recall something about the HasForeignKey() call accepting a Func that contains a call to an anonymous type in its body, such as what we find here. But I'll be darned if I can locate anything discussing what the general structure of that type should be.

The official documentation doesn't discuss it:

  • Fluent API with VB.NET
  • HasForeignKey(Of TKey)

Nor do these similar Q&As quite exactly address the issue:

  • EF Code First Fluent API specifying the Foreign Key property
  • Entity Framework Code First Mapping Foreign Key Using Fluent API
  • Specifying Foreign Key Entity Framework Code First, Fluent Api

This same question was asked a couple of months ago here, but so far it hasn't received an answer.

I'm using EntityTypeConfiguration(Of T). Here's my code:

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

How does one set a foreign key name, or—even more specific, assuming I'm remembering correctly—what should be the general structure of that anonymous type?

--UPDATE--

I tried this:

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

...but a migration creation attempt answered with this:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: The properties expression 'Section => new VB$AnonymousType_0`2(DependentKeyExpression = Section.DocumentId, Name = "FK_Sections_Documents")' is not valid. The expression should represent a property: C#: 't => t.MyProperty' VB.Net: 'Function(t) t.MyProperty'. When specifying multiple properties use an anonymous type: C#: 't => new { t.MyProperty1, t.MyProperty2 }' VB.Net: 'Function(t) New With { t.MyProperty1, t.MyProperty2 }'.

So, given that the anonymous type construct is for specifying the key column(s), it's not the way to specify a foreign key name.

The question still stands: How may we specify the foreign key name using the Fluent API in EF6.4?

解决方案

Unfortunately, in EF6 there is no built-in way to do this. To clarify your question a little, What you are asking is how to specify the name of the underlying database constraint that is created based on the foreign key specified in your model. This would be a job for the migration generator. Though the functionality is there in EF6 migrations to pass a constraint name, If you explore the source code you'll see it is never actually used, and all of the methods are private and internal.

This was recitfied in EFCore where you can now do: Me.HasRequired(Function(Section) Section.Document).WithMany().HasForeignKey(Function(Section) Section.DocumentId).HasConstraintName("FK_Sections_Documents") but that doesn't help you.

So what you need is to write a custom migration generator that will do what you want. This exact question was answered (code in C#, database is SQL Server) in this post: Change foreign key constraint naming convention

这篇关于如何使用 Fluent API 和 Code First 迁移设置外键名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:如何使用 Fluent API 和 Code First 迁移设置外键名称?

基础教程推荐