jdl134679 jdl134679 - 1 month ago 15
C# Question

EF6 FluentAPI, 0:1 Unidirectional

I've spent the last three hours trying to figure this out and finally gave up (I'll work around it). But... just to be sure... is there no way to set up a unidirectional 0:1/1:1 in EF6 Fluent API?

Consider:

CREATE TABLE LegacyUsers (
ID INT NOT NULL PRIMARY KEY,
UserName NVARCHAR(50),
EmployeeID INT NULL
)

CREATE TABLE Employees (
ID INT NOT NULL PRIMARY KEY,
EmployeeName NVARCHAR(50)
)


Domain Models:

public class LegacyUser {
public int ID {get;set;}
public int? EmployeeID {get;set;}
public virtual Employee Employee {get;set;}
}

public class Employee {
public int ID {get;set;}
public string EmployeeName {get;set;}
}


"Fluent" (haha) API theoretical setup:

modelBuilder.Entity<LegacyUser>()
.HasOptional(x => x.Employee)
.WithForgeignKey(x => x.EmployeeID)


I've researched for hours and tried any number of ways to configure this. For my efforts I've been rewarded with "column name already exists" validation errors or "invalid column: Employee_ID" errors (of these which I could fix easily enough had this been bidirectional, but this is a more or less locked schema). The only thing that I've found that would force it to work is to try it as a 1:M relationship, which throws off the whole "fluency" by having to use the domain model property as a collection rather than a simple, single property.

Is there really no way to do this as easily as I seem to think there should be? The requirement is very simple: get the associated employee object given the employee ID on file for the legacy user (without having to mangle the models or add new fields to the database)

(for reference):

One to zero-or-one with HasForeignKey

Unidirectional One-To-One relationship in Entity Framework

Answer

The only thing that I've found that would force it to work is to try it as a 1:M relationship, which throws off the whole "fluency" by having to use the domain model property as a collection rather than a simple, single property.

This is indeed the only way to setup such relationship as described in Associations in EF Code First: Part 5 – One-to-One Foreign Key Associations. But you are misreading the unidirectional part. Luckily the "uni" part is the single navigation property at the dependent side - exactly where the foreign key property exists.

So your model is ok, you just need to set it up like this:

modelBuilder.Entity<LegacyUser>()
    .HasOptional(e => e.Employee)
    .WithMany()
    .HasForeignKey(e => e.EmployeeID)
    .WillCascadeOnDelete(false);

The essential part is the parameterless WithMany call.