Использование NHibernate Identifier Identity Generator - PullRequest
1 голос
/ 24 октября 2009

Я прочитал более чем в одном месте, что с помощью идентификатора NHibernate в качестве Первичный ключ считается плохой практикой, потому что идентификатор генерируется на стороне сервера и, следовательно, нам нужен ответ от сервера о сгенерированных идентификаторах. (я думаю, что я также видел сообщение Ayende, в котором говорится, что у сервера ms-sql могут быть проблемы генерация идентификатора, что может привести к нарушениям первичного ключа)

Теперь, скажем, у меня очень простая модель предметной области: блоги и посты. где каждый блог может иметь много постов и каждый пост принадлежит ТОЧНО одному блогу (отношения один ко многим) но МЫ ТОЛЬКО СОХРАНИМ Пост -> Блог, а не Блог -> Посты

теперь предположим, что я использую NHibernate WITH Idenitifer Id Generation, так что я не использую каскадирование, поэтому в моем коде c # есть что-то вроде этого:

SaveBlogInTransaction(blog1); <br> SavePostsInTransaction(blog1posts);

Теперь мой вопрос заключается в следующем: если вставка может быть сделано только в одном месте в моем коде (нет проблем с параллелизмом), гарантируется ли связь постов с их блогом в БД?


Я имею в виду, давайте посмотрим на схему таблицы сообщений:
PostId, PostName, PostType, BlogId

гарантируется ли, что BlogId будет действительным?

примечание: каждый метод работает как транзакция, и в конце он выполняет фиксацию в db

Ответы [ 3 ]

2 голосов
/ 25 октября 2009

Сообщения будут иметь правильный идентификатор блога даже в перефразированном вопросе. NHibernate вставит строку блога в базу данных, как только будет вызван Save, и получит сгенерированное значение идентификатора, используя SCOPE_IDENTITY в то время. Это значение идентификатора будет сохранено в объекте «Блог» и будет доступно для всех сообщений, созданных позже.

Вот почему люди говорят, что идентификаторы на основе идентификаторов не являются хорошим выбором - NHibernate должен выполнить SQL-запрос для немедленной вставки строки, чтобы можно было получить правильное значение идентификатора. Если используется другой генератор идентификаторов , NHibernate может избежать выполнения операторов вставки SQL, пока транзакция не будет зафиксирована, поскольку с базой данных не нужно связываться для определения значения идентификатора объекта.

0 голосов
/ 24 октября 2009

Я хотел бы задать вопрос немного по-другому. скажем, у нас есть этот код:

<br> SaveBlogInTransaction(blog1); <br> SaveBlogInTransaction(blog2); <br> SavePostsInTransaction(post1_a, post1_b, ...); // all the posts of blog1 <br> SavePostsInTransaction(post2_a, post2_b, ...); // all the posts of blog2 <br> <br>

гарантируется ли post1_a, post1_b, ... posts 'blogid = blog1id?
гарантируется ли, что post2_a, post2_b, ... blogid = posts = blog2id?

я думаю, что SCOPE_IDENTITY () здесь не подходит, потому что мы сначала вставляем blog1, blog2 и только затем blog1_posts и blog2_posts

примечание: у нас есть отношение один ко многим в модели, но в БД мы сохраняем только для каждого поста идентификатор блога, к которому он принадлежит (у нас нет таблицы BlogPosts)

0 голосов
/ 24 октября 2009

Это зависит от вашего отображения. Если вы сопоставили отношение «один ко многим» так, что у Blog есть коллекция BlogPosts, а у BlogPost есть ссылка на Blog, вы можете создать блог, добавить сообщения в свою коллекцию BlogPosts и сохранить только блог. NHibernate позаботится о том, чтобы сначала вставить запись в блоге, а затем установить внешний ключ для дочерних объектов, прежде чем сохранять их. Это гарантирует, что BlogId будет действительным.

Я не смотрел исходный код NHibernate, но я уверен, что он использует лучшие методы для восстановления идентичности после вставки, вероятно, SCOPE_IDENTITY. В этом блоге обсуждаются три метода.

Я не согласен, что использование идентичности - это плохая практика. Основная проблема заключается в том, что NHibernate может сохранить объект для получения идентификатора до вызова Flush. Поэтому вставка может происходить вне транзакции, и запись должна быть удалена вручную.

...