I have several models in this Db,
I am using the following seeding class, and I initialize it at startup using SeedData.Initialize(serviceProvider);
where serviceProvider is injected in the Configure method.
public class SeedData
{
public static void Initialize(IServiceProvider serviceProvider)
{
using (var context = new ArtCoreDbContext(
serviceProvider.GetRequiredService<DbContextOptions<ArtCoreDbContext>>()))
{
// Look for any movies.
if (context.Genders.Any())
{
return; // DB has been seeded
}
context.Genders.AddRange(
new Genders
{
Name = "Male"
},
new Genders
{
Name = "Female"
}
);
context.SaveChanges();
if (context.Statuses.Any())
{
return; // DB has been seeded
}
context.Statuses.AddRange(
new Statuses
{
Name = "Active"
},
new Statuses
{
Name = "Inactive"
},
new Statuses
{
Name = "Cancelled"
}
);
context.SaveChanges();
if (context.PatientsRegistry.Any())
{
return; // DB has been seeded
}
context.PatientsRegistry.AddRange(
new PatientsRegistry
{
PatientFileId = 1234,
FirstName = "John",
SecondName = "M",
LastName = "Doe",
Gender = {Id = 5, Name="Male"},
Status = {Id = 2, Name="Inactive"}
}
);
context.SaveChanges();
}
}
}
and their models are
public class Genders
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Statuses
{
public int Id { get; set; }
public string Name { get; set; }
}
[Table("PatientsRegistry")]
public class PatientsRegistry
{ [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long RecordId { get; set; }
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public long PatientFileId { get; set; }
public string FirstName { get; set; }
public string SecondName { get; set; }
public string LastName { get; set; }
public Genders Gender { get; set; }
public Statuses Status { get; set; }
public ICollection<PartnersRegistry> Partners { get; set; }
public PatientsRegistry()
{
Partners = new Collection<PartnersRegistry>();
}
}
I Succeded in seeding both models (Genders & Statuses) but not PatientsRegistry!, is it the nav. prop?
what am I missing here?
this is the solution, Ref is here, Answered by Edward Z
context.PatientsRegistry.AddRange(
new PatientsRegistry
{
PatientFileId = 1234,
FirstName = "John",
SecondName = "M",
LastName = "Doe",
Gender = context.Genders.Where(g => g.Name == "Male").FirstOrDefault(),
Status = context.Statuses.Where(s => s.Name == "Inactive").FirstOrDefault()
}
);
Another solution is by adding two new prop to PatientsRegistry
along with the Navigation Prop
public int GenderId { get; set; }
public int StatusId { get; set; }
public class Genders
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Statuses
{
public int Id { get; set; }
public string Name { get; set; }
}
[Table("PatientsRegistry")]
public class PatientsRegistry
{ [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long RecordId { get; set; }
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public long PatientFileId { get; set; }
public string FirstName { get; set; }
public string SecondName { get; set; }
public string LastName { get; set; }
public int GenderId { get; set; }
public Genders Gender { get; set; }
public int StatusId { get; set; }
public Statuses Status { get; set; }
public ICollection<PartnersRegistry> Partners { get; set; }
public PatientsRegistry()
{
Partners = new Collection<PartnersRegistry>();
}
}
Now based on this model the fluent API will create a foreign key with a Cascade RI on Delete which sql server does not accept so I change it to
onDelete: ReferentialAction.Restrict);
Now in my seeding class, I can select the Id value as follows (I modified it a bit),
if (!context.PatientsRegistry.Any())
{
context.PatientsRegistry.AddRange(
new PatientsRegistry
{
PatientFileId = 1234,
FirstName = "John",
SecondName = "M",
LastName = "Doe",
GenderId = 1,
StatusId = 2
}
);
context.SaveChanges();
}
Add PatientsRegistry
to Genders
and Statuses
:
public class Genders
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<PatientsRegistry> PatientsRegistries { get; set; }
}
public class Statuses
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<PatientsRegistry> PatientsRegistries { get; set; }
}
then inside method OnModelCreating
in ArtCoreDbContext
class add following configs:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Genders>().HasMany(g => g.PatientsRegistries).WithOne(p => p.Gender);
modelBuilder.Entity<Statuses>().HasMany(g => g.PatientsRegistries).WithOne(p => p.Status);
base.OnModelCreating(modelBuilder);
}
change you seed class to:
public class SeedData
{
public static void Initialize(IServiceProvider serviceProvider)
{
using(var context = new ArtCoreDbContext(serviceProvider.GetRequiredService<DbContextOptions<ArtCoreDbContext>>())))
{
if (context.Genders.Any() && context.Statuses.Any() && context.PatientsRegistries.Any())
return; // DB has been seeded
var g1 = new Genders { Name = "Male" };
var g2 = new Genders { Name = "Female" };
context.Genders.AddRange(new[] { g1, g2 });
var s1 = new Statuses { Name = "Active" };
var s2 = new Statuses { Name = "Inactive" };
var s3 = new Statuses { Name = "Canceled" };
context.Statuses.AddRange(new[] { s1, s2, s3 });
context.PatientsRegistries.AddRange(
new PatientsRegistry
{
PatientFileId = 1234,
FirstName = "John",
SecondName = "M",
LastName = "Doe",
Gender = g1,
Status = s1
},
new PatientsRegistry
{
PatientFileId = 1235,
FirstName = "Julia",
SecondName = "M",
LastName = "Doe",
Gender = g2,
Status = s2
}
);
context.SaveChanges();
}
}
}