简体   繁体   English

如何使用EF fluentApi并设置具有2个不同外键的复合键的类?

[英]How to use EF fluentApi and set a class with composite key of 2 different foreign keys?

I've found some similar questions here, but none were aswered with something that would work for me. 我在这里找到了一些类似的问题,但是没有一个问题对我有用。

I have a project with about 60 entities with lots of scenarios, all mapped to the database by the simple use of some basic EF annotations. 我有一个包含大约60个实体的项目,其中包含许多场景,所有这些都通过简单使用一些基本的EF注释映射到数据库。 One scenario that I couldn't put to work, is the following: 我无法使用的一种情况是:

public class Client {
  [Key]
  public int IDClient { get; set; }
  (...)
}

public class Research {
  [Key]
  public int IDReasearch { get; set; }
  (...)
}

public class ClientReaserach {
  [Key, Column(Order = 1)]
  public int IDClient { get; set; }
  [ForeignKey("IDClient")]
  public virtual Client Client { get; set; }

  [Key, Column(Order = 2)]
  public int IDResearch { get; set; }
  [ForeignKey("IDResearch")]
  public virtual Research Research { get; set; }

  (...)
}

Although this seems like other scenarios that worked so far, this one seems to me like a fluentAPI kind of thing (as far as I know, annotations only gives me a sub-set of EF's real capacities). 尽管到目前为止似乎还可以使用其他方案,但在我看来,这似乎是一种fluentAPI(据我所知,注释仅提供了EF实际功能的子集)。

So I have some questions: 所以我有一些问题:

  • Can I remain using my annotations and use fluentAPI to map only the situation described above? 我可以继续使用我的注释并使用fluentAPI来仅映射上述情况吗?

  • How will EF "knows" that this entities and its relationships are mapped through the fluentAPI (and not try to map them again when I add a new migration)? EF将如何“知道”此实体及其关系是通过fluentAPI映射的(在添加新迁移时不尝试再次映射它们)?

  • Is it OK to rebuild all my project using fluentAPI? 可以使用fluentAPI重建我的所有项目吗? What should I do withh all the migrations already generated (should I just delete them)? 我应该如何处理所有已经生成的迁移(我应该删除它们)?

  • How would I accomplish the above scenario through fluentAPI? 我将如何通过fluentAPI完成上述方案?

EDIT 1: 编辑1:

This is the real code that I'm using to accomplish the scenario mentioned, is the following: 这是我用来完成上述方案的真实代码,如下所示:

public class PacientePesquisa
{
    [Key, Column(Order = 1)]
    [Required(ErrorMessage = Msg_Critica_Req_IDPesquisa)]
    [Display(Name = "Pesquisa")]
    public int IDPesquisa { get; set; }

    [ForeignKey("IDPesquisa")]
    public virtual Pesquisa Pesquisa { get; set; }

    [Key, Column(Order = 2)]
    [Required(ErrorMessage = Msg_Critica_Req_NRProntuario)]
    [StringLength(NRProntuario_MaxLength, ErrorMessage = Msg_Critica_Tam_NRProntuario)]
    [Display(Name = "Prontuário")]
    public string NRProntuario { get; set; }

    [ForeignKey("NRProntuario")]
    public virtual Paciente Paciente { get; set; }

    (...)


public class Pesquisa 
{
    [Key]
    public int IDPesquisa { get; set; }

    (...)

public class Paciente 
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public string NRProntuario { get; set; }

    (...)

And when running the "add-migration", I'm receiving the following error: 并且在运行“ add-migration”时,我收到以下错误:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Data.Entity.ModelConfiguration.ModelValidationException: One or more validation errors were detected during model generation:

System.Data.Entity.Edm.EdmAssociationConstraint: : The number of properties in the Dependent and Principal Roles in a relationship constraint must be identical.        

I'll try to answer your questions, but one question up front: What is the problem with your mapping with annotations? 我将尝试回答您的问题,但首先要回答一个问题:带注释的映射有什么问题? It looks fine to me and I don't see a need for Fluent API. 对我来说看起来不错,我认为不需要Fluent API。 In this answer is a similar model ("many-to-many relationship with payload") and it uses annotations and mapping conventions exclusively without any Fluent API mapping. 这个答案中,有一个类似的模型(“与有效负载的多对多关系”),它仅使用注释和映射约定,而没有任何Fluent API映射。

About your questions: 关于您的问题:

Can I remain using my annotations and use fluentAPI to map only the situation described above? 我可以继续使用我的注释并使用fluentAPI来仅映射上述情况吗?

Yes, you can mix mapping via data annotations and via Fluent API without problems - as long as you don't create contradicting mappings, like renaming a column with annotations to a different name than with Fluent API. 是的,您可以通过数据注释和Fluent API混合使用映射而不会出现问题-只要您不创建矛盾的映射即可,例如将带有注释的列重命名为与Fluent API不同的名称。

How will EF "knows" that this entities and its relationships are mapped through the fluentAPI (and not try to map them again when I add a new migration)? EF将如何“知道”此实体及其关系是通过fluentAPI映射的(在添加新迁移时不尝试再次映射它们)?

EF processes the OnModelCreating method of your context and applies the mapping you have defined. EF处理上下文的OnModelCreating方法并应用您定义的映射。 It also processes the annotations and applies the mappings defined there. 它还处理注释并应用在此定义的映射。 It merges both mappings to a single model. 它将两个映射合并为一个模型。 This model is serialized to a "model hash" that is stored in the MigrationHistory table in your database. 该模型被序列化为存储在数据库的MigrationHistory表中的“模型哈希”。 If the model hash is identical with the latest already stored hash value EF knows that model and database are in sync and up-to-date and doesn't create a new migration. 如果模型哈希与已经存储的最新哈希值相同,EF就会知道模型和数据库是同步且最新的,并且不会创建新的迁移。

Is it OK to rebuild all my project using fluentAPI? 可以使用fluentAPI重建我的所有项目吗? What should I do withh all the migrations already generated (should I just delete them)? 我应该如何处理所有已经生成的迁移(我应该删除它们)?

Yes, it's OK. 好的,可以。 There is no need to delete the old migrations. 无需删除旧的迁移。 Adding a new mapping with Fluent API is just a new evolution of your entity model - like adding new annotations is. 使用Fluent API添加新映射只是实体模型的新改进-就像添加新注释一样。

How would I accomplish the above scenario through fluentAPI? 我将如何通过fluentAPI完成上述方案?

modelBuilder.Entity<ClientResearch>()
    .HasKey(cr => new { cr.IDClient, cr.IDResearch });

modelBuilder.Entity<ClientResearch>()
    .HasRequired(cr => cr.Client)
    .WithMany() // or .WithMany(c => c.ClientResearches) if you have a collection
    .HasForeignKey(cr => cr.IDClient);

modelBuilder.Entity<ClientResearch>()
    .HasRequired(cr => cr.Research)
    .WithMany() // or .WithMany(r => r.ClientResearches) if you have a collection
    .HasForeignKey(cr => cr.IDResearch);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM