В настоящее время я пишу приложение, которое обращается к устаревшей базе данных.Я использую nhibernate в качестве своего ORM.
В БД есть три таблицы, которые представляют (почти) классические отношения «многие ко многим».С той разницей, что таблица ссылок также содержит дополнительные данные.
Код выглядит примерно так:
public class User
{
public virtual string Login { get; set;}
public virtual string Name { get; set;}
public virtual IList<UserRole> UserRoles { get; set;}
}
public class Role
{
public virtual int Id { get; set;}
public virtual string Description { get; set;}
public virtual IList<UserRole> UserRoles { get; set;}
}
public class UserRole
{
public virtual User User { get; set;}
public virtual Role Role { get; set;}
public virtual bool Active { get; set;}
}
public class UserMap : ClassMap<User>
{
public UserMap()
{
Table("Users");
Id(u => u.Login).Column("USER_LOGIN").GeneratedBy.Assigned();
Map(u => u.Name).Column("USER_NAME");
HasMany(u => u.UserRoles).KeyColumn("USER_LOGIN");
}
}
public class RoleMap : ClassMap<Role>
{
public RoleMap()
{
Table("Roles");
Id(r => r.Id).Column("ROLE_ID").GeneratedBy.Assigned();
Map(r => r.Description).Column("ROLE_DESCR");
HasMany(r => r.UserRoles).KeyColumn("ROLE_ID");
}
}
public class UserRoleMap : ClassMap<UserRole>
{
public UserRoleMap()
{
Table("UserRoles");
CompositeId()
.KeyReference(x => x.User, "USER_LOGIN")
.KeyReference(x => x.Role, "ROLE_ID");
Map(x => x.Active).Column("ROLE_IS_ACTIVE");
}
}
Таким образом, у пользователя может быть несколько ролей, а у роли - несколько пользователей.Как я уже сказал, классика многие ко многим.Но таблица UserRoles также содержит поле «active», которое требуется моему приложению для правильной работы.
Все работает правильно, но IMHO nhibernate генерирует слишком много запросов.Когда я выбираю пользователя и получаю доступ к его ролям, это запросы, которые отображаются в Nhibernate Profiler:
SELECT user0_.USER_LOGIN as USER_LOGIN0_0_,
user0_.USER_NAME as USER_NAME_0_
FROM Users user0_
WHERE user0_.USER_ID = 'testuser'
-- Fetch the user
SELECT userrole0_.USER_LOGIN as USER_LOGIN1_,
userrole0_.ROLE_ID as ROLE_ID1_,
userrole0_.ROLE_ID as ROLE_ID1_0_,
userrole0_.USER_LOGIN as USER_LOGIN1_0_,
userrole0_.ROLE_IS_ACTIVE as ROLE_IS_ACTIVE1_0_
FROM UserRoles userrole0_
WHERE userrole0_.USER_LOGIN = 'testuser'
-- Fetch the roles for that user (why are some fields selected twice?)
-- returns three rows: roleids: 1, 2 and 3
SELECT userrole0_.ROLE_ID as ROLE_ID1_0_,
userrole0_.USER_LOGIN as USER_LOGIN1_0_,
userrole0_.ROLE_IS_ACTIVE as ROLE_IS_ACTIVE1_0_
FROM UserRoles userrole0_
WHERE userrole0_.USER_LOGIN = 'testuser'
and userrole0_.ROLE_ID = 1
SELECT userrole0_.ROLE_ID as ROLE_ID1_0_,
userrole0_.USER_LOGIN as USER_LOGIN1_0_,
userrole0_.ROLE_IS_ACTIVE as ROLE_IS_ACTIVE1_0_
FROM UserRoles userrole0_
WHERE userrole0_.USER_LOGIN = 'testuser'
and userrole0_.ROLE_ID = 2
SELECT userrole0_.ROLE_ID as ROLE_ID1_0_,
userrole0_.USER_LOGIN as USER_LOGIN1_0_,
userrole0_.ROLE_IS_ACTIVE as ROLE_IS_ACTIVE1_0_
FROM UserRoles userrole0_
WHERE userrole0_.USER_LOGIN = 'testuser'
and userrole0_.ROLE_ID = 3
-- Fetch all rows again separately but with full key?!?!!?
Итак, Nhibernate начинается с выборки моего пользователя: OK. Затем он выбирает роли для этого пользователя:Хорошо. Но затем каждая строка, возвращаемая этим вторым запросом, снова извлекается из БД!Я не знаю, почему это происходит, поскольку данные, возвращаемые во втором запросе, на самом деле содержат достаточно данных для NHibernate, чтобы заполнить весь мой объект UserRole.
Есть ли кто-нибудь, кто может:
- объясните мне, почему это происходит
- помогите мне понять, как это предотвратить.то есть я хотел бы просто сказать NHibernate, что дополнительные запросы к таблице UserRoles не нужны.
Большое спасибо!С уважением, ldx