How to configure one to zero and one to one relati

2019-08-02 03:34发布

I am a beginner and learning fluent API from tutorials. I read the some of the already given SO solution about 1-0, 1-* but I could not understand them properly. I simply want to use fluent API to set up One to One and One to Zero Relationship provided no convention followed.

House and Room (terrible example)

Requirement:

1. One House can have zero room or ONE room MAX.
2. One Room must be inside a house.
3. If a room is deleted House SHOULD NOT Get Deleted
4. If a House is getting deleted and there is a room then
  User should first delete the room then only House should be allowed to be deleted.


public class House
{
    public int HouseId { get; set; }
    public string HouseName { get; set; }
    public virtual Room Room { get; set; }
}

public class Room
{
    public int RoomId { get; set; }
    public string RoomName { get; set; }
    public int HouseId { get; set; }
    public virtual House House { get; set; }
}

So, Room cannot exist w/o a House but a House can exist w/o a room. Also, in case if a House has room, it can only have one.

         dBModelBuilder.Entity<House>()
            .HasOptional(f => f.Room)
            .WithRequired(s => s.House);

I saw some solution but they are telling to set the PK and FK same. But I don't want to do that. Is there a way to achieve what I want w/o setting PK and FK same. I DO NOT want the HouseID to be PK of my Room class. Also in my case principal is House and Dependent is Room. Do I need to add soemthing like "Optional Dependent" or "Optional Principal". Can some one please guide me I am a beginner.

Also, Do I need go remove navigation property from any of my MODELS? Is that extraneous?

How to tell EF to use HouseId of Room class as FK.

1条回答
▲ chillily
2楼-- · 2019-08-02 04:10

Also in my case principal is House and Dependent is Room

Then you are on the right track with

modelBuilder.Entity<House>()
    .HasOptional(f => f.Room)
    .WithRequired(s => s.House)

because in EF one-to-one relationship the required side is always the principal. You need to specify the principal/dependent only when both sides are required or both sides are optional.

The problem is your requirement of using different FK in the dependent entity than the PK, which is the default EF model for such relationship (so called Shared Primary Key Association), and is supported well. From the other side, one-to-one FK association is supported, but with some limitations. More specifically, explcit FK property like HouseId in your Room is not supported - there is no HasForeignKey fluent method for this type of configuration, and it's by purpose. I can't say why, but it's a fact. If you try playing with [ForeignKey] attribute, you'll get quite unexpected results, so don't do that.

Remove that property:

public class Room
{
    public int RoomId { get; set; }
    public string RoomName { get; set; }
    public virtual House House { get; set; }
}

and use Map fluent API with MapKey to specify the FK column name:

modelBuilder.Entity<House>()
    .HasOptional(f => f.Room)
    .WithRequired(s => s.House)
    .Map(c => c.MapKey("HouseId"));

This will give you the desired database table design (although there is no way to constrain HouseId column to be unique, except manually editing the migration).

查看更多
登录 后发表回答