DTOGenerator: Easily Generate Data Transfer Objects from ADO.NET Entity Framework or LINQ to SQL Data Classes

In my previous post I wrote about a small utility that automatically generates Data Transfer Objects from LINQ to SQL Data Classes. Few days ago I had the time to add an important feature – the application can now generate DTO’s from ADO.NET Entity Framework Model as well. I also renamed the application to DTOGenerator and published it in CodePlex.

Data Transfer Objects in 2 Diagrams

There are really a lot of explanations about Data Transfer Objects in the web. You can read about them in the MSDN Magazine. But, Here is a 2 diagrams that show the concept of DTO’s in 2 most common scenarios:

Getting Information: DAL=>BLL=>GUI (click to enlarge)

image

Insert Information: GUI=>BLL=>DAL (click to enlarge)

image

How to Use DTOGenerator

Creating Data Transfer Objects is really easy while using DTOGenerator.

  1. First, you have to download the latest version. You can choose if you want to download executable files only or the full source code.
  2. After the download completed, extract the application. in the following examples i’ll assume that the application files (/bin/release in the full source code, or the files in the root of the “Executable Files Only” ZIP) located in c:\DTOGenerator.
  3. In order to use the application, you must have a .NET assembly that include ADO.NET Entity Framework model or LINQ to SQL Data Classes (or both…). Then, you have to use the following command from cmd:
    c:\DTOGenerator\DTOGenerator.exe “param1”  “param2”
    (between parameter1 and parameter2 there is a single space).
    param1 is the path for you .net assembly
    param2 is the path to a directory where the generated files (.cs files – DTO classes) will be created.
  4. After the files created, add them to your project. The DTO’s are in different namespace called DTO (you can change it manually).

The following code is an example for the file that DTOGenerator will create for the “Product” entity in the Northwind database:

   1: //ADO.NET EF Example
   2:  
   3: using System;
   4: using System.Data.Linq;
   5: using System.Linq;
   6: using System.Collections.Generic;
   7: /*
   8: This Data Transfer Object created Automatically by DTOGenerator.
   9: You can download DTOGenerator and get support in the project site: http://dtogenerator.codeplex.com 
  10: DTOGenerator developed by Shahar Gvirtz (http://weblogs.asp.net/shahar)
  11: */
  12:  
  13: namespace DTO
  14: {
  15:     public class ProductDTO
  16:     {
  17:         public static ProductDTO GetDTOFromDALObject(ConsoleApplication3.Product src, bool GetChilds)
  18:         {
  19:             ProductDTO obj = new ProductDTO();
  20:             obj.Discontinued = src.Discontinued;
  21:             obj.ProductID = src.ProductID;
  22:             obj.ProductName = src.ProductName;
  23:             obj.QuantityPerUnit = src.QuantityPerUnit;
  24:             obj.ReorderLevel = src.ReorderLevel;
  25:             obj.UnitPrice = src.UnitPrice;
  26:             obj.UnitsInStock = src.UnitsInStock;
  27:             obj.UnitsOnOrder = src.UnitsOnOrder;
  28:             if(src.Category != null && GetChilds)
  29:                 obj.Category = CategoryDTO.GetDTOFromDALObject(src.Category,false);
  30:             if(src.Order_Details != null && GetChilds)            {
  31:                 List<Order_DetailDTO> Order_DetailDTOlst = new List<Order_DetailDTO>();
  32:                 src.Order_Details.ToList().ForEach(p=>Order_DetailDTOlst.Add(Order_DetailDTO.GetDTOFromDALObject(p,false)));
  33:                 obj.Order_Details = Order_DetailDTOlst;
  34:             }
  35:  
  36:             if(src.Supplier != null && GetChilds)
  37:                 obj.Supplier = SupplierDTO.GetDTOFromDALObject(src.Supplier,false);
  38:  
  39:             return obj;
  40:         }
  41:         public ConsoleApplication3.Product GetDALObject(bool IncludeChilds)
  42:         {
  43:             ConsoleApplication3.Product obj = new ConsoleApplication3.Product();
  44:             obj.Discontinued = Discontinued;
  45:             obj.ProductID = ProductID;
  46:             obj.ProductName = ProductName;
  47:             obj.QuantityPerUnit = QuantityPerUnit;
  48:             obj.ReorderLevel = ReorderLevel;
  49:             obj.UnitPrice = UnitPrice;
  50:             obj.UnitsInStock = UnitsInStock;
  51:             obj.UnitsOnOrder = UnitsOnOrder;
  52:             if(Category != null && IncludeChilds)
  53:                 obj.Category = Category.GetDALObject(false);
  54:             if(Order_Details != null && IncludeChilds)            {
  55:                 System.Data.Objects.DataClasses.EntityCollection<ConsoleApplication3.Order_Detail> Order_Detailsgetdallst = new System.Data.Objects.DataClasses.EntityCollection<ConsoleApplication3.Order_Detail>();
  56:                 Order_Details.ForEach(p=>Order_Detailsgetdallst.Add(p.GetDALObject(false)));
  57:                 obj.Order_Details = Order_Detailsgetdallst;            }
  58:  
  59:             if(Supplier != null && IncludeChilds)
  60:                 obj.Supplier = Supplier.GetDALObject(false);
  61:  
  62:  
  63:             return obj;
  64:         }
  65:         
  66:         public Boolean Discontinued { get; set; }
  67:         public Int32 ProductID { get; set; }
  68:         public String ProductName { get; set; }
  69:         public String QuantityPerUnit { get; set; }
  70:         public Int16? ReorderLevel { get; set; }
  71:         public Decimal? UnitPrice { get; set; }
  72:         public Int16? UnitsInStock { get; set; }
  73:         public Int16? UnitsOnOrder { get; set; }
  74:         public DTO.CategoryDTO Category { get; set; }
  75:         public List<DTO.Order_DetailDTO> Order_Details { get; set; }
  76:         public DTO.SupplierDTO Supplier { get; set; }
  77:  
  78:  
  79:     }
  80: }

If we work with LINQ to SQL, then the DTO for “Product” will looks like this:

   1: using System;
   2: using System.Data.Linq;
   3: using System.Linq;
   4: using System.Collections.Generic;
   5: /*
   6: This Data Transfer Object created Automatically by DTOGenerator.
   7: You can download DTOGenerator and get support in the project site: http://dtogenerator.codeplex.com 
   8: DTOGenerator developed by Shahar Gvirtz (http://weblogs.asp.net/shahar)
   9: */
  10:  
  11: namespace DTO
  12: {
  13:     public class ProductDTO
  14:     {
  15:         public static ProductDTO GetDTOFromDALObject(ConsoleApplication4.Product src)
  16:         {
  17:             ProductDTO obj = new ProductDTO();
  18:             obj.ProductID = src.ProductID;
  19:             obj.ProductName = src.ProductName;
  20:             obj.SupplierID = src.SupplierID;
  21:             obj.CategoryID = src.CategoryID;
  22:             obj.QuantityPerUnit = src.QuantityPerUnit;
  23:             obj.UnitPrice = src.UnitPrice;
  24:             obj.UnitsInStock = src.UnitsInStock;
  25:             obj.UnitsOnOrder = src.UnitsOnOrder;
  26:             obj.ReorderLevel = src.ReorderLevel;
  27:             obj.Discontinued = src.Discontinued;
  28:  
  29:             return obj;
  30:         }
  31:         public ConsoleApplication4.Product GetDALObject()
  32:         {
  33:             ConsoleApplication4.Product obj = new ConsoleApplication4.Product();
  34:             obj.ProductID = ProductID;
  35:             obj.ProductName = ProductName;
  36:             obj.SupplierID = SupplierID;
  37:             obj.CategoryID = CategoryID;
  38:             obj.QuantityPerUnit = QuantityPerUnit;
  39:             obj.UnitPrice = UnitPrice;
  40:             obj.UnitsInStock = UnitsInStock;
  41:             obj.UnitsOnOrder = UnitsOnOrder;
  42:             obj.ReorderLevel = ReorderLevel;
  43:             obj.Discontinued = Discontinued;
  44:  
  45:  
  46:             return obj;
  47:         }
  48:         
  49:         public Int32 ProductID { get; set; }
  50:         public String ProductName { get; set; }
  51:         public Int32? SupplierID { get; set; }
  52:         public Int32? CategoryID { get; set; }
  53:         public String QuantityPerUnit { get; set; }
  54:         public Decimal? UnitPrice { get; set; }
  55:         public Int16? UnitsInStock { get; set; }
  56:         public Int16? UnitsOnOrder { get; set; }
  57:         public Int16? ReorderLevel { get; set; }
  58:         public Boolean Discontinued { get; set; }
  59:  
  60:  
  61:     }
  62: }

 

Using the Data Transfer Objects

The main difference in the way DTOGenerator works with ADO.NET EF and the way it works with LINQ to SQL, is that while working with LINQ to SQL no object association will be created. You can compare line 74 in the first example to line 52 in the second example and see the difference.

As you can see, each DTO include two important method: static method called GetDTOFromDALObject that get as parameter an instance of the ADO.NET EF entity object and return DTO that already has all the data stored in the entity instance.
The second method is GetDALObject that return an instance of the entity object that includes all the data stored in the Data Transfer Object.

If you don’t want to load data into the associated objects (for lazy-loading or for some other reasons) GetDTOFromDALObject and GetDALObject has both Boolean parameter that indicates if you want to fill the associated objects with data (the Boolean parameter is only when the DTO’s was generated from ADO.NET EF Model).

For example, if we work with LINQ to SQL then this how selecting data will looks like:

using (var data = new NorthwindDataContext())
{
List<DTO.ProductDTO> products = (from p in data.Products
select DTO.ProductDTO.GetDTOFromDALObject(p)).ToList();
}

Selecting data with ADO.NET Entity Framework will looks like this:

   1: using (var data = new NORTHWNDEntities())
   2: {
   3:     var product = data.Products.First(p => p.Category.CategoryName == "Beverages");
   4:     product.Category = data.Categories.First(p => p.CategoryID == 1);
   5:     var product2 = ProductDTO.GetDTOFromDALObject(product, true);
   6:     Console.WriteLine(product2.Category.Description); 
   7:     Console.Read();
   8: }

as you can see, in line 5 we say that we want to get DTO with associated objects that filled with data. if we called DetDTOFromDALObject with “false” then line 6 will throw an exception, because product2.category would be null.

Adding rows to the table will looks like this (LINQ to SQL Example):

   1: //Create a new Product in GUI - use DTO
   2: DTO.ProductDTO newProduct = new DTO.ProductDTO();
   3: newProduct.CategoryID = 1;
   4: newProduct.Discontinued = true;
   5: newProduct.ProductName = "check";
   6: newProduct.QuantityPerUnit = "10";
   7: newProduct.UnitPrice = 90;
   8: newProduct.UnitsInStock = 10;
   9:  
  10: //In the DAL, the Insert method get DTO.ProductDTO as parameter,
  11: //but it has to use the LINQ to SQL object to insert it - that's why we have GetDALObject()
  12: using (var data = new NorthwindDataContext())
  13: {
  14:     data.Products.InsertOnSubmit(newProduct.GetDALObject());
  15:     data.SubmitChanges();
  16: }

First, we get DTO object from another layer in our application (GUI, for example), then, when we add the data (to LINQ to SQL in this example) we use the “GetDALObject” method to give InsertOnSubmit the correct type as parameter, with all the data that stored in the DTO inside.

Summary

DTOGenerator is a small code generator the automatically create Data Transfer Objects from given .NET assembly with LINQ to SQL Data Classes or ADO.NET Entity Framework.

It’s really easy to use the application.

It’s beta version, so please report aboug bugs that you found or features you want.

Project Site
Download v0.5

Shahar.

19 Comments

  • Hi,
    I think you are taking it too far away. basically, this is an application that helps developers to save some time. A lot of developers would write the same code anyway, so instead of write it manually, I wrote application that do this automatically.

    If someone think, like you, that using this application will make him work harder - he simply shouldn't use it. You should use utilities like this only when they save your time.

    Shahar.

  • Good job, nice ideas. Eventaully people will understand application architecture is important. It's would be nice, if you could point out how EF4 will change your approach.

    Cheer
    -R

  • Yaah,
    Architecture is a very important thing, but you should keep the balance between using "cool utilities" and working. I wrote utility that i believe can save time. BUT, developers must know when to use something and when not to use it (because it will just spend their time). maybe you should talk with the developers in your company about it ;-)

    Ruairi, Thank you. EF4 will give you the option to use POCO built in, which means that if the ADO.NET Team will do they job good, there will be no need in my utility (except if you use LINQ to SQL).

    Shahar.

  • Perfect timing of the post, when i needed the most.

    "Some one will always hate you no matter what you do".. so ignore that blurr above and keep up with the good work.

    Thank you

  • Cool!

    May I suggest that you add a switch to include or not the WCF serialization attributes DataContract and DataMenber.

  • Thank you all.

    Guy, I'll add it in the next version.

    Shahar.

  • >>>param1 is the path for you .net assembly

    is the asp.net framework assembly or you talking about application .net assembly ?

  • @nisarkhan, I'm talking about the assembly that include your model (LINQ to SQL or ADO.NET EF - doesn't matter).

    Shahar.

  • Just a quick question, is there a problem with this tool on Windows 7 as I get and error

  • I'm using Windows 7 and i don't have a problem. what's the error?

  • Excellent work!

    It is a shame complete tools like yaah were even blessed with the ability to partially communicate with the human race. It is idiots like him obviously have no idea what they are on about. Without the DAL / BLL abstraction concepts deployment of these applications is an absolute nightmare. I expect he is one of the idiots that writes applications in a month and take 3 months to deploy it. You have to also ask yourself how did he end up looking for a DTO generator in the first place? Go figure.

    Keep up the great work Shahar.

  • Simple and nice solution!

    And, oh yeah, ignore the rude comments of Yaah. Sounds like he just got fired because he insisted in writing the new business app in FORTRAN 2.

    Regards

  • I'm using .NET version 4. It looks like it does not support this version.

  • This a certainly a good utility tool but should have supported VB.NET


  • I find your website on google, it proved to be useful for me , i like it very much !

  • It looks like it does not support this version but good.

  • An anniversary is a day that commemorates or celebrates a past procedures that occurred on the same day of the year as the initial event.

  • Afterward, the parties never turn to a schematic planning as there were ongoing disagreements on several terms.

  • Really enjoyed this blog article.Much thanks again. Great.

Comments have been disabled for this content.