Предполагается, что следующие сущности:
public class AppUser
{
public virtual int Id { get; set; }
public virtual string Login { get; set; }
}
// Mapped as joined-subclass
public class Person : AppUser
{
public virtual int Age { get; set; }
}
Если я создаю 1 AppUser и сохраняю его следующим образом
var user = new AppUser() { Login = "test" };
session.Save( user ); // let's say Id = 1
Как я могу привести / преобразовать / «продвинуть» его в Person, сохраняя то же самое? ID?
Теперь я застрял в моей таблице AppUser со строкой с Id = N. Как я могу заполнить таблицу Person тем же Id? Я не могу удалить AppUser и воссоздать его как Person, так как на AppUser могут ссылаться внешние ключи.
Я мог бы выпустить «INSERT» SQL «вручную», но это уродливо ...
Это определенно вопрос NHibernate. Я понимаю, что с точки зрения ООП это не имеет большого смысла, отсюда и отсутствие других тегов, кроме nhibernate.
Я не думаю, что nHibernate сможет решить эту проблему для вас. nHibernate работает с вашими данными как с объектом, и, особенно с объединенным подклассом, я не думаю, что есть что-то встроенное, что позволит вам изменить тип подкласса на лету, или, по крайней мере, изменить тип и сохранить оригинальный ID.
Я думаю, что лучше всего написать хранимую процедуру, которая, учитывая ID и тип NEW, удаляет все записи из таблиц подклассов и добавляет новую запись в нужную таблицу подклассов.
После выполнения этой процедуры перезагрузите объект в nHibernate (и убедитесь, что вы удалили все кэшированные данные, относящиеся к нему), теперь он должен иметь правильный тип, с которым вы хотите работать, установите его НОВЫЕ свойства и сохраните его.
Таким образом, у вас есть относительно универсальная хранимая процедура, которая просто изменяет типы ваших подклассов, но вам не нужно добавлять всю эту безумную логику для обработки различных свойств ваших подклассов.
Это обсуждалось на SO до , и я цитирую Джона Скита для потомков:
Нет. Ссылка на производный класс должен фактически относиться к экземпляру производный класс (или null). В противном случае как вы ожидаете, что он будет вести себя?
Например:
object o = new object();
string s = (string) o;
int i = s.Length; // What can this sensibly do?
Если вы хотите иметь возможность преобразовать экземпляр базового типа в производный тип, я предлагаю вам написать метод создания соответствующего экземпляр производного типа. Или посмотрите на свой дерево наследования снова и попробуйте перепроектировать так, чтобы вам не нужно было делать это в первую очередь.
В примере Скита строки - это объекты, а объекты - не строки. Так что «апкастинг» не сработает.