Reputation: 43
I'm learning C# at the moment with .NET Core and EF Core for working with database.
Now I'm at the point where I got stuck configuring my entities.
I have written the following classes:
public class Customer
{
#region Properties
public Guid CustomerID { get; set; }
...
public Address Address { get; set; }
#endregion
public Customer()
{
Address = new Address();
}
}
public class CustomerConfiguration : IEntityTypeConfiguration<Customer>
{
public void Configure(EntityTypeBuilder<Customer> builder)
{
//Primary Key
builder.HasKey(c => c.CustomerID);
//Complex Types
builder.OwnsOne<Address>("Address");
}
}
public class Employee
{
#region Properties
public Guid EmployeeID { get; set; }
...
public Address Address { get; set; }
#endregion
public Employee()
{
Address = new Address();
}
}
public class EmployeeConfiguration : IEntityTypeConfiguration<Employee>
{
public void Configure(EntityTypeBuilder<Employee> builder)
{
//Primary Key
builder.HasKey(c => c.EmployeeID);
//Complex Types
builder.OwnsOne<Address>("Address");
}
}
public class Address
{
public string Street { get; set; }
public string ZipCode { get; set; }
public string City { get; set; }
public State State { get; set; }
public Country Country { get; set; }
}
I need to configure Address
class with Fluent API that Address.Street
is for Customer
and Employee
MaxLength = 50?
Is it possible to configure it for both at the same time? Or do I need to configure it for each entity?
Thanks for your help!
Upvotes: 4
Views: 2782
Reputation: 5254
The valid answer of @Gert Arnold demonstrates, how to accomplish what you want for all of your target entities in a centralized way.
In case you want to keep the information in your configuration classes, then you can define it there instead (but it could be a bit more redundant, depending on the case):
public class CustomerConfiguration : IEntityTypeConfiguration<Customer>
{
public void Configure(EntityTypeBuilder<Customer> builder)
{
//Primary Key
builder.HasKey(c => c.CustomerID);
//Complex Types
builder.OwnsOne(e => e.Address)
.Property(e => e.Street)
.HasMaxLength(50);
}
}
public class EmployeeConfiguration : IEntityTypeConfiguration<Employee>
{
public void Configure(EntityTypeBuilder<Employee> builder)
{
//Primary Key
builder.HasKey(c => c.EmployeeID);
//Complex Types
builder.OwnsOne(e => e.Address)
.Property(e => e.Street)
.HasMaxLength(42); // or 50 if you want
}
}
Upvotes: 2
Reputation: 109255
You can set all kinds of attributes of model types at once because they're easily accessible by modelBuilder.Model.GetEntityTypes()
. Setting max length of owned type properties can be done like so:
var ownedAddresses = modelBuilder.Model.GetEntityTypes()
.Where(t => t.IsOwned() && t.ClrType == typeof(Address))
.ToList();
foreach (var address in ownedAddresses)
{
address.FindProperty("Street").SetMaxLength(50);
}
...after the owned types have been registered to the model builder, i.e. after you added the type configurations.
Of course, the Where(t => t.IsOwned()
predicate is redundant here. It's just to show another way to find owned types.
Upvotes: 1
Reputation: 1711
Until the current stable version of Entity Framework Core (3.1.6) this is not possible. Quote:
Instances of owned entity types cannot be shared by multiple owners (this is a well-known scenario for value objects that cannot be implemented using owned entity types)
Source: https://learn.microsoft.com/en-us/ef/core/modeling/owned-entities#current-shortcomings.
Your only option here would be to make Address
an Entity itself with its own table.
Then you would have an many-to-one relation from Customer
/ Employee
(many) to Address
(one).
For this you would have to extend your Address
with a primary key and Customer
and Employee
with a foreign key each referencing Address
. Then as you would do normally you can create a TypeConfiguration with your validation rules.
Upvotes: -1