Автоматически обновлять идентификаторы дочерней коллекции после вставки в двунаправленную связь «один ко многим» - PullRequest
0 голосов
/ 27 октября 2010

Я уверен, что эта проблема уже решалась, но я не могу найти «дубликат».Итак, вопрос:

У меня двунаправленная ассоциация «один ко многим»: документ и комментарии .Таблица комментариев имеет внешний ключ (не обнуляемый), указывающий на таблицу документов.Классы:

public class Document {
   public virtual Guid Id {get; set;}
   public virtual string Title {get; set;} 
   public virtual string Body {get; set;}
   public virtual IList<Comment> Comments {get; set;}
}

public class Comment {
   public virtual Guid Id {get; set;}
   public virtual Document Document {get; set;}
   public virtual string Body {get; set;}
}

//Mappings

public class DocumentMap : ClassMap<Document> {
    public DocumentMap(){
       Id(x => x.Id).GeneratedBy.GuidComb();
       Map(x=>x.Title);
       Map(x=>x.Body);
       HasMany(x=>x.Comments).Inverse().Cascade.All().AsBag();
    }
}

public class CommentMap : ClassMap<Comment> {
    public CommentMap(){
       Id(x => x.Id).GeneratedBy.GuidComb();
       Map(x=>Body);
       References(x=>x.Document).Column("DocumentId").Not.Nullable();
    }
}

//The problem

var existingDocument = FetchDocumentFromDatabase(someDocumentGuidId);
Console.WriteLine(existingDocument.Comments.Count()); //0
existingDocument.Comments.Add(new Comment { Document = existingDocument, Body = "Test"});
session.SaveOrUpdateCopy(existingDocument);//all OK
//commiting transaction etc
Console.WriteLine(existingDocument.Comments[0].Id); 
// 00000000-0000-0000-0000-000000000000

Но мне нужен мой новый идентификатор комментария здесь!

Комментарий добавлен ОК в БД, но идентификатор объекта по-прежнему пустой Guid.

Как автоматически заполнять идентификаторы дочерних объектов после того, как они были добавлены как часть обновления родительского объекта?

Я использую NHibernate 3.0.0 Alpha 3 (кажется, очень стабильным) и Fluent NHibernate v.1.1.

Пожалуйста, советуйте.

ОБНОВЛЕНИЕ 1: все изменения распространяются на БД очень хорошо (свойства документа обновляются, а также добавляются новые комментарии).

1 Ответ

2 голосов
/ 31 октября 2010

Проблема в том, что вы используете SaveOrUpdateCopy.Здесь происходит то, что existingDocument не используется для сохранения в базе данных.

С http://nhibernate.info/doc/nh/en/index.html#manipulatingdata-updating-detached:

Последний случай можно избежать с помощью SaveOrUpdateCopy(Object o).Этот метод копирует состояние данного объекта в постоянный объект с тем же идентификатором.Если в данный момент нет постоянного экземпляра, связанного с сеансом, он будет загружен.Метод возвращает постоянный экземпляр.Если данный экземпляр не сохранен или не существует в базе данных, NHibernate сохранит его и вернет как новый постоянный экземпляр.В противном случае данный экземпляр не становится связанным с сеансом.В большинстве приложений с отсоединенными объектами вам нужны оба метода, SaveOrUpdate() и SaveOrUpdateCopy().

Это означает, что existingDocument оставлен в покое, а NHibernate использует совершенно разные экземпляры для фактического выполнения егодействия на.

Так что мы можем сделать.Есть несколько вариантов:

  1. Результат от SaveOrUpdateCopy должен быть правильным Document.Вы можете изменить свой код на:

    existingDocument = (Document)session.SaveOrUpdateCopy(existingDocument);
    
  2. Вы можете переключиться на SaveOrUpdate.Теперь, я думаю, есть очень конкретная причина, по которой это может быть невозможно для вас, потому что вы специально выбрали SaveOrUpdateCopy.В любом случае, SaveOrUpdate - это то, что вы обычно используете;

  3. Вы можете перезагрузить Document.Это означает, что после SaveOrUpdateCopy вы можете поставить:

    var existingDocument = FetchDocumentFromDatabase(someDocumentGuidId);
    
  4. Если вы используете SaveOrUpdateCopy, потому что existingDocument пришел из другого ISession, вы также можетевыберите присоединение existingDocument к текущему ISession, используя Lock().После того, как вы «заперли» в existingDocument в новый ISession, вы можете использовать SaveOrUpdate вместо SaveOrUpdateCopy, и тогда будет использован тот экземпляр, включая Comment и Guidназначено.

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