3

Let’s say in my EF6 project [Database-first approach] I have a complex type called Address [just to clarify my complex type does not have any identity and is only a merge of aggregation of standalone data and it is not even responsible for its own persistence]

Currently I have all the fields associated with the address as direct properties for the constituent parts of the address and have the following automatically-generated definition for Person class:

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Nullable<int> Easting { get; set; }
    public Nullable<int> Northing { get; set; }
    public string Building { get; set; }
    public string County { get; set; }
    public string PostCode { get; set; }
    public string StreetName { get; set; }
    public string StreetNumber { get; set; }
    public string Town { get; set; }
    public string Unit { get; set; }
    public string Village { get; set; }
    public int CountryId { get; set; }
}

Ideally I would like to have something like the following [every time I update model from database]:

public class Person         
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Address Address { get; set; }
}

public class Address
{
    public Nullable<int> Easting { get; set; }
    public Nullable<int> Northing { get; set; }
    public string Building { get; set; }
    public string County { get; set; }
    public string PostCode { get; set; }
    public string StreetName { get; set; }
    public string StreetNumber { get; set; }
    public string Town { get; set; }
    public string Unit { get; set; }
    public string Village { get; set; }
    public int CountryId { get; set; }
}

How would I be able to have all address related fields as an aggregated field called Address when I update my model from the database (SQL Server 2012)?

As far as I know the only way forward is modifying T4 template. If your only suggested solution is T4 template alternation could you please show me some sample projects taking similar strategies or provide your own version.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
MHOOS
  • 5,146
  • 11
  • 39
  • 74
  • Do you use code-first approach? I had no issues with complex types when worked with EF6 and code-first approach. Columns with prefix `Address` (e.g. `Address_Easting`, `Address_Northing`, `Address_Building`) should be created in table `Person` by default. If you use database-first approach then simply follow naming pattern for address related columns. – Ilya Palkin Oct 18 '14 at 21:58
  • 2
    I Specifically mentioned this is a Database-first model in the question title. – MHOOS Oct 20 '14 at 08:02
  • Have you tried moving the address properties to a complex type in the EF designer (http://msdn.microsoft.com/en-us/data/jj680147.aspx)? – Chris Oct 22 '14 at 15:51
  • Did you read the link you sent me yourself?It says:"When you build the conceptual model, warnings about unmapped entities and associations may appear in the Error List. You can ignore these warnings because after you choose to generate the database from the model, the errors will go away". I don't know how else I should make this clearer that this is a Database-First project and model is generated based on the given database. – MHOOS Oct 22 '14 at 16:00
  • yeah, I stood up a database with a table matching the schema implied by your first object above and generated a model using db-first. I followed the steps in the link and was able to refactor the address properties into a separate complex type. Using Linq, I was able to query like this: `using (var context = new sandboxEntities()) { var persons = from a in context.Persons where a.Address.Building == "Building A" select a; }` – Chris Oct 22 '14 at 16:05
  • Can you tell me what happens when you Update Model from the database and you save it?Are you complex types like Address still available? – MHOOS Oct 22 '14 at 16:12
  • I added a new column to Persons and added a new table to the database and updated the model with no issues. – Chris Oct 22 '14 at 16:44
  • @MHOOS Did Refactor -> Move to New Complex Type work for you? – Chris Oct 23 '14 at 21:27

3 Answers3

0

When you use database first approach in EF you lay all responsibility for resulting classes on generator. So you cannot get complex type Address in this approach. You should use other approaches to get what you want. If I were you I would use code first approach and write mapping from existing database to classes in code.

Kirill Bestemyanov
  • 11,946
  • 2
  • 24
  • 38
0

You can use TPH to achieve what you want for example:

in your classes you will have the following:

1- class Person

public class Person
{
    public int Id{get; set;}
    public string Name{get; set;}
}

2- class address inherited from the class person

public class Address: Person
{
    public int? Easting { get; set; }
    public int? Northing { get; set; }
    public string Building { get; set; }
    public string County { get; set; }
    public string PostCode { get; set; }
    public string StreetName { get; set; }
    public string StreetNumber { get; set; }
    public string Town { get; set; }
    public string Unit { get; set; }
    public string Village { get; set; }
    public int CountryId { get; set; }
}

and in your DbContext class called "Entities" for example, you only define the following

public class Entities: DbContext
{
    public DbSet<Person> People{get; set;}
}

so what this will generate in your database?

1- it will generate a table called people containing both properties from person and address classes

2- you can access the people data either from person or from address in this way

var  db=new Entities();
var person= db.People.OfType<Person>(); // this will give you only Id  and Name properties
var address= db.People.OfType<Address>(); // this will give you the person and address details together 

hope this will help you

Monah
  • 6,714
  • 6
  • 22
  • 52
0

You can abstract the domain model classes from the application classes using a DTOs and Automapper.

Alexander Talavari
  • 418
  • 2
  • 9
  • 24