MJ.Karimkhani
MJ.Karimkhani

Reputation: 41

How to Create one-to-one relationship by non-primary key (EF First Code)

I have two classes 'Car' and 'CarDetails'

 
    public class Car {

        public int Id { get; set; }

        public Guid CarGuid { get; set; }

        public string Name { get; set; }

        public virtual CarDetails CarDetails { get; set; }
    }

    public class CarDetails {

        public int Id { get; set; }

        public Guid CarGuid { get; set; }

        public string Color { get; set; }

        public int Weight { get; set; }

        [ForeignKey("CarGuid")]
        public virtual Car Car { get; set; }
    }

Now, I want to create a relationship between two classes by 'CarGuid', but EF won't allow me to do so, Please help me!

Upvotes: 4

Views: 3327

Answers (1)

danludwig
danludwig

Reputation: 47375

You cannot create a one-to-one (or one-to-zero or one) relationship between two EF entities / SQL tables using a non-primary-key property / column. You have to use primary key columns to achieve this kind of relationship with EF.

public class Car
{
    public int Id { get; set; }

    public Guid CarGuid { get; set; }

    public string Name { get; set; }

    public virtual CarDetails CarDetails { get; set; }
}

public class CarDetails
{
    [Key, ForeignKey("Car")]
    public int Id { get; set; }

    public Guid CarGuid { get; set; }

    public string Color { get; set; }

    public int Weight { get; set; }

    public virtual Car Car { get; set; }
}

With the above relationship, you end up having Car as the principal, and CarDetails as the dependent. By having CarDetails.Id be both the primary key of CarDetails and the foreign key referencing Car.Id, you can ensure that each Car has no more than 1 CarDetails.

However, this is technically not a 1<->1 relationship... it is a 1<->0..1 relationship. This type of model will allow Car objects to exist without any corresponding CarDetils objects.

If you want something closer to a 1<->1 relationship, I believe the only way to do that is with the fluent model builder:

public class CarsDbContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Car>();
        modelBuilder.Entity<CarDetails>()
            .HasRequired(x => x.Car).WithRequiredDependent(x => x.CarDetails)
        ;

        base.OnModelCreating(modelBuilder);
    }
}

With the above definition, you cannot save a Car unless you also save a corresponding CarDetails within the same SaveChanges operation. This is as close to a 1<->1 as entityframework will take you. You can achieve the same thing from the other side of the relationship in a similar way:

public class CarsDbContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Car>()
            .HasRequired(x => x.CarDetails).WithRequiredPrincipal(x => x.Car)
        ;
        modelBuilder.Entity<CarDetails>();

        base.OnModelCreating(modelBuilder);
    }
}

Reference: http://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx

Upvotes: 2

Related Questions