Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework optional:optional relationship

I am trying to set up an Entity Framework model with an optional:optional relationship:

In my situation, sometimes an AdditionalData record exists that points to a BaseTable record, but sometimes BaseTable or AdditionalData records exist without any linkage. The foreign key to the BaseTable (if it exists) is on the AdditionalData table.

I want to be able to navigate back and forth between BaseTable and any AdditionalDatas that might be connected.

BaseTable  0..1 ----- 0..1 AdditionalData1
                 \
                  --- 0..1 AdditionalData2


public class BaseTable {
    public int Id { get; set; }
    public virtual AdditionalType1 AdditionalType1 { get; set; }
    public virtual AdditionalType2 AdditionalType2 { get; set; }
}                  

public class AdditionalType1 {
    public int Id { get; set; }
    public int? BaseTableId { get; set; }
    public virtual BaseTable BaseTable { get; set; }
}

public class AdditionalType2 {
    public int Id { get; set; }
    public int? BaseTableId { get; set; }
    public virtual BaseTable BaseTable { get; set; }
}

How do I make this work? I got as far as:

modelBuilder.Entity<AdditionalType1>()
    .HasOptional(zmt => zmt.BaseTable)
    .WithOptionalDependent(zm => zm.AdditionalType1)
    .Map(a => a.MapKey("BaseTableId"));
modelBuilder.Entity<AdditionalType2>()
    .HasOptional(zmt => zmt.BaseTable)
    .WithOptionalDependent(zm => zm.AdditionalType2)
    .Map(a => a.MapKey("BaseTableId"));

but it tells me this:

error: (1564,6) : error 0019: Each property name in a type must be unique. Property name 'BaseTableId' was already defined.

I don't know exactly what that refers to, and not sure how to fix.

EDIT: If I remove the Map/MapKey clauses as suggested here (https://stackoverflow.com/a/8016308/237091) I get this error instead, when a query runs that uses it:

Invalid column name 'BaseTable_Id' as it maps itself to BaseTable_Id automatically instead of my BaseTableId field.

like image 889
Scott Stafford Avatar asked Jun 27 '13 14:06

Scott Stafford


People also ask

What is HasPrincipalKey?

HasPrincipalKey(Type, String[]) Configures the unique property(s) that this relationship targets. Typically you would only call this method if you want to use a property(s) other than the primary key as the principal property(s).

What is IEntityTypeConfiguration?

IEntityTypeConfiguration<TEntity> InterfaceAllows configuration for an entity type to be factored into a separate class, rather than in-line in OnModelCreating(ModelBuilder).

What is OnModelCreating in Entity Framework?

The DbContext class has a method called OnModelCreating that takes an instance of ModelBuilder as a parameter. This method is called by the framework when your context is first created to build the model and its mappings in memory.

What are the different relationship patterns in Entity Framework?

Entity framework supports three types of relationships, same as database: 1) One-to-One 2) One-to-Many, and 3) Many-to-Many.


1 Answers

It looks like you're trying to set up a 1:0..1 relationship from your AdditionalType objects (which I may have misinterpreted completely.

N.B. I think you would have to hold a BaseTableId on your BaseTable for this to work (or define a primary key):

If BaseTableId is the foreign key in this instance, I think this may be what you're after:

modelBuilder.Entity<AdditionalType1>()
    .HasOptional(zmt => zmt.BaseTable)
    .WithMany()
    .HasForeignKey(a => a.BaseTableId);

Which is what I've used previously, but can't admit to understanding it fully (the .WithMany() trips me up); it's a slight workaround listed in article from this answer: Entity Framework 0..1 to 0 relation)

Apologies if I've missed the point entirely.

like image 126
Chris Avatar answered Oct 23 '22 10:10

Chris