C# MVC+nHibernate,按id传递儿童;使用DTO?错误的方法?

C# MVC+nHibernate,按id传递儿童;使用DTO?错误的方法?,c#,asp.net-mvc,nhibernate,C#,Asp.net Mvc,Nhibernate,我正在研究一个三层的应用程序演示、业务、持久性,我在概念上遇到了问题:通过MVC与nHibernate交互的最佳方法是什么。具体来说,我有一个页面,可以让您创建一个用户并选择他们的角色。角色下拉列表通过从业务处理程序获取的对象列表填充。列表将所选ID保存为int[],la: @Html.ListBoxFor( x => x.SelectedRoles, new SelectList(Model.Roles, "Id", "Name")) 使用这些基类: public cl

我正在研究一个三层的应用程序演示、业务、持久性,我在概念上遇到了问题:通过MVC与nHibernate交互的最佳方法是什么。具体来说,我有一个页面,可以让您创建一个用户并选择他们的角色。角色下拉列表通过从业务处理程序获取的对象列表填充。列表将所选ID保存为int[],la:

@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,然后通过CreateUser调用将用户对象传递给它的业务处理程序。在上面的示例中,此工作流发生了故障,因为当我传递一个用户对象时,它的列表是空的,因为AutoMapper在逻辑上没有将int[]绑定到列表

这就是我的问题所在:

将int[]传递给我的Create方法,即CreateUser,int[],然后执行类似User.Roles=ids.Selectx=>\u roleRepository.GetByIdx.ToList;,是否更好;,或者我真的应该使用其他方法……DTO就是在这里发挥作用的吗?我知道他们将来会如何使重构变得更容易,因为我会有像CreateUserDto这样的东西,它永远不需要方法重命名,因为我可以根据需要向DTO添加更多字段

来自构建在存储过程上的迷你ORM,我觉得这种方法是错误的。不管使用DTO,我都会通过GetById为我请求的每个角色生成一个新的查询吗?或者这是nHibernate会自动缓存的东西


这是正确的方法吗?在过去,我只需将角色ID的int[]直接传递到SQL中,然后从那里创建记录—一个数据库调用来创建用户及其所有角色。我很难用ORM方法来高效地完成这项工作。

既然您已经在使用,为什么不为角色属性创建一个映射呢

.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());
    }
}

我没有考虑这样做,因为无论我把配置文件放在哪里,它们都会引起架构方面的麻烦。如果我把它们放在我的业务层中,我必须让该层现在知道我的ViewModels。如果它们出现在演示文稿中,我调用了业务处理程序vs.存储库,我就解决了这个问题,但现在我从处理程序中抽象出了一段随机的逻辑。当时我不喜欢这两种方法,我认为DTO是避免这些事情的方法。所以我采用了你的解决方案,但在我的ViewModels和Entities之间插入了DTO,这使我的层保持分离。为ViweModels->DTO和DTO->Entities添加了配置文件映射,效果很好!谢谢