Reputation: 726
I've looked at a lot of articles this afternoon, but I can't seem to find a complete post that deals with complex objects within models that addresses what I'm attempting to do.
I am using a Code First approach, but do not have my models directly altering my database structure. Therefore, if changes occur to the database structure, I am manually changing the models.
With that said, I have the following table:
Name
Address1
Address2
Address3
City
State
Zip
Latitude
Longitude
I would like to build a model that looks like the following:
public class Person
{
public string Name { get; set; }
public Address Address { get; set; }
public Coordinates Coordinates { get; set; }
}
public class Address {
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
}
public class Coordinates
{
public float Latitude { get; set; }
public float Longitude { get; set; }
}
In my head, this seems like a tidy, objected oriented approach to 1-to-1 data coming back from the database. Instead of all these separate variable, similar data is grouped into subclasses.
My question is: How do I bind this complex model to my database using EF? If that is not possible, how do I write a custom binder to deal with data in this fashion.
Or am I thinking about this incorrectly. Is there a different way to approach this or should the data be structured differently?
EDIT
Based upon Jason Meckley's response below, this is the final code that I used to complete this task.
namespace MyNamespace
{
public partial class Person
{
public string Name { get; set; }
public Address Address { get; set; }
public Coordinates Coordinates { get; set; }
}
[ComplexType]
public class Address
{
[Display(Name = "Address")]
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
}
[ComplexType]
public class Coordinates
{
public float Latitude { get; set; }
public float Longitude { get; set; }
}
public partial class DATABASE_CONNECTION_NAME : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder
.Entity<Person>()
.Property(x => x.Address.Address1)
.HasColumnName("Address1");
modelBuilder
.Entity<Person>()
.Property(x => x.Address.Address2)
.HasColumnName("Address2");
modelBuilder
.Entity<Person>()
.Property(x => x.Address.Address3)
.HasColumnName("Address3");
modelBuilder
.Entity<Person>()
.Property(x => x.Address.City)
.HasColumnName("City");
modelBuilder
.Entity<Person>()
.Property(x => x.Address.State)
.HasColumnName("State");
modelBuilder
.Entity<Person>()
.Property(x => x.Address.Zip)
.HasColumnName("Zip");
modelBuilder
.Entity<Person>()
.Property(x => x.Coordinates.Latitude)
.HasColumnName("Latitude");
modelBuilder
.Entity<Person>()
.Property(x => x.Coordinates.Longitude)
.HasColumnName("Longitude");
}
}
}
Upvotes: 0
Views: 471
Reputation: 7591
decorate Address
and Coordinates
with the attribute [ComplexType]
. In your dbcontext subclass override OnModelCreating
and map the complex properties to the appropriate columns.
By default complex objects would be mapped like this Address_Address
and Coordinates_Latitude
so you need to override the default mapping with something like
modelBuilder
.Entity<Person>()
.Property(x => x.Address.Address1)
.HasColumnName("Address1");
Upvotes: 1