There is a
DtoTemplateSettings.ttinclude file
that looks like this:
So you setup the path to your .emdx data model in that config file, and set a few namespace names and other settings. You'll want to add that file and
the other .tt templates to your data access project in a folder named "Dtos" or "Templates" (or whatever you'd like).
Consider a basic Person class that has contact information. On the left we see the diagram for the Entity object that Entity Framework
modeled for us, based on the database. On the right is the DTO class that was automatically generated from the T4 template.
Note that the navigation properties that are collections have lists of DTO types: so when you get a DTO object graph,
it's all DTO types. A DTO type never references an Entity type. Getting a DTO type is the easiest thing in the world.
The DTO classes will all have a
StripCycles() method as well. I left it out of the code sample above,
because depending on the class, and the number of relationships it has with other classes, it can become complicated. They are recursive
methods, though indirectly (A calls B which calls A which calls B, etc) that strip any cycles out of your DTO graph. This is handy when you need
to serialize an object graph, and your particular flavor of serializer throws exceptions when it encounters a cycle (like anything with WCF).
What exactly is a cycle?
If you had a parent object with a collection of child objects, and each child object has a reference back to its parent, you've
got cycles.
parent.children[0].parent == parent. You could keep coding yourself in circles. Well, certain formats don't support
cycles, like json. So these cycles often need to be removed (unless you're using the much esteemed
Json.NET serializer,
which can simply be told to ignore them for you), before you serialize into those formats.
This template creates a single static class named
AutoMapperConfig that contains a single public static method:
CreateMappings().
Here's a snippet of what's in that method for our
Person to
PersonDto mapping.
So all
CreateMappings() does is set up the
AutoMapper maps for going back
and forth between your DTO and Entity types automatically. What's even better, is the AutoMapper usage is all wrapped up in
the code generated by Loef, with the Entity classes having
ToDto() methods, and the DTO classes having
ToEntity() methods.
Just make sure you call
AutoMapperConfig.CreateMappings() when your application starts (say, in your Global.asax Application_Start method).
Also worth noting is that calling
someEntity.ToDto() will not trigger lazy loading in your model.
Look at the lambdas used in MapFrom() that make sure that
EntityCollection and
EntityObject
types are loaded before including them in the DTO. This means your DTO graphs will always exactly match your Entity graphs.
This template creates partial classes for all of your entity types, to add a few convenience methods and properties to each of your entity classes.
GetByKey() (and its various overloads) allow for eager fetching of related entities over multiple levels.
Here are a few examples.
The EntityToDto.tt also creates a static class named
EntityExtensionMethods that contains specific extension methods for
eager loading in a fashion similar to EF's
Include() extension method, just with strong typing.
There a 6 simple utility classes used in Loef. Four of them, you'll probably never even use directly, as they are mostly used internally
by the code generated from the T4 templates.
-
IncludeChainBase (this is used for the strongly typed eager fetching, so things like p.Groups.People resolves to a string).
Each entity class has a nested class that inherits from this type. The nested class simply contains the association paths to
other related entities.
-
QueryExtensions. This class contains various extension methods for ObjectQuery and IQueryable. One of the extension
methods you might use directly is Order<T>. The default OrderBy lets you order by a column given as a string,
but OrderByDescending does not. This method helps with that.
-
UnitOfWorkStore. HttpContext.Current.Items is a little gem of a storage bag. It's basically a storage location
that's unique per user, per postback. The lifetime of objects placed in this bag (which are stored by a string key) is limited to the
duration of a single request and response. Why, that sounds like exactly what we need regarding our ObjectContext instances, doesn't it?
This class is used to store the globally accessible singleton instance of your ObjectContext, so that each user has their own context for
each request.
-
Singleton. This one you'll probably never use, and it's actually not even used by Loef currently.
It was an interim class used here and there until the PerRequestSingleton (see below) class was created.
There are 2 more classes that are quite handy, and that you'll want to use directly in your code.
If any of your operations deal with paging data, this class is your friend. It has a couple of overloaded constructors that make
returning paged data based on an existing
IQueryable or
IEnumerable a snap.
The PagedData class is very small and simple. You can understand it at a glance.
This is a fun one. Let's assume that with this whole AddressBook example, our
ObjectContext class
in our .edmx model is named
AddressBookEntities. With
PerRequestSingleton,
we can do this:
We create a Dal class that is our "entry point" to an always available instance of the ObjectContext, which is
unique per user, per request (in an ASP.NET environment). It's used like this:
That's it.
AddressBookDal.Instance will refer to the singleton instance of the AddressBookEntities
class. It's usable in your code behind files, in your IHttpHandlers, in your RestCake services, in your WCF services, etc. It's
always there, and you'll never have to do this again:
You're looking at it. All of the
examples use the
AddressBook.DataAccess
project that's part of the RestCake source download at CodePlex. The AddressBook.DataAccess project uses the templates
and utility classes from Loef to set up the data layer. If you take a look at the
AddressBook.Services
project (which uses RestCake to create the REST services), there are no references to
AddressBookEntities.
It's always
AddressBookDal, which uses the
PerSingletonRequest. Take a look
at those two projects, and you'll have a good idea of how easy it is to start using Loef and RestCake, and how much these little
libraries can do for you.
You don't have to use them together either. They have no dependencies on one another. If you're using
Entity Framework, but aren't doing anything with RESTful services, grab Loef. If you're doing RESTful services, but aren't using
Entity Framework, grab RestCake. If you're using both, grab both.