Search code examples
entity-framework-4entity-framework-ctp5complextype

EF4 - Can a POCO be used as both an Entity and ComplexType?


I am using EF4 CTP5. Here are my POCOs:

public class Address
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Line1 { get; set; }
    public string Line2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string PostalCode { get; set; }
}

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Address> Addresses { get; set; }
    public List<Order> Orders { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public decimal Total { get; set; }
    public Address ShippingAddress { get; set; }
    public Address BillingAddress { get; set; }
}

Is there a way to get Address to be a ComplexType for the Order class? After playing around with this, I'm guessing not, but maybe there's a way I haven't seen.

EDIT: In response to Shawn below, I gave it my best shot:

//modelBuilder.Entity<Order>().Ignore(o => o.BillingAddress);
//modelBuilder.Entity<Order>().Ignore(o => o.ShippingAddress);
modelBuilder.Entity<Order>()
    .Property(o => o.BillingAddress.City).HasColumnName("BillingCity");

Fails at runtime with error "The configured property 'BillingAddress' is not a declared property on the entity 'Order'." Trying to use Ignore() doesn't work. Next, the Hanselman article is CTP4, but the CTP5 equivalent is:

modelBuilder.Entity<Order>().Map(mapconfig =>
{
    mapconfig.Properties(o => new {
        o.Id
        , o.Total
        , o.BillingAddress.City
    });
    mapconfig.ToTable("Orders");
});

Fails with error "Property 'BillingAddress.City' of type 'Order' cannot be included in its mapping."

I give up. Maybe the final release will have something like this. Or maybe I need to switch to NHibernate =)


Solution

  • All you need to do is to place ComplexTypeAttribute on Address class:

    [ComplexType]
    public class Address
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Line1 { get; set; }
        public string Line2 { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string PostalCode { get; set; }
    }
    

    Alternatively, you can achieve this by fluent API:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.ComplexType<Address>();
    }
    

    But you cannot have Address type as to be both an Entity and a Complex Type, it's one way or another.

    Take a look at this blog post where I discuss this at length:
    Associations in EF Code First CTP5: Part 1 – Complex Types