A better version of dtofactory

In this post I dealt with a primitive version of a T4 template to generate dto starting from domain objects. In these days I had little time to improve it a little bit, and I created a simple test project to verify some of the basic functionality.

Usage of the T4 template is really simple, I’ve created in the test project an Entity Factory model to the ubiquitous northwind database, then I added a OrderDto.tt file to the project with this content.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<#@ template language="C#" hostspecific="True" debug="True" #>
<#@ output extension="cs" #>
<#@ include file="DtoFactory.tt" #>
<#
// <copyright file="OrdersDto.tt" company="Gian Maria Ricci">
//  Copyright  © Gian Maria Ricci. All Rights Reserved.
// </copyright>
    GenerateDto(
        @"bin\Debug\DtoFactory.Exe", 
        "DtoFactory.Orders",
        "OrdersBaseDto",
        "DtoFactory",
        "http://www.nablasoft.com/dotnet/",
        1,      
        new String[] {"OrderId", "OrderDate", "Customers.CustomerID", "Customers.ContactName"},
        null,   
        true, true, true);  
#>

It is quite the same of the previous version, but now I inserted some enhancements. If you look at the property list you can see that I inserted properties like Customers.CustomerID and Customers.ContactName, that belongs to the customers object. When you use a domain model you are working with a graph of object, but dto must be plain. My generator will generate this class:

image

My dto class implements various interfaces and it has properties like Customers_ContactName and Customers_CustomerID, so it is a simple transfer object that contains all information we need. The assembler class is responsible to create a dto from original object and as usual can be used in this way:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
using (NorthwindEntities context = new NorthwindEntities())
{
    var Query = context.Orders
       .Where(o => o.Customers.CustomerID == "ALFKI")
       .Select(OrdersBaseDto.Assembler.ExpressionSelector);

    foreach (var order in Query)
    {
        Console.WriteLine("OrderId:{0} Customer:{1} Date:{2}",
            order.OrderID, order.Customers_CustomerID, order.OrderDate);
    }
}

This code simply use the ExpressionSelector contained in nested class Assembler of my dto of choice, then I can iterate into the query using various properties of the dto object. The most important stuff is that the expression selector actually does a projection , here is the generated query captured from the profiler.

1
2
3
4
5
6
7
8
9
SELECT 
1 AS [C1], 
[Extent1].[OrderDate] AS [OrderDate], 
[Extent1].[OrderID] AS [OrderID], 
[Extent1].[CustomerID] AS [CustomerID], 
[Extent2].[ContactName] AS [ContactName]
FROM  [dbo].[Orders] AS [Extent1]
LEFT OUTER JOIN [dbo].[Customers] AS [Extent2] ON [Extent1].[CustomerID] = [Extent2].[CustomerID]
WHERE N'ALFKI' = [Extent1].[CustomerID]

Only the field related to the dto are retrieved, and thanks to Entity Framework you get the join and projection for free, no unnecessary data is taken from database. This is a quite good result, because with few lines of code my generator is able to geneate a dto composed by properties taken from various objects, and thanks to LINQ I also got a projection for free that permits me to gain maximum efficiency avoiding to retrieve full objects.

Another interesting stuff is this one, you can link various Dto objects between them

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
    GenerateDto(
        @"bin\Debug\DtoFactory.Exe", 
        "DtoFactory.Orders",
        "OrdersTestDto",
        "DtoFactory",
        "http://www.nablasoft.com/dotnet/",
        1,      
        new String[] {"OrderID", "OrderDate", "Customers"},
        new PropertyData[] {new PropertyData("Customers", "CustomersDto")},   
        true, true, true); 

I’m asking to generate an OrdersTestDto object that contains the Customers property, but I specify that I do not want full Customers object, but simply a CustomersDto, so you will end in two dto connected together

image

This facility permits me to reuse dto but actually the ExpressionSelector of this dto cannot be directly used with LINQ, it needs still more work ;).

All the project is still in a very rought form, but I’m quite satisfied on it, if you like it you can download here. The code is provided as-is :) do not blame the author.

alk.

Tags: Dto T4 Code generation