I have 3 models with fields in it like the following:
public class RootObject
{
[Key]
public int RootObjectId { get; set; }
[ForeignKey("RootObjectId")]
public virtual AObject AObject { get; set; }
[ForeignKey("RootObjectId")]
public virtual BObject BObject { get; set; }
public string Name { get; set; }
}
public class AObject
{
[Key]
public int AObjectId { get; set; }
//Other fields
}
public class BObject
{
[Key]
public int BObjectId { get; set; }
//Other fields
}
I want it so that if I were to visually inspect the RootObject
table I would see see a list of RootObjectId
's and Name
's. For ease, lets assume even numbered RootObjectId
's are mapped to AObjectId
's and odds are mapped to BObjectId
's. If I were to visually inspect AObject
, I would expect to see the ID's 2, 4, 6, ... that are FK's for RootObject
. If were to visually inspect BObject
, I would expect to see the ID's 1, 3, 5, ... that are FK's for RootObject
.
Currently, when I try this approach I get the following error:
"An error occurred while updating the entries...Referential integrity constraint violations. A Dependent Role has multiple principals with different values."
I tried to remove the FK attributes in RootObject
but that created 2 additional columns in RootObject
that were populated with ID numbers. I don't want this since every RootObject
has either one AObject
or one BObject
. It can't have both.
To me, you are looking for something for which the TPT (Table per Type) approach in Entity Framework could be a solution. Applied to your case (there are many approaches, but this I tested and it works):
public class RootObject
{
[Key]
public int RootObjectId { get; set; }
public string Name { get; set; }
}
[Table("AObjects")]
public class AObject : RootObject
{
//Other fields
public string AField { get; set; }
}
[Table("BObjects")]
public class BObject : RootObject
{
//Other fields
public string BField { get; set; }
}
For the DbContext class:
public DbSet<RootObject> RootObjects { get; set; }
public DbSet<AObject> AObjects { get; set; }
public DbSet<BObject> BObjects { get; set; }
Seed example:
AObject a1 = new AObject() { Name = "ImA", AField = "adata" };
BObject b1 = new BObject() { Name = "ImB", BField = "bdata" };
context.AObjects.Add(a1);
context.BObjects.Add(b1);
context.SaveChanges();
I don't think it is possible to use ONE column to be a foreign key to two different tables. You should rather think of two (optional) FK like:
public class RootObject
{
[Key]
public int RootObjectId { get; set; }
public int? EvensAObjectId { get; set; }
public int? OddsBObjectId { get; set; }
[ForeignKey("EvensAObjectId")]
public virtual AObject AObject { get; set; }
[ForeignKey("OddsBObjectId")]
public virtual BObject BObject { get; set; }
public string Name { get; set; }
}
To set up 1-0..1 relationships you need to define the relationships explicitly during model configuration.
public class Model1 : DbContext
{
public Model1()
: base("name=Model1")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<AObject>()
.HasRequired(e => e.RootObject).WithOptional(r => r.AObject);
modelBuilder.Entity<BObject>()
.HasRequired(e => e.RootObject).WithOptional(r => r.BObject);
base.OnModelCreating(modelBuilder);
}
public virtual DbSet<RootObject> RootObjects { get; set; }
public virtual DbSet<AObject> AObjects { get; set; }
public virtual DbSet<BObject> BObjects { get; set; }
}
public class RootObject
{
[Key]
public int RootObjectId { get; set; }
public virtual AObject AObject { get; set; }
public virtual BObject BObject { get; set; }
public string Name { get; set; }
}
public class AObject
{
[Key]
public int AObjectId { get; set; }
public virtual RootObject RootObject { get; set; }
}
public class BObject
{
[Key]
public int BObjectId { get; set; }
public virtual RootObject RootObject { get; set; }
}
You'll want to be really careful when setting RootObject.AObject
and RootObject.BObject
, as if there is already a related row you will get an error when you save. Also, I don't think there's any way to get EF enforce the constraint that each RootObject must have either an AObject or a BObject, but not both - you'd need to enforce that in your code.
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.