SQL Server
↑
Data Layer — EFv4
↑ (Auto generated AutoMapper configs between entities and DTOs)
DTOs (Auto generated with T4 templates, based on the edmx)
↑
Service Layer (WCF REST, based on a template)
↑ (Json.NET for serialization/deserialization)
Web UI (heavy on the jquery)
This article will focus on the Data Layer, which will include my DTOs. I’ll cover specifically:
- Adding a new ADO.NET Entity Data Model and configuring it
- Turning your DataContext class into a singleton class that works well for ASP.NET environments (optional)
- Adding a custom T4 template to auto generate your DTO classes.
- Adding a custom T4 template to auto generate the [entity to dto] and [dto to entity] AutoMapper configurations.
- Adding a custom T4 template to auto generate additional code for your entity classes
- Adding a few custom helper classes for use inside the data layer (UnitOfWorkStore, JsonHelper, StronglyTypedIncludeHelpers)
First, here’s my contrived data model. I have Person objects, with basic info. Each person can have an Address. Each person can also be the owner of Projects.
Earth shattering, I know. I can hear people migrating en masse from MS Project to this new scheme.
Creating the EFv4 Data Model
This isn’t an Entity Framework 101 tutorial, so I won’t hand hold you through the entire process of creating the data model. Add a new ADO.NET Entity Data Model item to your data layer project. If you want to use the contrived model I’ve shown above, here’s the SQL create script. I’m not using the POCO generator templates, I’m just using the default config (so my objects inherit from EntityObject). You can have lazy loading enabled or disabled, it’s just a matter of preference. Initially I had a problem with AutoMapper triggering the lazy loading, but that’s sorted out now, so leave it on if you like it.Turning your DataContext class into a singleton class
This part is optional. If you like seeing this all over your code:
using (PersonEntities context = new PersonEntities())
{
// ...
}
Then by all means, skip this section. Especially if you like passing around the “current instance” of your object context to every method that interacts with your DAL. If you just love that, then DEFINITELY skip this section.
I’m not going to argue the best way to create the singleton pattern in C#. I’m setting up a special singleton that is unique “per user, per post back”. I use a class called UnitOfWorkStore, that looks like this:
static class UnitOfWorkStore
{
public static object GetData(string key)
{
if (HttpContext.Current != null)
return HttpContext.Current.Items[key];
return CallContext.GetData(key);
}
public static void SetData(string key, object data)
{
if (HttpContext.Current != null)
HttpContext.Current.Items[key] = data;
else
CallContext.SetData(key, data);
}
}
It allows you to store any object, by string key. If used in an ASP.NET environment, it uses HttpContext.Current.Items as the storage mechanism. The scope of that Items “bag” is unique to each user on your site (since they each have their own HttpContext), and the lifetime of the Items bag is the lifetime of the request/response lifecycle. It’s a very handy storage spot. This UnitOfWorkStore class will also work if used in a non-ASP.NET environment. It falls back to storing things in CallContext.
So create a partial class in your project to add some custom code to your DataContext class. Here’s how I’ve set up my singleton accessor:
public partial class PersonEntities
{
private static readonly object s_objSync = new object();
private static readonly string UOW_DATACONTEXT_KEY = "PersonEntities_UserInstance";
/// <summary>
/// Uses a UnitOfWorkStore to return the same instance of PersonEntities, that is unique
/// per user, per postback (or CallContext, if not in an HttpContext environment, such as unit tests or console apps)
/// </summary>
public static PersonEntities Instance
{
get
{
// Dirty (non thread-safe) check
if (UnitOfWorkStore.GetData(UOW_DATACONTEXT_KEY) == null)
{
lock (s_objSync)
{
// Thread-safe check
if (UnitOfWorkStore.GetData(UOW_DATACONTEXT_KEY) == null)
{
PersonEntities context = new PersonEntities();
UnitOfWorkStore.SetData(UOW_DATACONTEXT_KEY, context);
}
}
}
return (PersonEntities)UnitOfWorkStore.GetData(UOW_DATACONTEXT_KEY);
}
/*
// This could be used if we wanted to add a method that disposed the current DataContext, and created a new one.
private set
{
UnitOfWorkStore.SetData(UOW_DATACONTEXT_KEY, value);
}
*/
}
}
Now you have an instance of your DataContext class that you can just access. It’s always there. It’s always the same one. But, you could still get rid of it and create a new one if you want, just modify that class to your liking. Now your queries can look like this:
var q = from people in PersonEntities.Instance.People orderby people.Lname select people;
I can’t tell you how much I love being able to just write PersonEntities.Instance in all of the methods in my data layer, knowing that it will “just work”. In console apps, web apps, and unit tests, it “just works”. I don’t know if you know this about me, but I’m a big fan of things that “just work”.
Adding a custom T4 template to auto generate your DTO classes
This is pure gold. With EFv2, your model wasn’t really easily exposed to the T4 templating engine, so auto generating code based on your model was difficult. There was a VS2008 plugin named SFS that sort of worked, but it didn’t have support for everything (like inheritance). I used it a lot for a while, and even emailed the sole maintainer to offer help, but alas, no response. The last release was over a year and a half ago. But that’s no problem now, as the EDMX model is now properly exposed to the T4 runtime with EFv4.So why DTOs at all? They are small and simple. They serialize well. You can control exactly what data goes into them. You can flatten your model in them, if you wish, to send more specific or aggregated data. They aren’t tied to a framework. There are more pros (and certainly a list of cons somewhere too), but this isn’t the place for that discussion. Maybe read the wikipedia page.
Rather than show you the template (which you can download here if you want it), I’ll show you the output for my PersonDto.
[DataContract]
public class PersonDto
{
/// <summary>Parameterless constructor (important for serialization)</summary>
public PersonDto()
{}
public string ToJson(bool format = false)
{
return JsonHelper.Serialize(this, format);
}
public Person ToEntity()
{
return AutoMapper.Mapper.Map<PersonDto, Person>(this);
}
[DataMember] public int ID { get; set; }
[DataMember] public string Fname { get; set; }
[DataMember] public string Lname { get; set; }
[DataMember] public string Email { get; set; }
[DataMember] public Nullable<int> AddressID { get; set; }
[DataMember] public System.DateTime DateCreated { get; set; }
[DataMember] public AddressDto Address { get; set; }
[DataMember] public List<ProjectDto> Projects { get; set; }
}
Perfect! It even includes the FK properties from the model, which can come in handy. You’ll notice some references to JsonHelper and AutoMapper; we’ll get to that in a minute. Notice that the collection types are just lists of other DTO types. This means you can easily create an entire object graph, represented by DTOs. In fact, the way we’re about to set up AutoMapper, if you were to fetch an entire object graph, you can easily convert the whole graph to DTOs, already all wired up.
// Get the person with ID = 1, with his Address and Projects eagerly loaded var q = from p in PersonEntities.Instance.People .Include(p => p.Address) .Include(p => p.Projects) where p.ID == 1 select p; Person person = q.SingleOrDefault(); // Convert to DTO PersonDto dto = person.ToDto(); // All wired up... Console.WriteLine(dto.Fname); Console.WriteLine(dto.Address.City); Console.WriteLine(dto.Projects[0].Name);Nice. So now that our DTO classes are all auto-generated, let’s see how this AutoMapper thing works.
Auto generate the [entity to dto] and [dto to entity] AutoMapper configurations
If you haven’t ever heard of AutoMapper, that’s ok. It’s a great little object-to-object mapper. Normally, to convert an entity object to a dto object, I’d have to do this:PersonDto dto = new PersonDto(); dto.Fname = person.Fname; dto.Lname = person.Lname; dto.Email = person.Email; dto.Address = //....dangit, now I have to do this same line-by-line garbage for an address object. Boo.AutoMapper helps you do this automatically. It uses reflection, and if the properties are named the same in the 2 classes you’re mapping, you’re configuration is as eash as:
// configs for entity => dto Mapper.CreateMap<Person, PersonDto>(); Mapper.CreateMap<Address, AddressDto>(); Mapper.CreateMap<Project, ProjectDto>(); // configs for dto => entity Mapper.CreateMap<PersonDto, Person>(); Mapper.CreateMap<AddressDto, Address>(); Mapper.CreateMap<ProjectDto, Project>(); // Usage Person person = q.SingleOrDefault(); PersonDto dto = Mapper.Map<Person, PersonDto>(person);Nice and easy! Scroll up a bit and take a look at the auto generated PersonDto class. You see that ToEntity() method? It does the AutoMapper call for us, so we can just call ToEntity() on any old DTO object we have lying around. In a second, we’ll be adding ToDto() methods to our entity classes, again with the magic of another T4 template.
While it’s easy to write the configurations for mapping from entities to dtos, and from dtos to entities, why not auto generate them? This could be skipped if you have special mappings you want to set up, or if you want to deliberately exclude certain members, or somehow flatten your model, but if you just want a straight across mapping from entities to dtos, then check out this template. It creates code like this:
// AutoMapper config for Person => PersonDto AutoMapper.Mapper.CreateMap<Person, PersonDto>() .ForMember(dto => dto.Address, options => options.MapFrom(obj => obj.AddressReference.IsLoaded ? obj.Address : null)) .ForMember(dto => dto.Projects, options => options.MapFrom(obj => obj.Projects.IsLoaded ? obj.Projects : null)) ; // Reverse config (dto => entity) AutoMapper.Mapper.CreateMap<PersonDto, Person>();Note the ForMember() calls. This prevents AutoMapper from triggering the lazy loading of navigation properties. For any EntityReference or EntityCollection types, it checks to see if the IsLoaded property is true. If it is, it returns that object. If not, null. If you are using the POCO generator to create your entity classes, then these lines will cause errors, since you won’t have EntityObject and EntityCollection types. You can just comment out the appropriate lines from the template.
Now that we’ve discussed AutoMapper, I’d like to point out that the T4 template that auto generates the DTO classes creates one additional class, named DtoExtensionMethods. It contains some extension methods for each IEnumerable<dto> type, so that you can convert a whole set of DTO objects to entity types all at once. This lets you do stuff like:
Person[] people = personDtos.ToEntities();Very handy.
Auto generate additional code for your entity classes
There are dozens of tutorials and references on how to do this out there. This one is specific to the stack that I’m setting up here, to create the ToDto() methods for the entity classes, as well as the extension methods to convert an IEnumerable<entity> to DTOs, just like the extension method that did the reverse from the dto template. This template is small enough that I’ll just show it in its entirety here (download here):
<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ include file="EF.Utility.CS.ttinclude"#><#@
output extension=".cs"#><#
CodeGenerationTools code = new CodeGenerationTools(this);
MetadataLoader loader = new MetadataLoader(this);
string inputFile = @"../PersonEntities.edmx";
EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile);
string namespaceName = code.VsNamespaceSuggestion();
EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this);
#>
using System.Collections.Generic;
using Test.DataAccess.DTOs;
namespace <#= code.EscapeNamespace(namespaceName) #>
{
public static class EntityExtensionMethods
{
<#
foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
{
#>
/// <summary>
/// Easily create DTO objects from actual domain entity objects
/// </summary>
public static <#=code.Escape(entity)#>Dto[] ToDtos(this IEnumerable<<#=code.Escape(entity)#>> entities)
{
return AutoMapper.Mapper.Map<IEnumerable<<#=code.Escape(entity)#>>, <#=code.Escape(entity)#>Dto[]>(entities);
}
public static string ToJson(this IEnumerable<<#=code.Escape(entity)#>> entities, bool format = false)
{
return JsonHelper.Serialize(entities.ToDtos(), format);
}
<#
}
#>
}
}
<#
// ********************************************************************************
// *** Emit Entity Types **********************************************************
// ********************************************************************************
foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
{
fileManager.StartNewFile(entity.Name + ".AutoGen.cs");
#>
using Test.DataAccess.DTOs;
namespace <#= code.EscapeNamespace(namespaceName) #>
{
<#=Accessibility.ForType(entity)#> <#=code.SpaceAfter(code.AbstractOption(entity))#>partial class <#=code.Escape(entity)#> <#=code.StringBefore(" : ", code.Escape(entity.BaseType))#>
{
public string ToJson(bool format = false)
{
return ToDto().ToJson(format);
}
public <#=code.Escape(entity)#>Dto ToDto()
{
return AutoMapper.Mapper.Map<<#=code.Escape(entity)#>, <#=code.Escape(entity)#>Dto>(this);
}
}
}
<#
} // end foreach entity
fileManager.Process();
#>
And the output (for just one of the entity classes, Address):
public partial class Address
{
public string ToJson(bool format = false)
{
return ToDto().ToJson(format);
}
public AddressDto ToDto()
{
return AutoMapper.Mapper.Map<Address, AddressDto>(this);
}
}
Two convenient methods to have on each entity object.
Study those T4 templates well. You can add all kinds of useful logic to your entity and DTO classes, and the entire data model is at your disposal.
A few custom helper classes for use inside the data layer
I already talked about the UnitOfWorkStore, when we set up our ObjectContext class to have a singleton instance. So let’s take a look at the JsonHelper class. It’s very basic. It sets up a static readonly JsonSerializer (Json.NET), configures it how I like in the static constructor, and adds 2 methods to serializer and deserialize objects. By containing references to actual Json.Net classes to this single class, our code is a bit easier to read, and if we ever decided to switch serializers (say, to the DataContractJsonSerializer, though I don’t know why you’d want to), we would only have to update this one class. Here’s the code in full, or you can download it.
public static class JsonHelper
{
private static readonly JsonSerializer s_serializer = new JsonSerializer();
static JsonHelper()
{
s_serializer.Converters.Add(new IsoDateTimeConverter());
s_serializer.MissingMemberHandling = MissingMemberHandling.Ignore;
s_serializer.NullValueHandling = NullValueHandling.Include;
s_serializer.PreserveReferencesHandling = PreserveReferencesHandling.None;
s_serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
}
public static string Serialize(object obj, bool format = false)
{
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonTextWriter(stringWriter);
jsonWriter.Formatting = format ? Formatting.Indented : Formatting.None;
s_serializer.Serialize(jsonWriter, obj);
return stringWriter.ToString();
}
public static T Deserialize<T>(string json)
{
StringReader reader = new StringReader(json);
return (T)s_serializer.Deserialize(reader, typeof(T));
}
}
Last up is the StronglyTypedIncludeHelpers class. (I like descriptive class names). I can’t take credit for this one, it’s a direct copy/paste, here’s the original. There are various versions of this kind of solution floating around, I like this one the best. Here’s the class, I won’t post the code, instead I’ll show you some examples of what it’s used for.
Entity Framework allows you to do eager fetching, meaning you can fetch related data for the entities that you’ll bringing back in your queries. If I wanted to get a person, but have his Address object already loaded, as well as his Projects collection, here’s how you do it.
var q =
from p in PersonEntities.Instance.People.Include("Address.People").Include("Projects")
where p.ID == 1
select p;
I added one extra eager fetch in there; not only will we get the person’s Address, but that Address object will have its People collection populated with all of the people that are assigned to that address as well. I just did this to illustrate that you can specify more than one level in the association path when you call Include(). Now, as useful as Include() is, it’s brittle. What happens when someone changes the entity set name from People to Persons? Your code still compiles, but it will start throwing all kinds of runtime exceptions. You have to hunt down every reference to People, hiding as strings. Well, these new extension methods can solve that.
var q = from p in PersonEntities.Instance.People .Include(p => p.Address.Include<Address, Person>(a => a.People)) .Include(p => p.Projects) where p.ID == 1 select p;For an association path that’s just 1 level, it’s great: p => p.Projects. Very nice. For paths that go multiple levels deep, it’s not as pretty. It seems that the type inference cannot be automatically deduced, so the generic type parameters have to be specified. It’s a little awkward the way that it has to be chained here, but I still prefer it to the brittle string method. If you changed an entity set name now, you’d get a compile time error. My favorite kind.
Wrapping up
This post ended up being much longer than I anticipated. It’s more of a treatise. I wanted to cover the whole data layer today though, so I can move on to the WCF REST service next time. I hope to get that done in one shot as well. But I’ll leave the automatic generation of the javascript service proxy class till after the WCF REST service (you’re going to love that by the way. It’s very cool…just point the JsProxyCreator.exe to your assembly with your [ServiceContract] classes, and presto! Instance js proxy class to call your services).Here are all the files I went over in this post:
UPDATE: The files here all have updated, improved versions. Check out the files at the end of part 3 in the series.
| CreateScript.sql | Create the SQL tables for my contrived data model (3 tables, Person, Address and Project) |
| UnitOfWorkStore.cs | Used with the DataContext singleton. This is an easy way to store things in HttpContext.Current.Items |
| PersonEntities.cs | The DataContext singleton |
| DtosTemplate.tt | T4 template to auto generate DTOs from your EDMX model, for all your entity classes |
| AutoMapperConfig.tt | T4 template to auto generate AutoMapper configs to/from entities/dtos |
| EntityToDto.tt | T4 template to create partial classes for your entity types, adding ToDto() and ToJson() methods |
| JsonHelper.cs | Encapsulate the usage of Json.NET library to this class. A helper class used all over (in the service layer too) |
| StronglyTypedIncludeHelpers.cs | Strongly typed Include() expressions, using lambdas, via these extension methods |
These files will likely get updated as I find bugs and make revisions. I’ll try to keep a running change log at the end of this post, if it’s anything significant.
Up next, part 3: The WCF REST service.
5 Comments
I am ever surprised by the volume and depth of your work. What a blessing to be able to work with you. I can’t wait to cut my teeth on this.
Awesome post!!!
I like your articles a lot. Something is bothering me though : where do you get the following from ?
using CBMapping.Data.Entity;
Sorry for the late response on this Julien. It got lost in my inbox, and I just saw it.
The namespace CBMapping.Data.Entity was the original namespace for these utility classes. I thought I had updated all of them to “Test.DataAccess” before uploading them, but it seems that I’ve missed some. At any rate, this whole package has still been evolving daily, since I use it in a production environment at work, for many projects. I just released an open source library for creating REST services in C# without WCF. It’s at http://rest.codeplex.com. I also have another project I’ll be releasing in the next week or two, named Loef (said “loaf”, but the ef is for entity framework). Loef is essentially what this post grew in to. It’s the small set of utility classes and T4 (.tt) templates to assist in the creation of a data layer using EFv4. It’s not published yet, but the url is http://loef.codeplex.com. Keep an eye out for it. Especially if you found anything useful in this post.
Hi Samuel,
I’ve read most of your articles / restcake etc… I do see it hasn’t been updated lately, does it mean your endeavors have terminated?
Thanks for your reply..!
Lars