asp.net-mvcfluent-nhibernatefluent-nhibernate-mappingsharp-architecture

Should NHibernate be responsible for mapping to viewmodels from domain objects?


I've started a new project and decided to user SharpArchitecture with Fluent nHibernate for my ORM. (I've never used nHibernate or SharpArchitecture before so be gentle if I'm missing something)

What I'm trying to do and I'm not sure if this is the correct way or not or if it's even possible with nHibernate maps is to take an domain entity lets say client and map it to a lighter ClientModel which will be used in my view. The reason for the lighter model is I don't want to bring back extra info that is in the client entity for this view.

So my thoughts were to create in addition to my client entity to create a ClientModel entity with only a few fields and use nHibernate to map the two together.

I've tried some things but they all failed miserably.

My question - Is this what I should be using nHibernate for or should I use something like automapper? Am I confusing the word map in nHibernate by assuming it means something it doesn't?

Looking for some nHibernate experts to help me out here.

Also a small sample would be greatly appreciated.

Here's some code.

public class Client : EntityWithTypedId<Guid>
    {
        public virtual String Name { get; set; }
        public virtual String Slug { get; set; }
        public virtual IList<Address> Addresses { get; set; }
        public virtual String ClientSize { get; set; }
        public virtual String Industry { get; set; }
        public virtual String Founded { get; set; }
        public virtual String Type { get; set; }
        public virtual String Specialty { get; set; }
        public virtual Boolean ShowOnWebsite { get; set; }
        public virtual Image Logo { get; set; }
        public virtual Image LogoBlackAndWhite { get; set; }
        public virtual Image LogoHighResolution { get; set; }
        public virtual String FacebookUrl { get; set; }
        public virtual String TwitterUrl { get; set; }
        public virtual String LinkedInUrl { get; set; }
        public virtual IList<Project> Projects { get; set; }
        public virtual IList<Tag> Tags { get; set; }
        public override Guid Id { get; protected set; }
        public virtual DateTime CreatedDate { get; set; }
        public virtual String CreatedBy { get; set; }
        public virtual DateTime ModifiedDate { get; set; }
        public virtual String ModifiedBy { get; set; }
        public virtual DateTime? DeletedDate { get; set; }
        public virtual String DeletedBy { get; set; }
    }

public class ClientViewModel
    {
        public virtual String Name { get; set; }
        public virtual String Slug { get; set; }
    }


public class ClientTasks : IClientTasks
    {
        private readonly IRepositoryWithTypedId<Client, Guid> _clientRepository;
        private readonly IRepositoryWithTypedId<Image, Guid> _imageRepository;
        public ClientTasks(IRepositoryWithTypedId<Client, Guid> clientRepository, IRepositoryWithTypedId<Image, Guid> imageRepository)
        {
            _clientRepository = clientRepository;
            _imageRepository = imageRepository;
        }

        public List<Client> GetAll()
        {
            var allClients = _clientRepository.GetAll().ToList();
            return allClients;
        }
}

Solution

  • So for this I decided to place the code from tasks layer (repository that only returned the full objects) into a query class per view (select only properties I wanted and mapped them to my ViewModel).

    Also I decided to use the mapping through nhibernate because selecting specific columns forced me to map the fields anyway back into my domain from an object array so I figured since I already needed to do that I might as well just use the TransformUsing method as well.

    ClientListQuery.cs

    public IList<ClientListViewModel> GetClientListQuery()
            {
                ClientListViewModel clientListViewModel = null;
                return Session.QueryOver<Client>()
                    .OrderBy(o => o.Name).Asc
                    .SelectList(list => list
                    .Select(c => c.Id).WithAlias(() => clientListViewModel.Id)
                    .Select(c => c.Name).WithAlias(() => clientListViewModel.Name)
                    ...
                    .Select(c => c.Logo.Id).WithAlias(() => clientListViewModel.LogoId)
                    .Select(c => c.LogoBlackAndWhite.Id).WithAlias(() => clientListViewModel.LogoBlackAndWhiteId))
                    .TransformUsing(Transformers.AliasToBean<ClientListViewModel>())
                    .List<ClientListViewModel>();
            }
    

    Client Controller

    [Transaction]
            public ActionResult Read([DataSourceRequest] DataSourceRequest request)
            {
                return Json(_clientListQuery.GetClientListQuery().ToDataSourceResult(request));
    
            }