Entity Framework 4.0 POCO-First development and POCO Template

How to use the POCO Template to create a top-down Entity Framework application.

According to Microsoft, the Entity Framework is the preferred method of data access for .NET applications, supporting strongly-typed access through LINQ. The Entity Framework also allows developers to program against a conceptual model that reflects application logic rather than a relational model that reflects the database structure. The Entity Framework can also be used from an ASP.NET application through the Entity Data Source.

EF4 now offers what developers have been screaming for - the ability to generate the back-end database schema from a POCO - based model that you design first - also known as "top down" development.

In order to facilitate this, Diego Vega of Microsoft has put together the ADO.NET C# POCO Entity Generator, a T4 template that is actually two templates - one called <YourProject>context.tt, and the other <YourProject>.tt. There is a complete listing of the various templates here.

The “<YourProject>.tt” file is responsible for generating a file for each EntityType and ComplexType in your "MyProject.edmx” model.

The second template (“<YourProject>.Context.tt”) produces a strongly typed ObjectContext for the “edmx” model. You use this strongly typed ObjectContext to interact with your database.

By splitting the template into two, one part that generates the Entity Types and Complex Types and one that generates a strongly typed context, it makes it possible not only to have Entities and ComplexTypes that are persistence ignorant but in addition to be able to site those classes in an assembly / project that has no persistence aware code in it at all. This is the model preferred by your "POCO Purist". To do this, one only needs to move the entities into a separate class library project, and move the <YourProject>.tt file into the new library project. Lastly, you need to "Fix" the link in the Template to point to the edmx model's new relative location, e.g. change

string inputFile = @ “MyProject.edmx” ;
To:
string inputFile = @ “..\MyMainProjectFolder\MyProject.edmx”;

Once this is done, you can have a class library that contains only persistence-ignorant entity classes, which will be used by the generated ObjectContext in the main project. Finally, you'll need to change the namespace where the context template expects to find your entities. You can do that easily by bringing up the Properties dialog for the .Context.tt Template and in the "Custom Tool Namespace" item, enter in your "Entities" namespace or whatever namespace you chose for your entities class library project. When the Template files are saved, the solution should build correctly.

Up until Entity Framework 4.0 I preferred the POCO top-down model so much that I would only use NHibernate, which easily supports it along with Fluent.NHibernate to facilitate reflected code - only mapping and configuration. But the idea of being able to design one's entity model directly on a nice Microsoft - engineered designer canvas that is already built in to Visual Studio 2010 certainly has its appeal.

In my example here, I don't do any of this entity separation as it is not difficult to do, and I wanted to keep everything super simple in order to illustrate the POCO alternative. I have a very simple Notes application with only two classes, Note and Category. This is what you design on an empty Entity Framework design surface:


The Association between Note and Category means that a Category can contain any number of Note instances, and a Note can only have one selected Category. Note that the designer adds a nice Navigation Property to each class that allows us to lazily load these objects on demand.

When you set up your Guid Id properties, it is important to set the StoreGeneratedPattern values to "None" - since we are supplying our own fresh Guids on our new entities that will be saved.

Once your model is designed, you can right-click on a blank spot in the design canvas and choose "Generate Database from Model", and bazoom - all the SQL for that provider is generated. Bring up the YourProject.edmx.sql file, right-click inside it and choose "Execute SQL" and you're done!

I'd be interested to see when Robert Simpson finds the time to update his ADO.NET SQLite Provider to match this new top-down model. You can use SQLite with Entity Framework 4.0 - you just cannot do top-down -- yet!

If you change your entity model, just regenerate the new backend SQL the same way. The onlly thing it does not do is create the database for you - you need to do that first and specify it with a new DataConnection.

Finally to get the entire POCO model working and get your generated entity classes, you need to right-click the designer and choose "Add Code Generation Item", and choose "ADO.NET POCO Entity Generator". This will generate your entity classes from the model that you designed.

That's all it takes. Now you can develop against your model and context. I have a simple Windows Forms app that lets you add a Category (which then appears in the Categories dropdown), and Add a Note. There are also two buttons to display your Notes either by selected date from a DateTime Picker, or via the Category that you have selected from the dropdown. Some example code is illustrated below:

private void btnAdd_Click(object sender, EventArgs e)
{
using (EF4POCONotes.Model1Container context = new Model1Container())
{
Category cat = new Category() {CategoryName = txtCategory.Text, Id = Guid.NewGuid()};
context.Categories.AddObject(cat);
context.SaveChanges();
this.cboCategory.DataSource = context.Categories;
}
}

private void btnAddNote_Click(object sender, EventArgs e)
{
Guid catId = (Guid) ((Category)cboCategory.SelectedValue).Id;
using (EF4POCONotes.Model1Container context = new Model1Container())
{
Category category = context.Categories.Where(c => c.Id == catId).FirstOrDefault();
Note note = new Note() {Id=Guid.NewGuid() ,CategoryId=catId,EntryDate = dtpEntryDate.Value, NoteText=txtNoteText.Text, Category=category ,Subject=txtSubject.Text};
context.Notes.AddObject(note);
context.SaveChanges();
this.cboCategory.DataSource = context.Categories;
}
}

private void Form1_Load(object sender, EventArgs e)
{
using (EF4POCONotes.Model1Container context = new Model1Container())
{
this.cboCategory.DataSource = context.Categories;
}
}

private void btnDisplay_Click(object sender, EventArgs e)
{
using (EF4POCONotes.Model1Container context = new Model1Container())
{
// give a range selected from the datetimepicker selected value
DateTime beginDate = dtpEntryDate.Value.AddDays(-1);
DateTime endDate = dtpEntryDate.Value.AddDays(1);
List<Note> notes = context.Notes.Where(n => n.EntryDate >beginDate && n.EntryDate<endDate ).ToList();
Form2 frm = new Form2();
frm.Notes = notes;
frm.ShowDialog();
}
}

private void btnDisplayCategory_Click(object sender, EventArgs e)
{
using (EF4POCONotes.Model1Container context = new Model1Container())
{
// Get the notes for this category
List<Note> notes =
context.Categories.Where(c => c.Id == ((Category) cboCategory.SelectedItem).Id).FirstOrDefault().
Notes.ToList();
Form2 frm = new Form2();
frm.Notes = notes;
frm.ShowDialog();
}

}

Entity Framework 4.0 has a lot of improvements over the previous version, and this is only one of them. You can download the completed solution here. Be sure to download and install the T4 Template from the link above, and be sure to check your connection string as I use SQL Server developer for all my work, not SQLEXPRESS. Create a new DataBase "EF4NOTES" and create a DataConnection to it in Server Explorer, and you should be good to go.

By Peter Bromberg   Popularity  (12900 Views)