Таблица редакций сопоставления в Fluent NHibernate

Я хочу провести аудит моей Posts таблицы, сохранив все изменения записей в PostRevisions таблице перед обновлением Post строк. PostRevision сущности должны хранить все Post столбцы сущностей вместе со столбцом RevisionId.

Я хочу сопоставить это с помощью Fluent NHibernate. PostRevision сущности должны отражать свойства Post сущностей, но без необходимости поддерживать два класса сущностей и классы сопоставления.

Как мне для этого разработать свои сущности и сопоставления?

Желаемый псевдокод для редактирования сообщения

var post = _unitOfWork.CurrentSession.Get<Post>(id);
var postRevision = new PostRevision(post);

post.Content = "changed value"; // change some things here

_unitOfWork.CurrentSession.Save(post);
_unitOfWork.CurrentSession.Save(postRevision);

_unitOfWork.Commit();

PostRevision класс композиции:

public class PostRevision
{
    public virtual Guid Id { get; private set; }
    public virtual Post Post { get; set; }

    public PostRevision()
    {
    }

    public PostRevision(Post post)
    {
        this.Post = post;
    }
}

Возможное свободное отображение:

public class PostRevisionMap : ClassMap<PostRevision>
{
    public PostRevisionMap()
    {
        Id(x => x.Id);
        Component(x => x.Post); // will something like this work?
    }
}

person Petrus Theron    schedule 24.04.2011    source источник


Ответы (1)


связь (я думаю), которую вы ищете, - "один-ко-многим": у сообщения много PostRevisions.
PostRevision ссылается на одно сообщение.
Поэтому я думаю, что правильным отображением на стороне Post будет

HasMany(x=> x.PostRevisions);  

и на стороне PostRevision:

References(x=> x.Post).  

см. nHibernate docs, чтобы получить более полное представление о том, как сопоставить эти ассоциации. .

Редактировать
Если вы хотите вести запись истории для каждой ревизии вашего сообщения, у вас есть 2 варианта:
1. добавить логическое поле «IsHistoric» в свой класс постов. Всякий раз, когда сообщение редактируется, вы не изменяете сам объект сообщения, а скорее отмечаете его как «IsHistoric = true» и создаете новый объект сообщения, который представляет измененное сообщение. Это метод, который я использую в своем проекте.
2. Создайте класс HistoricPost, унаследованный от Post. Вам не нужно повторять сопоставление, и вы можете использовать отдельную таблицу для этого класса (стратегия «таблица на подкласс»).
см. здесь для получения дополнительных сведений.
Я думаю, что вы также можете указать другой столбец Id для дочернего класса, используя Id(x => x.SomeOtherId); в сопоставлении 'HistoricPost '. Я не пробовал, так что не уверен на 100%.

person J. Ed    schedule 24.04.2011
comment
@sJhonny, как должно выглядеть сопоставление классов для PostRevisions, если я не хочу дублировать все свойства сопоставления? - person Petrus Theron; 25.04.2011
comment
Сопоставление будет иметь ровно 2 строки - одну для сопоставления идентификатора (что-то вроде Id (x = ›x.Id)), а другую - ту, которую я опубликовал. Вот и все. поскольку объект Post уже отображается сам по себе, вам не нужно отображать его снова. - person J. Ed; 26.04.2011
comment
@sJhonny, я уточню свой вопрос. Post в PostRevision должен быть объектом-значением, а не ссылкой на сущность. Перед обновлением записи Post ее текущее значение сохраняется в таблице PostRevisions. - person Petrus Theron; 26.04.2011
comment
извините, я этого не осознавал. в этом случае я вижу 2 варианта: либо создать новую сущность (PostHistory), которая наследуется от Post, либо указать ее в классе PostRevision (см. этот вопрос - stackoverflow.com/questions/2041567/). Другой вариант - добавить логическое поле в класс Post - IsHistoric (или что-то подобное). При каждой ревизии вы фактически должны создавать новый экземпляр Post и обновлять поле IsHistoric существующего. - person J. Ed; 26.04.2011
comment
@sJhonny, для варианта 1, как PostHistory наследовать сопоставления для Post без дублирования кода? - person Petrus Theron; 26.04.2011
comment
Ах! Я не знал, что он может обрабатывать отдельные таблицы для каждого подкласса. Укажите это как свой ответ, и я отмечу его как принятый. - person Petrus Theron; 26.04.2011
comment
@sJohnny, Могу ли я отключить идентификатор родительского класса, чтобы у подкласса был собственный идентификатор? - person Petrus Theron; 26.04.2011