私は 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の方法に頭を悩ませるのに苦労しています。