Могут ли сущности быть присоединены к сеансу IS, который ранее не был присоединен? - PullRequest
2 голосов
/ 05 января 2011

Я играю с NHibernate 3.0. Пока все довольно круто. Я пытаюсь прикрепить объект, который ранее не был отсоединен:

var post = new Post(){ Id = 2 };
session.Update(post); // Thought this would work but it doesn't.
post.Title = "New Title After Update";
session.Flush();

Что я пытаюсь написать , так это:

var post = new Post(){ Id = 2 };
session.Attach(post);
post.Title = "New Title After Update";
session.Flush(); // Sql should be something like: UPDATE Post SET Title='New Title After Update' WHERE Id=2

Возможно ли так, что обновляется только Title? В настоящее время это возможно в EntityFramework. Я бы не хотел загружать Post из базы данных, когда мне просто нужно обновить несколько свойств. Кроме того, я пытаюсь избежать вызова метода, который создал бы объект ... так как, по моему мнению, он отходит от объектно-ориентированного подхода.

EDIT : я знаю об использовании транзакций, я просто использовал Flush(), чтобы сделать код простым. Итак, я думаю, что мы находимся на правильном пути к тому, чего я пытаюсь достичь. Я хотел бы иметь возможность создавать сущность с известным идентификатором, используя конструктор , как я это делал во втором блоке кода выше. Я не хочу вызывать Get<T> или Load<T>, так как он чувствует себя довольно неправильно, создавая объекты, подобные этому, которые уже существуют в базе данных. Например, в Entity Framework я могу написать 2-й пример кода, и он будет «просто работать». Обновляется только свойство Title.

Ответы [ 3 ]

4 голосов
/ 05 января 2011

Вы можете session.Save() или session.SaveOrUpdate()

обновление

Ладно, теперь я понимаю, что вы пытаетесь сделать. Вы пытаетесь обновить одно свойство для Post, которое ранее сохранялось, а не новое Post, и для этого вы создаете экземпляр нового Post и присваиваете ему Id единицы в базе данных. .

Я не уверен, что вы имеете в виду, когда говорите, что пытаетесь избежать вызова метода, который бы создал объект, но способ сделать это с помощью NHibernate таков:

var post = session.Load<Post>(2);
post.Title = "New Title";
session.SaveOrUpdate(post);

В общем, вы не должны звонить Flush() на своих сессиях.

Здесь важно отметить использование session.Load. Вызов Load с идентификатором сам по себе не загружает объект из базы данных . Значения свойств объекта будут загружены только тогда, когда вы получите к ним доступ.

Конечно, в этом сценарии я считаю, что NHibernate будет загружать свойства для Post, (но не для коллекций, если вы не указали режим активной выборки), и это имеет смысл ( честно говоря, я не понимаю, почему EF не будет загружать объект). Что если установщик для вашего свойства Title делает что-то важное, например, сверяет его с существующим заголовком, проверяет длину заголовка, проверяет ваши учетные данные или обновляет другое свойство? Простой отправки ОБНОВЛЕНИЯ в базу данных недостаточно.

1 голос
/ 05 января 2011

Можно обновить только измененные свойства, установив динамическое обновление в отображении. Однако, насколько я знаю, невозможно (без возврата к SQL) выполнить обновление без извлечения объекта из базы данных в какой-то момент.

0 голосов
/ 06 января 2011

Используйте метод слияния.Вы должны создать новую переменную экземпляра, чтобы принять присоединенный объект = nhibernate больше ничего не будет делать с вашим отключенным экземпляром.

        var post = new Post(){ Id = 2 };
        post.Title = "New Title After Update";
        // Must create a new instance to hold final attached entity
        var attachedPost = session.Merge(post);
        session.Update(attachedPost);
        session.Flush();
        // Use attachedPost after this if still needed as in session entity

, который охватывает функции «присоединения», которые вы ищете, но яЯ не вижу, как вы сможете обновить только одно свойство.если экземпляр объекта не был заполнен из базы данных, свойства будут другими.Динамическое сопоставление не решит эту проблему - NHibernate видит свойства как «обновленные» для множества пустых строк.

Должен сказать, что вы создаете новый экземпляр, но на самом деле вы обновляете существующий экземпляр,Вы работаете напрямую с идентификаторами, а не объектами.И вы устанавливаете одно свойство, и теперь у вас есть экземпляр, который может зависать и делать больше вещей, но он не навязывает никаких инвариантов и может фактически не иметь никакого сходства с реальной сделкой, кроме свойства id ...

Все это выглядит довольно анти-объектно-ориентированным лично для меня.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...