Question

I have the following code that creates a new bookmark and adds one or more tags to it. If a tag does not already exist it is created and added to the bookmark.

Bookmark bookmark = new Bookmark();
bookmark.Title = request.Title;
bookmark.Link = request.Link;
bookmark.DateCreated = request.DateCreated;
bookmark.DateModified = request.DateCreated;
bookmark.User = _userRepository.GetUserByUsername(request.Username);

IList<Tag> myTags = _tagRepository.GetTags(request.Username);
IList<string> myTagsToString = myTags.Select(x => x.Title).ToList<string>();

foreach (var tag in request.Tags)
{
    if (myTagsToString.Contains(tag))
    {
        Tag oldTag = myTags.SingleOrDefault(x => x.Title == tag);
        bookmark.Tags.Add(oldTag);
    }
    else
    {
        Tag newTag = new Tag();
        newTag.Title = tag;
        newTag.User = _userRepository.GetUserByUsername(request.Username);
        newTag.DateCreated = request.DateCreated;
        newTag.DateModified = request.DateCreated;
        bookmark.Tags.Add(newTag);
    }
}

_bookmarkRepository.Add(bookmark);
_uow.Commit();

I implemented unit of work but I am not sure if I did this correctly. I use the save method followed by a commit. The save method inserts the bookmark and tags to the database and the commit method does an insert to the junction table (bookmarks have many tags and tags have many bookmarks).

So everything is inserted correctly. But if I remove the commit method the bookmark and tags still get inserted. But their is no insert to the junction table. Does this mean these inserts are not in the same transaction since commit is not necessary to save the bookmark and tags to the database? The commit is only necessary to save the relationship between tags and bookmarks.

EDIT:

Repository

public abstract class Repository<T, TEntityKey> where T : IAggregateRoot
{
    private IUnitOfWork _uow;

    public Repository(IUnitOfWork uow)
    {
        _uow = uow;
    }

    public void Save(T entity)
    {
        SessionFactory.GetCurrentSession().SaveOrUpdate(entity);
    }

    public void Add(T entity)
    {
        SessionFactory.GetCurrentSession().Save(entity);
    }

    public void Remove(T entity)
    {
        SessionFactory.GetCurrentSession().Delete(entity);
    }

    public IEnumerable<T> FindAll()
    {
        ICriteria criteriaQuery = SessionFactory.GetCurrentSession().CreateCriteria(typeof(T));

        return (List<T>)criteriaQuery.List<T>();
    }
}

UnitOfWork

public class NHUnitOfWork : IUnitOfWork
{
    public void RegisterAmended(IAggregateRoot entity)
    {
        SessionFactory.GetCurrentSession().SaveOrUpdate(entity);
    }

    public void RegisterNew(IAggregateRoot entity)
    {
        SessionFactory.GetCurrentSession().Save(entity);
    }

    public void RegisterRemoved(IAggregateRoot entity)
    {
        SessionFactory.GetCurrentSession().Delete(entity);
    }

    public void Commit()
    {
        using (ITransaction transaction = SessionFactory.GetCurrentSession().BeginTransaction())
        {
            try
            {
                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                throw;
            }
        }
    }
}

BookmarkRepository

public class BookmarkRepository : Repository<Bookmark, int>, IBookmarkRepository
{
    public BookmarkRepository(IUnitOfWork uow)
        : base(uow)
    {
    }
}

UPDATE: I changed NHUnitOfWork to this:

public class NHUnitOfWork : IUnitOfWork
{
    private ITransaction _transaction;

    public void RegisterAmended(IAggregateRoot entity)
    {
        SessionFactory.GetCurrentSession().SaveOrUpdate(entity);
    }

    public void RegisterNew(IAggregateRoot entity)
    {
        SessionFactory.GetCurrentSession().Save(entity);
    }

    public void RegisterRemoved(IAggregateRoot entity)
    {
        SessionFactory.GetCurrentSession().Delete(entity);
    }

    public void BeginTransaction()
    {
        _transaction = SessionFactory.GetCurrentSession().BeginTransaction();
    }

    public void Commit()
    {
        using (_transaction)
        {
            try
            {
                _transaction.Commit();
            }
            catch (Exception ex)
            {
                _transaction.Rollback();
                throw;
            }
        }
    }
}

So I can use it like this:

_uow.BeginTransaction();

Bookmark bookmark = new Bookmark();
bookmark.Title = request.Title;
bookmark.Link = request.Link;
bookmark.DateCreated = request.DateCreated;
bookmark.DateModified = request.DateCreated;
bookmark.User = _userRepository.GetUserByUsername(request.Username);

IList<Tag> myTags = _tagRepository.GetTags(request.Username);
IList<string> myTagsToString = myTags.Select(x => x.Title).ToList<string>();

foreach (var tag in request.Tags)
{
    if (myTagsToString.Contains(tag))
    {
        Tag oldTag = myTags.SingleOrDefault(x => x.Title == tag);
        bookmark.Tags.Add(oldTag);
    }
    else
    {
        Tag newTag = new Tag();
        newTag.Title = tag;
        newTag.User = _userRepository.GetUserByUsername(request.Username);
        newTag.DateCreated = request.DateCreated;
        newTag.DateModified = request.DateCreated;
        bookmark.Tags.Add(newTag);
    }
}

_bookmarkRepository.Add(bookmark);
_uow.Commit();

I added a begin transaction to the NHUnitOfWork implementation. This means I need to call _uow.BeginTransaction() before any select or insert and in the end call _uow.Commit(). This seems to work if I look at NHibernate Profiler. If this is wrong please tell me :)

Was it helpful?

Solution

Your Save methods are not executed inside a transaction, because you close and open the transaction in the Commit method.

The correct implementation would be to start the transaction before calling Save.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top