Reputation: 23
I'm trying to model an entity with a complex value object.
The database structure could be something similar to this:
+-------------------------------------+
| car |
+----------------------+--------------+
| id | CHAR(40) |
+----------------------+--------------+
| model | VARCHAR(255) |
+----------------------+--------------+
| specs_engine_version | VARCHAR(255) |
+----------------------+--------------+
| specs_lighting | VARCHAR(255) |
+----------------------+--------------+
+------------------------------------+
| specs_interior_equipment |
+-----------------------+------------+
| car_id | CHAR(40) |
+-----------------------+------------+
| interior_equipment_id | INT(11) |
+-----------------------+------------+
This is the Car
entity:
public class Car : IEntity<Guid>
{
public Guid Id { get; private set; }
public string Model { get; private set; }
public Specs Specs { get; set; }
public Car()
{ }
}
This is the Specs
value object:
public class Specs : ValueObject<Specs>
{
public string EngineVersion { get; private set; }
public string Lighting { get; private set; }
public List<int> InteriorEquipment { get; private set; }
public Specs()
{}
}
I'm configuring the mappings more or less like this:
class CarMap : IEntityTypeConfiguration<Car>
{
public void Configure(EntityTypeBuilder<Car> builder)
{
builder.HasKey(t => t.Id);
builder.ToTable("car");
builder.Property(e => e.Id).HasColumnName("id");
builder.Property(e => e.Name).HasColumnName("name");
builder.OwnsOne(j => j.Specs, l =>
{
l.Property(t => t.EngineVersion).HasColumnName("specs_engine_version");
l.Property(t => t.Lighting).HasColumnName("specs_lighting");
});
}
}
The question is: how should I configure the mappings in order to persist the interior equipment in a separate table?
I know I can define the interior equipment as an object an use something like this:
builder
.HasMany(j => j.InteriorEquipment)
.WithOne()
.HasForeignKey(t => t.CarId)
.OnDelete(DeleteBehavior.Cascade)
.Metadata.PrincipalToDependent.SetPropertyAccessMode(PropertyAccessMode.Field);
but I don't know how to join all pieces...
Could you help me?
Upvotes: 1
Views: 371
Reputation: 23
I found a solution to keep table splitting by using an object to represent an equipment.
This is the mapping configuration:
class CarMap : IEntityTypeConfiguration<Car>
{
public void Configure(EntityTypeBuilder<Car> builder)
{
builder.HasKey(t => t.Id);
builder.ToTable("car");
builder.Property(e => e.Id).HasColumnName("id");
builder.Property(e => e.Name).HasColumnName("name");
builder.OwnsOne(j => j.Specs, l =>
{
l.Property(t => t.EngineVersion).HasColumnName("specs_engine_version");
l.Property(t => t.Lighting).HasColumnName("specs_lighting");
l.OwnsMany(x => x.InteriorEquipment, x =>
{
x.HasKey(t => t.Id);
x.WithOwner().HasForeignKey("CarId");
x.ToTable("specs_interior_equipment");
x.Property(j => j.Id).HasColumnName("id");
x.Property(j => j.CategoryId).HasColumnName("equipment_id");
x.Property(j => j.CarId).HasColumnName("car_id");
});
});
}
}
and this is the equipment object:
public class Equipment: TEntity<Guid>
{
private Equipment() { }
public Equipment(Guid carId, int equipmentId)
{
Id = Guid.NewGuid();
CarId = carId;
EquipomentId = equipmentId;
}
public Guid Id { get; internal set; }
public Guid CarId { get; internal set; }
public int EquipmentId { get; internal set; }
}
Upvotes: 0
Reputation: 21
Marc
I think in your case you need a separated class to build the table specs, this should be not done in the car class Something like:
class SpecMap : IEntityTypeConfiguration<Spec>
then you can add a function in your repository calls to retrieve all the info.
Here I post you how we resolve this in InfoJobs, hope it helps you.
Class Candidate Points to CandidateResumeDeficiencies, so Candidate could have a list of CandidateResumeDeficiencies.
-> The CandidateResumeClass
public class CandidateResume : BaseEntity, IAggregateRoot { #region .: Properties :.
public int IdCandidateResume { get; protected set; }
public int IdCandidate { get; protected set; }
....
}
-> The Deficiency class
public class CandidateResumeDeficiency
{
public int IdCandidateResumeDeficiency { get; private set; }
public int IdCandidateResume { get; private set; }
public int IdDeficiency1 { get; private set; }
...
}
-> The builder
class CandidateEntityTypeConfiguration : IEntityTypeConfiguration<Candidate>
{
public void Configure(EntityTypeBuilder<Candidate> builder)
{
builder.ToTable("candidates", EFContext.DbSchema.candidate.ToString());
builder.HasKey(b => b.IdCandidate);
builder.HasAlternateKey(b => new { b.IdCompany, b.Email });
}
}
class CandidateResumeDeficiencyEntityTypeConfiguration : IEntityTypeConfiguration<CandidateResumeDeficiency>
{
public void Configure(EntityTypeBuilder<CandidateResumeDeficiency> builder)
{
builder.ToTable("candidateresumedeficiencies", EFContext.DbSchema.candidate.ToString());
builder.HasKey(b => b.IdCandidateResumeDeficiency);
}
}
-> The Repository
public class CandidateResumeRepository : EFRepository<CandidateResume, int>, ICandidateResumeRepository
{
public CandidateResumeRepository(EFContext dbContext) : base(dbContext)
{
}
public async Task<CandidateResume> GetFullAsync(int idCandidateResume) =>
await ((EFContext)_dbContext).CandidateResumes
.Include(c => c.Deficiencies)
.FirstOrDefaultAsync(c => c.IdCandidateResume == idCandidateResume);
}
Upvotes: 2