I’m working on a three-tier application (presentation, business, persistence) and am having conceptual trouble on what the best approach for interacting with nHibernate via MVC. Specifically, I have a page that lets you create a user and select their roles. The roles drop-down list is populated via a List objects obtained from a business handler. The list saves the selected ids to an int[], a la:
@Html.ListBoxFor(
x => x.SelectedRoles,
new SelectList(Model.Roles, "Id", "Name"))
using these base classes:
public class Role
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<User> Users { get; set; }
}
public class User {
public virtual int Id { get; set; }
public virtual string Username { get; set; }
public virtual IList<Role> Roles { get; set; }
}
public RoleMap()
{
Id(x => x.Id);
Map(x => x.Name);
HasManyToMany(x => x.Users)
.Table("UserRole")
.ParentKeyColumn("RoleId")
.ChildKeyColumn("UserId")
.Inverse();
}
public UserMap()
{
Id(x => x.Id);
Map(x => x.Username);
HasManyToMany(x => x.Roles)
.Table("UserRole")
.ParentKeyColumn("UserId")
.ChildKeyColumn("RoleId")
.Cascade.SaveUpdate();
}
I then use AutoMapper to bind my ViewModel to my Entity (i.e. UserCreateViewModel -> User), then pass the User object to its business handler via a Create(User) call. This workflow breaks down for the above example, since when I pass a User object, its List is empty (since AutoMapper doesn’t bind an int[] to a List, logically).
This is where my question arises:
Is it better to just pass in the int[] to my Create method, i.e. Create(User, int[]), then do something like User.Roles = ids.Select(x => _roleRepository.GetById(x)).ToList();, or should I really be using some other approach…is this where DTOs come into play? I see how they would make refactoring easier in the future, since I would have something like Create(UserDto), which would never require method-renaming (since I could just add more fields to the DTO as I needed them).
Coming from mini-ORMs built on stored procedures, I feel like this approach is wrong. Regardless of using a DTO, won’t I be generating a new query for every role I request via GetById? Or is this something that nHibernate will automatically cache?
Is this even the right approach? In the past I would just pass the int[] of role ids directly into SQL and create the records from there – one database call to create the user and all of their roles. Having a hard time wrapping my head around an ORM-way of doing that efficiently.
Since you are already using AutoMapper, why don’t you create a map for
Rolesproperty?That could be encapsulated in an AutoMapper Profile that’s using DI: