我正在开发一个三层应用程序(演示、业务、持久性),并且在通过 MVC 与 nHibernate 交互的最佳方法方面遇到了概念上的麻烦。具体来说,我有一个页面可让您创建用户并选择他们的角色。角色下拉列表通过从业务处理程序获得的 List 对象填充。该列表将选定的 id 保存到一个 int[] 中,例如:
@Html.ListBoxFor(
x => x.SelectedRoles,
new SelectList(Model.Roles, "Id", "Name"))
使用这些基类:
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();
}
然后我使用 AutoMapper 将我的 ViewModel 绑定到我的实体(即 UserCreateViewModel -> User),然后通过 Create(User) 调用将 User 对象传递给其业务处理程序。对于上面的例子,这个工作流崩溃了,因为当我传递一个 User 对象时,它的 List 是空的(因为 AutoMapper 在逻辑上没有将 int[] 绑定到 List)。
这就是我的问题出现的地方:
将 int[] 传递给我的 Create 方法是否更好,即 Create(User, int[]),然后执行类似的操作User.Roles = ids.Select(x => _roleRepository.GetById(x)).ToList();
,或者我真的应该使用其他方法...这是 DTO 发挥作用的地方吗? 我看到他们将来如何使重构更容易,因为我将拥有像 Create(UserDto) 这样的东西,它永远不需要方法重命名(因为我可以根据需要向 DTO 添加更多字段)。
来自基于存储过程的 mini-ORM,我觉得这种方法是错误的。不管使用 DTO,我不会为我通过 GetById 请求的每个角色生成一个新查询吗?或者这是 nHibernate 会自动缓存的东西?
这甚至是正确的方法吗?在过去,我只是将角色 ID 的 int[] 直接传递到 SQL 并从那里创建记录——一个数据库调用来创建用户及其所有角色。很难用一种 ORM 方式来有效地做到这一点。