I’m learning ASP.NET 6.0 Core Web api,
I have a car model that looks like this
public class Car
{
public int id { get; set; }
public string make { get; set; }
public string model { get; set; }
public int price { get; set; }
public string rentalType { get; set; }
public Specs specs { get; set; }
public string imgSrc { get; set; }
public string info { get; set; }
public Highlights highlights { get; set; }
}
public class Highlights
{
public string ENGINE { get; set; }
public int HORSEPOWER { get; set; }
public string TOPSPEED { get; set; }
public int Gears { get; set; }
}
public class Specs
{
public string transmission { get; set; }
public string fuelType { get; set; }
public int numOfSeats { get; set; }
}
and DbSeeder:
public class Seeder
{
public static List<Car> GetCars() => new List<Car>
{
new Car {
id = 1,
make = "AUDI",
model = "A3",
price = 150,
rentalType = "day",
specs = new Specs {
transmission = "Automatic",
fuelType = "Petrol",
numOfSeats = 5
},
imgSrc = "https://m.atcdn.co.uk/vms/media/0f40778ee8f8402c8cc51fe08eaf2dfd.jpg",
info = "The Audi A3 is a subcompact executive/small family car (C-segment) manufactured and marketed by the German automaker Audi AG since September 1996, currently in its fourth generation.The first two generations of the Audi A3 were based on the Volkswagen Group A platform, while the third and fourth generations use the Volkswagen Group MQB platform.",
highlights = new Highlights {
ENGINE = "2.0L Turbo 2000CC",
HORSEPOWER = 200,
TOPSPEED = "220 Kmh",
Gears = 7
},
},
new Car
{
id = 2,
make = "BMW",
model = "M5",
price = 200,
rentalType = "hour",
specs = new Specs {
transmission = "Automatic",
fuelType = "Petrol",
numOfSeats = 5
},
imgSrc = "https://imgd.aeplcdn.com/0x0/n/cw/ec/50723/m5-exterior-right-front-three-quarter-2.jpeg",
info = "The BMW M5 is a high-performance variant of the BMW 5 Series marketed under the BMW M sub-brand. It is considered an iconic vehicle in the sports sedan category. The majority of M5s have been produced in the sedan (saloon) body style, but in some countries, the M5 was also available as a wagon (estate) from 1992 to 1995 and from 2006 to 2010.",
highlights = new Highlights
{
ENGINE = "4.4L Turbo 4400CC",
HORSEPOWER = 617,
TOPSPEED = "305 Kmh",
Gears = 8
}
},
};
}
DbContextService
public class DbContextService : DbContext
{
public DbContextService(DbContextOptions<DbContextService> options) : base(options) { }
public DbSet<Car> Cars { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Car>(entity =>
{
entity.OwnsOne(c => c.specs);
entity.OwnsOne(c => c.highlights);
});
modelBuilder.Entity<Car>().HasData(Seeder.GetCars());
}
public DbSet<User> Users { get; set; }
}
When I try to Add-Migration I received an error
The seed entity for entity type ‘Car’ cannot be added because it has the navigation ‘highlights’ set. To seed relationships, add the entity seed to ‘Highlights’ and specify the foreign key values {‘Carid’}. Consider using ‘DbContextOptionsBuilder.EnableSensitiveDataLogging’ to see the involved property values.
From my understanding, I need to add some new id and connect them to the cars to which their highlights belong. However, what if I don’t want to introduce an additional key-value pair (for the ID)? Is there a way to accomplish this without doing so? If not, what would be the most efficient way to achieve this? Thanks.
>Solution :
Using HasData with owned types is not so straight forward as it should be.
I’d recommend the following approach:
Add a seed method to your DbContext:
public void SeedData()
{
if (!Cars.Any())
{
Cars.AddRange(Seeder.GetCars());
SaveChanges();
}
}
Then call that method during your application startup.
Alternatively, to use HasData to seed an entity with owned types, you’d need to use an anonymous object representing the column names in the database, e.g.:
modelBuilder.Entity<Car>().HasData(new
{
id = 1,
// other core properties
specs_transmission = "Automatic",
// other specs properties (using the underscore)
highlights_ENGINE = "Petrol",
// other highlights properties (using the underscore)
}