Question

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;
        }
}
Était-ce utile?

La solution 2

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));

        }

Autres conseils

It sounds like you have a good high level idea of what needs to be done. You should use NHibernate to send and retrieve data to the database - not for mapping to the clientside. Send only the data you need back to the client. I'm a fan of Automapper and use it to map between data objects and viewmodels exposed via the user interface.

This is a very trivial example, but imagine you have an accountcontroller that will display account information in a view. You could use something like the following to get the information from the database and map it into a viewmodel

public ActionResult Index(){
  var myAccount = _session.Get<Account>(1);
  var viewModel = _mapper.Map<Account,AccountViewModel>(myAccount);
  return View(viewModel);
}

In your automapper mapping file, set up something like this:

 Mapper.CreateMap<Account, AccountViewModel>()
     .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.FullName))
     .ForMember(dest => dest.FirstName, opt => opt.MapFrom(src => src.FName));
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top