How do I map DAL to DTOs? <updated/>

Oct 19, 2010 at 1:12 PM
Edited Oct 20, 2010 at 1:18 PM

<update>

Since I cannot find any documentation on the problem I've had to write my own mapping classes. The problem I have now is that I cannot send the classes created by NHydrate (that I mapped to) to the db, so I'm sure I'm doing something wrong. Has anyone please got some code that shows how I should be mapping to/from the NHydrate created classes? NHydrate looks great and up till now has saved me loads of time/hassle, but if I cannot get a solution in the next day or so I'll have to give up on NHydrate and try another route. 

Cheers,

Matt

</update>

 

Hi all,

I want to be able to use the DTOs generated in my DataTransfer library throughout my app, and map them across to the business objects only when some database interaction occurs. I can find no (recent) documentation on this, it is possible without me having to write my own mapping classes? Many thanks,

Matt 

<edit>

i think I'm having the same problem...

http://nhydrate.codeplex.com/Thread/View.aspx?ThreadId=230863

</edit>

<edit_2>

On examining my DTO library, none of the collection references are present. For example I have a class fooDTO.cs that should contain a collection of barDTO.cs, but it does not. do I need to add these collections myself?

</edit_2>

Oct 20, 2010 at 1:26 PM

Hi Matt - I'm about as new here as you, so don't have many answers, but I did see this which gives a couple of examples of persistence with DTOs:

http://nhydrate.codeplex.com/wikipage?title=Inversion%20of%20Control&referringTitle=Documentation

Essentially, there isn't a built in collection with DTO objects - you use the c# List object instead.

Hope that helps

Iain

Oct 20, 2010 at 1:33 PM

Thanks for responding Iain, I've been through that doc. I just need some examples of how to map from my DTO classes to the NHydrate created classes. I guess I'll keep digging away in the generated code, see if I can see what the problem is...

Oct 20, 2010 at 2:18 PM

Try this:

// I run this in the constructor for my controller code

ConfigurationManager.AppSettings["ProxyAssembly"] = @"Company.Project.DALProxy"; // This tells the DTO layer which proxy to use

// The DAL proxy does the mapping to the DAL to save the object

 

// This code runs where I do the save

using Company.Project.DataTransfer;

 using Company.Project.Service.IOCExtensions;

personDTO.Persist(); // This does the save

 

That's it!

 

Oct 20, 2010 at 2:37 PM

Huzzah! It only flippin' worked (apologies for the casual swearing)!

I'll redo my mapping to work off the DTO objects. Many thanks for your help,

Matt

Oct 20, 2010 at 2:47 PM

As Columbo said, "Just one more thing... "

As I mentioned in an earlier post, "On examining my DTO library, none of the collection references are present. For example I have a class fooDTO.cs that should contain a collection of barDTO.cs, but it does not. do I need to add these collections myself?"

So do I just add

List<bar> myList = new List<bar>()

to the partial fooDTO class? Will this allow the whole object graph (since, in turn bar.cs also contains a collection class) to be saved in one move? 

Oct 20, 2010 at 3:08 PM

Hi Matt, have a look again at the link I sent you earlier - there's an example there of how to handle collections of sub-objects - it's very brief, but should hopefully be enough to get you going

Cheers!

Oct 20, 2010 at 3:11 PM

Right at the bottom of the article, in case you're wondering where...

Oct 20, 2010 at 3:12 PM

Or to make life even easier...

While dependency walking is not supported though the generated property construct, it is supports with extension methods. The functionality is equivalent but the DTO must use methods instead of the easier to read property syntax. Also the DAL caches the relations once you walk down that path. There is no hit on the data store for the second walk. In the DTO, since you are calling a method, it is executed each time your call it and thus the database is hit each time you execute the method.

//DAL dependency walking
Customer customer = …get a customer here…;
BusinessObjectList< Order> orders = customer.OrderList;

//DTO dependency walking
CustomerDTO customer = …get a customer here…;
OrderDTO[] orders = customer.GetOrderList();

 

Oct 21, 2010 at 8:16 AM
Edited Oct 21, 2010 at 8:16 AM

Cool, I see how that works once I have data in the db. However, I still have this problem:

  • I create a new FooDTO object 
    FooDTO myFoo = new FooDTO()
    
  • I have added a List<> of BarDTO objects to the customizable extender class for FooDTO. I add my BarDTO objects to the list
    myFoo.BarList.Add(myBar1)
    myFoo.BarList.Add(myBar2)
    myFoo.BarList.Add(myBar3)
    myFoo.BarList.Add(myBar4)
  • I call 
    myFoo.Persist()
    
  • The database now stores the properties from the myFoo object (hurray!) but it has not stored the properties in any of the myBar objects (boo!)

How do I add my Bar objects the the Foo object so that they are added to the database in one go? Cheers,

Matt

Oct 21, 2010 at 9:14 AM

OK, I think I finally cracked this. I'll complete my code today and then I'll write it up for the community and post it back here. Many thanks for your help Iain. Cheers,

Matt

Nov 22, 2010 at 6:45 PM

Could share your experience on how to persit relations with DTO objects? Thanks.

Nov 22, 2010 at 8:34 PM

Specifically how did you resolve persisting relations. Thanks.

Nov 23, 2010 at 8:28 AM
Edited Nov 23, 2010 at 8:28 AM

Here's how I did it, comments welcome on my implementation...

As previously stated I have a class foo, that contains a collection of bar objects. My implementation of the 21st Oct was incorrect, and should have been as follows:

  • Create a new FooCollection object, this class has been generated by NHydrate and is in the Business.Objects namespace for your project:
	FooCollection fooCol = new FooCollection();
  • You then create the list class of Bar objects by calling the following method on the FooCollection (also in Business.Objects):
	BarCollection barCol = fooCol.SubDomain.GetCollection<BarCollection>();
  • To create objects to add to your collections, use the NewItem() method thus:
	Foo myFoo = fooCol.NewItem();
	Bar myBar = barCol.NewItem();
  • The objects in the child collection need to link back to their parent objects. In this case, Bar contains a property FooItem:
	myBar.FooItem = myFoo;
  • Once you've added data to your objects, add them back to their collections:
	fooCol.AddItem(myFoo);
	barCol.AddItem(myBar);

So, for the whole process, my code looks something like this (Disclaimer: may contain typos/blatant accuracies):

// Instantiate collections
FooCollection  fC = new FooCollection();
BarCollection bC = bC.SubDomain.GetCollection();

// Get an instance of Foo and populate it with data
Foo myFoo = fC.NewItem();
myFoo.SomeProperty = "Some value";
myFoo.SomeOtherProperty = "Some other value";
fC.AddItem(myFoo); // Add back to the collection

// Add 10 Bar objects
for(int i = 0; i < 10; i++)
{
    // Get an instance of Bar populate in with data
    Bar myBar = bC.NewItem();
    myBar.FooItem = myFoo; // Foo object Bar object is related too
    myBar.SomeProperty = "Some value_" + i;
    bC.AddItem(myBar); // Add back to the collection
}

// Persist all data
fC.Persist();

Their may be some errors where I've copied across from my code, but the method works for me. Cheers,

Matt

Nov 23, 2010 at 12:51 PM

So your are not using DTO objects? Looks like you started with DTO objects...

Nov 23, 2010 at 12:56 PM

That's correct, I started using the NHydrate DTO library, but I could not find any documentation plus I had my own DTO already written. I just map between my DTO and the NHydrate generated library (the DAL, not the DTO). 

Nov 24, 2010 at 3:23 PM

Ok. I'm also trying similar and trying to avoid hand coding object mapping. here is what I'm doing.

Generated DTO objects and using them in ViewModel which will be used by the View

Using Automapper (from Codeplex) to map Business Objects to the ViewModel objects.

This works fine. However, the map from DTO object to Business Object does not work. Wondering if there is a quick solution for this. 

Thanks.

Coordinator
Nov 25, 2010 at 1:17 AM

Generate the (1) NHDAL (DAL in the generator popup) and (2) DALPRoxy, (3) Data Transfer layer (DTO), and (4) the Service Interfaces. Set the project dependencies so they build in the right order. Then you should be able to serialize and pass around the DTO objects. These are a mirror of your DAL objects. The DALProxy has extension methods that you can use on the server (in services or whatever you have on the server box). The extensions "extend" DTO objects and give them functionality like load and persistence. 

So you have a server application and use the DALProxy to load objects. Then pass the DTO items around to clients, through services, etc. When you get the objects back from a service or serialized from disk or where ever you get them from, you can then persist them to the database with 1 line of code. In your server application (most likely a WCF service), you have the DTO and a reference to the DALPRoxy layer. Call the DTO or List<DTO> object's "Persist" method (an extension from the DALProxy) and the changes go straight into the database.

Coordinator
Nov 25, 2010 at 4:42 PM

If you include the DALProxy project (and dependencies) then you can query DTO lists like they have real methods and functionality. In the sample below I have created a List<> of RegionDTO objects. The DALProxy extension methods add fucntionality on top of these types of objects so I can execute this code.

List<RegionDTO> list = new List<RegionDTO>();
list.RunSelect();

foreach (var region in list)
{
System.Diagnostics.Debug.WriteLine(region.Name);
}

The extension method just calls the corresponding DAL methods in the background, but it does provide an easy to use way to getting "functionality" on a DTO layer.