NHibernate — несколько типов, реализующих один и тот же интерфейс

В моем приложении определены следующие типы

public interface IUser {
   int Id { get; set; }
   int UserName { get; set; }
}

public class User : IUser {
   public virtual int Id { get; set; }
   public virtual string UserName { get; set; }
}

Класс User свободно отображается следующим образом:

public class UserMap : ClassMap<User> {
    public UserMap() {
        Table("Users");
        Id(x => x.Id);
        Map(x => x.UserName);
    }
}

Я хотел бы создать другую реализацию IUser, но у меня есть пара ограничений:

  1. Новые поля должны быть добавлены в ту же таблицу, что и таблица Users.
  2. Код для расширения типа существует в отдельном проекте.

Например, вот мой новый класс:

public class CustomUser : IUser {
   public virtual int Id { get; set; }
   public virtual string UserName { get; set; }
   public virtual string Name { get; set; }
}

Который отображается как:

public class CustomUserMap : ClassMap<CustomUser> {
    public CustomUserMap() {
        Table("Users");
        Id(x => x.Id);
        Map(x => x.UserName);
        Map(x => x.Name);
    }
}

Первая проблема, с которой я столкнулся, заключалась в том, что он не хотел, чтобы один и тот же интерфейс отображался дважды. Я преодолел это, добавив некоторый код в событие Application_Start, чтобы добавить класс UserMap только в том случае, если класс CustomUserMap не существует.

Однако вскоре я столкнулся со следующей проблемой: если я добавлю ссылку на интерфейс IUser в другом типе, он выдает ошибку:

Ассоциация из таблицы Blogs относится к несопоставленному классу: IUser

Я, вероятно, делаю что-то совершенно неправильно, и я был бы признателен, если бы кто-нибудь мог показать мне, что я делаю неправильно. Спасибо


person nfplee    schedule 13.01.2012    source источник


Ответы (1)


Если вы хотите, чтобы они сопоставлялись с одной и той же таблицей, почему бы вам не наследовать пользователя? Это также реализует интерфейс IUser.

Чтобы предотвратить дублирование выбора (при выборке пользователя он может получить CustomerUser во втором круговом обходе), вам необходимо явно указать полиморфизм в классе User. В файлах hbm это будет polymorphism="explicit", не знаю о свободном nhibernate.

person jishi    schedule 13.01.2012
comment
Причина, по которой я не сделал этого изначально, заключалась в том, что я понятия не имел о polymorphism=explicit (Polymorphism.Explicit(); в Fluent NHibernate) и столкнулся с проблемой, о которой вы упомянули, с дублирующимся выбором. Однако это не позволяет мне переходить от пользователя к CustomUser. например, var customUser = (CustomUser)session.Get‹User›(1) выдает ошибку, возможно, мне просто придется принять это, но, пожалуйста, дайте мне знать, если это возможно. Спасибо - person nfplee; 13.01.2012
comment
Поскольку он не получил дополнительные поля, необходимые для CustomerUser, он не сможет преобразовать их в CustomerUser. Вы можете осуществить это, выбрав CustomerUser, а затем вместо этого приведя его к User. В этом случае, я думаю, вам вообще не нужно было бы привязывать класс User в Nhibernate. В противном случае вам просто нужно было бы .Get‹CustomerUser›(user.Id) всякий раз, когда вам нужен CustomerUser. - person jishi; 13.01.2012
comment
Спасибо, причина, по которой я хотел преобразовать User в CustomUser, заключается в том, что у меня есть методы службы, которые возвращают User. Однако я думаю, что могу изменить методы службы, чтобы вернуть T, где T: IUser. - person nfplee; 14.01.2012