views:

59

answers:

2

We are using nHibernate in our domain model, and would like to create DTOs for sending objects over WCF to a front-end application made using the MVVM-pattern (WPF/WinForms). We have total control of both the client and server - and both are upgraded at the same time, so versioning/cross platform is not an issue.

I see how editing single entries works, however I am still not certain about the best way to send collections of objects over the wire. The DTO then used to fill a grid, where rows can be updated, deleted or added.

My question is; What is the best method using DTOs and nHibernate to capture insert, updates and deletes in a grid/table like scenario?

Thank you.

(Our application originally used DataTables, where the DataTable/DataRow kept track of modifications and using GetChanges/Merge you could transfer over the wire only what was modified and needed updating - where inserts and deletes were also well kept track of)

A: 

You'll need to bind to a BindingSource such as:

dataGridView1.DataSource = _presenter.BindingSource;

You will also have an interface between your View and Presenter of some sort.

In your presenter, you'll return an IList<NHibernateResult> where NHibernateResult is the class with all your getter's and setter's for the properties you want to return. It can either be a custom class with limited properties (e.g. columns) or your entity class. NHibernateResult is not an actual class, just a placeholder for this answer.

For example (in presenter),

private IList<OrdersResult> _bindingSource;

        public IList<OrdersResult> BindingSource
        {
            get
            {
                //_bindingSource = OrderDataControl.Instance.GetAll();
                _bindingSource = 
                    OrderDataControl.Instance.GetSimpleOrderList(_firstResult, _maxResult);
                return _bindingSource;
            }

            set
            {
                _bindingSource = value;
            }
        }

OrderDataControl is a Data Access Object or Data Transfer Object. It interacts with your SessionProvider and Respository (aka Model).

This level of abstraction removes the data layer from your presenter and makes your view totally dumb about the model altogether. It relegates your view to only UI related events such as Enabled, Visible, Colors, etc.

0A0D
#OAOD Thank you for your reply, however I do not see how the bindingSource helps with keeping track of modifications to the collection. That is, if the IList is modified, I would still need to send the complete list back to the server - use the DTO to re-grab the entities and merge the changes from the DTO (or update all entities in the list). As deleted items are no longer in the list, I would need special handling for them.
Thies
+1  A: 

I would most probably send a container class which contains the new and updated instances and the items to delete.

For instance:

class GridModificationsDto
{
  Dto[] NewOrUpdatedItems { get; set; }
  Identity[] DeletedItems { get; set; }
}

When an item is new, it doesn't have an id. You could also have a separate list for new items.

Then you need to do something like this:

foreach(Dto dto in modifications.NewOrUpdatedItems)
{
  if (dto.id == 0)
  {
    session.Save(DtoMapper.CreateEntity(dto));
  }
  else
  {
    Entity entity = session.Get<Entity>(dto.id);
    DtoMapper.Update(entity, dto);
  }
}

foreach(Identity identity in modifications.DeletedItems)
{
  session.Delete<Entity>(identity.id);
}

I don't know how you could obtain the list of modified items in the ui. I thought that this would be available by data binding and PropertyChanged events and stuff like this. If there isn't anything useful, you may need to inherit your own Grid control.

Stefan Steinegger