EF Core does not support Complex types mapping.
If I had an object such as:
public class Entity {
public string StringProp {get; set;}
public SubEntity NestedEntity {get; set;}
}
where SubEntity is :
public class SubEntity{
public int IntProp {get; set;}
}
How could I map this to a table that has columns for StringProp and IntProp. Basically one record in the table is composed of the properties of both Entity and SubEntity.
I've tried ignoring SubEntity and exposing it's properties in Entity but that doesn't work because when NestedEntity is ignored any properties on Entity using its properties have no values.
Is there any other option than creating a class that has all the properties of the complex type or refactoring the database?
I have decided to go with a class that contains all the relevant properties and maps to all the required table columns. It works fine as a workaround. Will update when there is support for complex types in EF Core.
ComplexType mappings are now available since EF Core 2.0. There are currently two ways to do this that I am aware of.
Via Attributes
Not specifying the Column attribute may cause Entity Framework to not map properties to the correct column in existing tables without migrations.
e.g., it may map to Address_StreetAddress
using System.ComponentModel.DataAnnotations.Schema;
public class User
{
public int Id { get; set; }
// The complex property we want to use
public Address Address { get; set; }
public string UserName{ get; set; }
}
// Lets Entity Framework know this class is a complex type
[ComplexType]
public class Address
{
// Maps the property to the correct column name
[Column("Address")]
public string StreeAddress { get; set; }
[Column("City")]
public string City { get; set; }
[Column("State")]
public string State { get; set; }
[Column("Zip")]
public string ZipCode { get; set; }
}
Via Fluent API
Not specifying the HasColumnName may cause Entity Framework to not map properties to the correct column in existing tables without migrations.
e.g., it may map to Address_StreetAddress
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
public class MyContext: DbContext
{
public DbSet<User> Users{ get; set; }
public MyContext(DbContextOptions<MyContext> options)
: base(options) { }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<User>(table =>
{
// Similar to the table variable above, this allows us to get
// an address variable that we can use to map the complex
// type's properties
table.OwnsOne(
x => x.Address,
address =>
{
address.Property(x => x.City).HasColumnName("City");
address.Property(x => x.State).HasColumnName("State");
address.Property(x => x.StreetAddress).HasColumnName("Address");
address.Property(x => x.SuiteNumber).HasColumnName("SuiteNumber");
address.Property(x => x.ZipCode).HasColumnName("Zip");
});
});
}
}