0
votes

I want to audit my Posts table by preserving whole record changes to a PostRevisions table before Post rows are updated. PostRevision entities should store all the Post entity columns along with a RevisionId column.

I want to map this with Fluent NHibernate. PostRevision entities should mirror the properties of Post entities, but without having to maintain two entity classes and mapping classes.

How should I design my entities and mappings to do achieve this?

Desired pseudocode for Post Edit

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 composition class:

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;
    }
}

Possible Fluent Mapping:

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

1 Answers

0
votes

the relation (I think) you're looking for is one-to-many: a Post has many PostRevisions.
a PostRevision references a single Post.
Therefore I think the correct mapping on the Post side would be

HasMany(x=> x.PostRevisions);  

and on the PostRevision side:

References(x=> x.Post).  

see the nHibernate docs for a more complete look on how to map these associations.

Edit
If you want to keep a history record for each revision of your post, you have 2 options:
1. add a boolean 'IsHistoric' field to your Post class. Whenever a Post is revised, you don't change the Post object itself, but rather mark it as 'IsHistoric = true' and create a new Post object which represents the revised Post. This is the method I use in my project.
2. Create a 'HistoricPost' class which inherits from Post. You don't have to repeat your mapping, and you can use a seperate table for this class (table-per-subclass strategy).
see here for further details.
I think you can also specify a different Id column for the child class, using Id(x => x.SomeOtherId); in the mapping of 'HistoricPost'. I haven't tried it though, so I'm not 100% sure.