I am dealing with payment devices. The device owners have to obtain terminal IDs (TIDs), which are obtained in bulk, and then associated with a specific device. Therefore, a device may or may not have a TID (but if it has one, can only have one TID), and a Tid may or may not be associated with a device (but if it is, it can only be associated with one device).
Both the Device
and Tid
models already exist, and I want to add the link between them.
I added the navigation properties as follows (all other properties removed for clarity)...
public class Device {
public string? TidId { get; set; }
public virtual Tid? Tid { get; set; }
}
public class Tid {
public string? DeviceId { get; set; }
public virtual Device? Device { get; set; }
}
When I try to add a migration for this, I get an error "The dependent side could not be determined for the one-to-one relationship between 'Tid.Device' and 'Device.Tid'. To identify the dependent side of the relationship, configure the foreign key property. If these navigations should not be part of the same relationship, configure them independently via separate method chains in 'OnModelCreating'. See http://go.microsoft.com/fwlink/?LinkId=724062 for more details."
I tried following the advice in the Microsoft docs, which meant adding the following to the database context...
builder.Entity<Device>()
.HasOne<Tid>()
.WithOne(t => t.Device)
.HasForeignKey<Tid>()
.IsRequired(false);
This added the migration, but when I tried updating the database, I got an error "The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_Tids_Devices_Id". The conflict occurred in database "abc", table "dbo.Devices", column 'Id'."
My guess (perhaps wrong) was that as I had only specified the relationshp in one direction, only one side of the relationship was nullable, whereas I need both sides to be nullable.
So, I added the other side...
builder.Entity<Tid>()
.HasOne<Device>()
.WithOne(d => d.Tid)
.HasForeignKey<Device>()
.IsRequired(false);
However, I couldn't even add a migration for this, as it gave me the error "A relationship cycle involving the primary keys of the following entity types was detected: 'Device -> Tid'. This would prevent any entity to be inserted without violating the store constraints. Review the foreign keys defined on the primary keys and either remove or use other properties for at least one of them."
Anyone able to explain how I set this up? I'm using EF Core 7.0.0 in an ASP.NET Blazor server app if it makes any difference.
You were almost there. What you need to add is an explicit statement of the foreign keys...
builder.Entity<Device>()
.HasOne<Tid>()
.WithOne(t => t.Device)
.HasForeignKey<Tid>(t => t.DeviceId)
.IsRequired(false);
builder.Entity<Tid>()
.HasOne<Device>()
.WithOne(d => d.Tid)
.HasForeignKey<Device>(d => d.TidId)
.IsRequired(false);
I think you should find that will work.