I'd like to extend existing relation between two entities without losing the data. That's ASP.NET Core 2.0 Web App.
I've got Cars
and Navs
(GPS sets). Specific Car
could have a specific Nav
and vice versa Specific Nav
could be in a specific Car. However, Nav
could be in a warehouse so it's not in any Car and specific Car could not have any Nav
at the moment. Of course the specific Nav
could be max in 1 car and specific Car could have max 1 Nav.
I've got relation between Navs
and Cars
. I'd like to add also relation between Cars and Nav
s to easily pull from Car level data about Nav
system that's there at the moment (if any).
Now I have following setup:
public class Car
{
public int ID { get; set; }
public string ModelName { get; set; }
//other properties
}
public class Nav
{
public int ID { get; set; }
public decimal ScreenSize { get; set; }
//other properties
public virtual Car Car { get; set; }
}
All I'd like to do is to add to Car
class:
public virtual Nav Nav { get; set; }
But when I run Add-Migration
it drops current relation so if I understand correctly I lose all data I have so far... That's what I get after AddMigration
:
migrationBuilder.DropForeignKey(
name: "FK_Navs_Cars_CarID",
table: "Navs");
migrationBuilder.DropIndex(
name: "IX_Navs_CarID",
table: "Navs");
migrationBuilder.DropColumn(
name: "CarID",
table: "Navs");
migrationBuilder.AlterColumn<int>(
name: "ID",
table: "Navs",
nullable: false,
oldClrType: typeof(int))
.OldAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
migrationBuilder.AddForeignKey(
name: "FK_Navs_Cars_ID",
table: "Navs",
column: "ID",
principalTable: "Cars",
principalColumn: "ID",
onDelete: ReferentialAction.Cascade);
What's the best way to maintain current relation & data and add relation from other side having both optional?
ADDED for clarification:
With current relation I could easily pull data about Car
from Nav
level:
var modelName = nav.Car != null ? nav.Car.ModelName : "";
I'd like to do the same other way too:
var screenSize = car.Nav != null ? car.Nav.ScreenSize : 0;
Before you added this property, EF was actually creating a one-to-many association. By adding this property, you're making it one-to-one. With a one to one, EF must define a principal end and dependent end (in other words, which one gets the foreign key). You can customize this, if you need to, but short of that, EF will make its own choice, and the situation here simply seems to be that it's choosing the opposite end from what you actually want. Therefore, you just need to add some fluent config to be explicit about what you want:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Car>()
.HasOne(p => p.Nav)
.WithOne(p => p.Car)
.HasForeignKey<Nav>("CarID");
}