IT:AD:EF/CodeFirst/Entities/ComplexTypes
- See:
Summary
Complex Types are simply a way of Logically grouping db fields together so that they are easier to manipulate.
An example would be:
public class User { public int Id { get; set; } public string First {get; set; } ... //Refer to a ComplexType (not same as a 1-1 relationship) //MUST: Cannot be marked Virtual to lazy load it: public Address Address { get; set; } public User { //MUST: Will be required to be non-null before Saving, so factory up early: Address = new Address(); } } public class Address { //MUST: no Id Property. //MUST: all properties are Scalar (not collections) public string Street { get; set; } ... }
Although they are represented on screen as two distinct objects (albeit 1-1 relationship), they are saved to Db as
User [Id,First,…,AddressStreet,Address…]
Design Checklist
- MUST: No PK can be inferred, or defined via FluentAPI.
- MUST: Only Scalar Properties (ie: no navigation properites to other Entities|Collections)
- MUST: Not Referenced in an
ICollection
from anywhere. - MUST: Not marked as Virtual.
- MUST: Required before saving.
- Therefore, when Constructing/Factoring up
User
, setAddress = new Address();
before Add/Saving.
- COULD: If it needs to be forced (eg: the class has an Id), can be forced as follows:
- using Attributes:
[ComplexType]
- using Fluent API within OnModelCreating():
Example:
modelBuilder.ComplexType<Address>();
* COULD: If we need to remap fields from default (Address_Street
) use one of the following:
- using Attributes:
[Column]
- using Fluent API within
DbContext.OnModelCreating()
:
Example:
`modelBuilder.ComplexType<Address>().Property(a=>a.Street).HasColumnName("Street");` `modelBuilder.Entity<Customer>().Property(c => c.Address.Street).HasColumnName("Customer_Street");`