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)
Insert Information: GUI=>BLL=>DAL (click to enlarge)
How to Use DTOGenerator
Creating Data Transfer Objects is really easy while using DTOGenerator.
- First, you have to download the latest version. You can choose if you want to download executable files only or the full source code.
- 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.
- 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. - 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.
Shahar.