简体   繁体   中英

How to handle primary key in child table which is also primary and foreign key in parent table?

How can I create a relationship in EF core where the child(FullName) table has DrugId which is the primary key. In the parent table(Basic Data), DrugId is foreign key. But there are other child tables and they are also referring DrugId in the parent table as a foreign key. How can I create this relationship in C# ef core? One way is to create one dedicated foreign key column for every child table but it will make duplicate DrugId in the parent table. for example:

Parent Table:

 public int DrugId {get;set;}
 public int FullNameDrugId {get; set;}
 public int DataInfoDrugId {get; set;}
 public int FormCode {get;set;}

FullName Table:

 public int DrugId {get;set;}
 public string name {get;set;}

DataInfo Table:

 public int DrugId {get;set;}
 public string Size {get;set;
 

In the parent table, DrugId and FullNameDrugId, and DataInfoDrugId are the same.

I want to get data from the parent id using LINQ and include the other two tables just adding "Include" statement. I want to navigate from parent table to child. Now how can I deal with this?

Just focus on basic data and fullName table

That looks like a Many-To-One relationship where several BasicData could refer to the same Drug, where the relationship between Drug and other tables like FullName that share the DrugId as a PK would be a One-to-One.

Using explicit mapping for the relationships:

// Drug (EF Core)

modelBuilder.Entity<Drug>(e =>
{
    e.HasOne(x => x.FullName)
        .WithOne()
        .OnDelete(DeleteBehavior.Cascade);
});

// Basic Data

modelBuilder.Entity<BasicData>(e =>
{
    e.HasOne(x => x.Drug)
        .WithMany()
        .IsRequired()
        .HasForeignKey(x => x.DrugId);
});

By default when using HasOne() . WithOne() it will join on the PKs of both tables.

Then to get to the drug's full name from a given BasicData query:

var data = _context.BasicDatas
    .Where( /* criteria */)
    .Select(x => new 
    {
        Id = x.Id,
        DrugId = x.Drug.Id, (Assuming using Id as PK in Drug)
        DrugName = x.Drug.FullName.Text
    }).ToList();

... To get the idea of how to leverage the relationship. If loading the entities themselves then eager load using .Include(x => x.Drug).ThenInclude(x => x.Fullname) (Assuming EF Core)

Well, I would suggest using PKs to reference the other one-to-one related tables so your tables and relation configuration should look like the below:

public class DrugBase
{
 [Key]
 public int DrugId {get;set;}
 public int FormCode {get;set;}

 public virtual DetailInfo DetailInfo {get;set;} // navigation properties
 public virtual DataInfo DataInfo {get;set;} // navigation properties
}

public class DetailInfo
{
 [Key]
 public int DrugId {get;set;} // PK
 public string Name {get;set;}
 
 public virtual DrugBase DrugBase {get;set;} // navigation properties
 // you can add any navigation property that DrugBase entity has
 // This might make it easier to write some queries easier
 // It allows you writing queries that don't reference DrugBase entity
}

public class DataInfo 
{
 [Key]
 public int DrugId {get;set;} // PK
 public string Size {get;set;
 
 public virtual DrugBase DrugBase {get;set;} // navigation properties
}

And you can configure them like below:

builder.Entity<DrugBase>();
            pihd.HasKey(r => r.DrugId);
            pihd.HasOne(r => r.DetailInfo)
               .WithOne(r => r.DrugBase)
               .HasForeignKey<DetailInfo>(r => r.DrugId)
               .HasPrincipalKey<DrugBase>(r => r.DrugId);

builder.Entity<DrugBase>();
            pihd.HasKey(r => r.DrugId);
            pihd.HasOne(r => r.DataInfo)
               .WithOne(r => r.DrugBase)
               .HasForeignKey<DataInfo>(r => r.DrugId)
               .HasPrincipalKey<DrugBase>(r => r.DrugId);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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