I'm working in my project with entity that use value objects, I have read in the doc that if you want work with value objects you must use owned types. When I save my entity with its repository this work perfectly, but when I try to load data this doesn't work, it only load my ID value object but not the others
this is my context
public class WikiContext : DbContext
{
private string _sConnection;
#region Constructs
public WikiContext()
{
}
public WikiContext(string sConnection)
{
_sConnection = sConnection;
}
#endregion
#region Entities
public DbSet<Customer> Customers{ get; set; }
#endregion
#region Mapping
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(_sConnection);
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new CustomerConfiguration());
base.OnModelCreating(modelBuilder);
}
#endregion
}
this is my CustomerConfiguration:
public class CustomerConfiguration : IEntityTypeConfiguration<Customer>
{
public void Configure(EntityTypeBuilder<Customer> builder)
{
// https://stackoverflow.com/questions/49607375/ef-core-dbcontext-map-custom-type-as-primary-key
// http://thedatafarm.com/data-access/entity-framework-private-constructors-and-private-setters/
builder.ToTable("Customers");
builder.HasKey(customer=> new { customer.Id });
builder
.Property<CustomerId>("Id")
.HasConversion(id => id.Value, guid => new CustomerId(guid));
// https://www.edgesidesolutions.com/ddd-value-objects-with-entity-framework-core/
builder.OwnsOne(c => c.Name, a =>
{
a.Property(p => p.Value).HasColumnName("Name");
a.WithOwner();
});
builder.OwnsOne(c => c.StudioId, a =>
{
a.Property(p => p.Value).HasColumnName("StudioId").HasColumnType("uniqueidentifier");
a.WithOwner();
});
}
}
and this is my customer repository method
public Customer[] Search()
{
var customers = Context.Customers.Select(customer=> customer);
return customers.ToArray();
}
I can do a workaround with the next model configuration, but I still have doubt about this way
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Customer>(builder =>
{
builder.ToTable("Customers");
builder.HasKey(customer => new { customer.Id });
builder
.Property<CustomerId>("Id")
.HasConversion(id => id.Value, guid => new CustomerId(guid));
builder
.Property<CustomerName>("Name")
.HasColumnName("Name")
.HasConversion(name => name.Value, value => new CustomerName(value));
builder
.Property<StudioId>("StudioId")
.HasColumnName("StudioId")
.HasConversion(p => p.Value, value => new StudioId(value));
});
base.OnModelCreating(modelBuilder);
}
#endregion
this is the Customer Entity
public class Customer: IAggregateRoot
{
#region Constructors
private Customer()
{
}
public Customer(CustomerId oId, CustomerName oCustomerName, StudioId oStudioId)
{
Id = oId;
Name = oCustomerName;
StudioId = oStudioId;
}
#endregion
#region Public Methods
public static Customer Create(CustomerId oId, CustomerName oName, StudioId oStudioId)
{
var oCustomer = new Customer(oId, oName, oStudioId);
//TODO: implement event sourcing here
return oCustomer;
}
#endregion
#region Property
public CustomerId Id { get; set; }
public CustomerName Name { get; set; }
public StudioId StudioId { get; set; }
#endregion
}
public class CustomerName
{
public string Value { get; set; }
#region Constructors
private CustomerName()
{
}
public CustomerName(string sName)
{
Value = sName;
}
#endregion
}
I can't figure out where the problem is, I tryed several model configuration but still I can understand why this doesn't works.
I'm using EntityFrameworkCore 5.0.1 with SQL Server and .Net Core 3.1
This was answered in the official EFCore's github repository, here a link to the answer answer