0

我正在开发一个三层应用程序(演示、业务、持久性),并且在通过 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 方式来有效地做到这一点。

4

1 回答 1

1

既然您已经在使用AutoMapper,为什么不为Roles属性创建地图?

.ForMember(x => x.Roles, o => o.MapFrom(
    x => x.Roles.Select(id => _roleRepository.GetById(id)).ToList())

这可以封装在使用 DI 的 AutoMapper 配置文件中:

public class UserProfile : Profile
{
    private readonly IRoleRepository _roleRepository;

    public UserProfile(IRoleRepository roleRepository)
    {
        _roleRepository = roleRepository;
    }

    protected override void Configure()
    {
        CreateMap<UserCreateViewModel, User>()
            .ForMember(x => x.Roles, o => o.MapFrom(
                x => x.Roles.Select(id => _roleRepository.GetById(id)).ToList());
    }
}
于 2012-07-05T14:37:56.867 回答