0

私は 3 層アプリケーション (プレゼンテーション、ビジネス、永続化) に取り組んでおり、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 にフィールドを追加するだけでよいため)。

ストアド プロシージャに基づいて構築されたミニ ORM から来ているので、このアプローチは間違っているように感じます。DTO の使用に関係なく、GetById を介して要求するすべてのロールに対して新しいクエリを生成することはありませんか? それとも、これは nHibernate が自動的にキャッシュするものですか?

これは正しいアプローチですか?以前は、ロール ID の int[] を SQL に直接渡し、そこからレコードを作成していました。1 つのデータベース呼び出しで、ユーザーとそのすべてのロールを作成していました。それを効率的に行うORMの方法に頭を悩ませるのに苦労しています。

4

1 に答える 1

1

すでにAutoMapperRolesを使用しているため、プロパティのマップを作成してみませんか?

.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 に答える