0

I'm having a serious issue with Entity Framework and I can't tackle it down. I have 2 entities, a chapter and a header, the header is linked to a chapter by using navigation properties.

[Table("T_CHAPTER")]
public class Chapter : EntityBase<int>
{
    [Required]
    [Column(Order = 1)]
    public string Name { get; set; }
}

[Table("T_HEADER")]
public class Header : EntityBase<int>
{
    [Required]
    [Column(Order = 1)]
    public string Name { get; set; }

    [Required]
    [Column(Order = 2)]
    public virtual Chapter Chapter { get; set; }
}

So far, nothing excotic here. Now, I want to tell that I'm using a Unit Of Work and a repository pattern, but I don't think that does mind.

First I'll add a record in the Chapters if it doesn't exists, that done with this code:

private Chapter CreateChapter(string chapter)
{
    var retrievedChapter = UnitOfWork.ChapterRepository.Get(x => x.Name.Equals(chapter, StringComparison.InvariantCultureIgnoreCase));

    if (retrievedChapter == null)
    {
        UnitOfWork.ChapterRepository.Insert(new Chapter { Name = chapter });
        UnitOfWork.Commit();

        retrievedChapter = UnitOfWork.ChapterRepository.Get(x => x.Name.Equals(chapter, StringComparison.InvariantCultureIgnoreCase));
    }

    return retrievedChapter;
}

The Insert method is the following:

public virtual void Insert(TEntity entity)
{
    if (OnBeforeEntityInsert != null)
    { OnBeforeEntityInsert(this, new RepositoryEventArgs(typeof(TEntity), entity)); }

    DbSet.Add(entity);

    if (OnEntityInsert != null)
    { OnEntityInsert(this, new RepositoryEventArgs(typeof(TEntity), entity)); }
}

And here's the Commit method:

public void Commit()
{
    if (OnBeforeCommit != null)
    { OnBeforeCommit(this, EventArgs.Empty); }

    RepositoriesContexts.Each(context => context.SaveChanges());

    if (OnCommit != null)
    { OnCommit(this, EventArgs.Empty); }
}

Each UnitOfWork has it's own context instance, and all the instances are saved here.

Then I do create a header with the following code:

private Header CreateHeader(Chapter chapter, string header)
{
    var retrievedHeader = UnitOfWork.HeaderRepository.Get(x => x.Name.Equals(header, StringComparison.InvariantCultureIgnoreCase) &&
                                                            x.Chapter.Id == chapter.Id);

    if (retrievedHeader == null)
    {
        UnitOfWork.HeaderRepository.Insert(new Header { Name = header, Chapter = chapter });
        UnitOfWork.Commit();

        retrievedHeader = UnitOfWork.HeaderRepository.Get(x => x.Name.Equals(header, StringComparison.InvariantCultureIgnoreCase) &&
                                                            x.Chapter.Id == chapter.Id);
    }

    return retrievedHeader;
}

Now, let's say that I add a chapter through this method and the ID of the created chapter is 1. I then pass that chapter to the header, but here instead of creating a header with the correct chapter, a new chapter is added and linked to the created header.

It's driving me nuts.

1 Answer 1

2

Each UnitOfWork has it's own context instance, and all the instances are saved here.

You have to share a single context across all repositories.

Sign up to request clarification or add additional context in comments.

5 Comments

Isn't the basic idea of a UnitOfWork that each repository has it's own context instance?
@Complexity no, the basic idea of UnitOfWork is to tie a bunch of repositories together in to a single manageable context instance. DbContext is already a unit of work style class. You may want to abstract it in the form of a interface to expose it to your consumers, but with EF you should not need a 2nd unit of work layer on top of it.
AFAIK, no. The idea of the unit of work pattern is that you can 'write' a single piece of work which contains all inserts, updates, and deletes, in a single action, the commit.
@ScottChamberlain thanks for your answer, but it there any drawback when implementing my own UnitOfWork over the DbContext instance?
@Complexity the only drawback I see is you are re-inventing the wheel, why write a UnitOfWork when EF gives you a UnitOfWork pre-made.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.