Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

entity framework + repository + unit or work question

I'm thinking about starting a new project using EF 4 and going through some articles, I found an article about EF with repository pattern and unit of work (http://blogs.msdn.com/b/adonet/archive/2009/06/16/using-repository-and-unit-of-work-patterns-with-entity-framework-4-0.aspx)

Looking at that article, it uses the ObjectContext as the UnitOfWork and it passes it to the Repository.

My question is what if I have 2 ObjectContext which mean I will have 2 unit of work, but I actually wants all the operation perform on those 2 context to be one single unit of work, is this scenario possible? I don't want to call save on each context, I'd like it to be transactional .... without using transactionscope ...

For example, I have a context that manages Operation Log and another context that manages Orders. Lets say In my business layer, I have a method called AddOrder(). AddOrder() will use the order context to create a new order, but it will also use the operation log context to create a new operation log entry. Since those are 2 context, I'll have to call save on both context to commit .... maybe the only option is to have only one single context ....

EDIT: I meant 2 context of different types for example: OperationalLogContext and OrderContext.

like image 786
pdiddy Avatar asked Sep 15 '10 02:09

pdiddy


1 Answers

Yep - i believe it's possible.

The kicker is how handle your Repositories.

For example, each Repository should take a Context .. so just create one context and pass it to each repository.

(code please!) Glad u asked :)

public interface IOrderRepository
{
    IQueryable<Order> FindAll();
}

public interface IOperationLogRepository
{
    IQueryable<OperationLog> FindAll();
}

public interface IUnitOfWork
{
    void Commit();
}

.

public class SqlServerContext : ObjectContext, IUnitOfWork
{
    public void SqlServerContext(string connectionString) 
        : base(connectionString)
    {
    }

    public void Commit()
    {
        this.SaveChanges();
    }

    // Your other POCO's and stuff here ..etc..
}

.

public class OrderRepostiory : IOrderRepository
{
    private readonly SqlServerContext _sqlServerContext;
    public void OrderRepostiory(SqlServerContext sqlServerContext)
    {
        _sqlServerContext = sqlServerContext;
    }

    public IQueryable<Order> FindAll()
    {
        _sqlServerContext.Orders;
    }
}

.. and finally, instantiation. Cause your a good boy/girl/rainbow unicorn, you would be using Dependency Injection ..

public class SqlServerRegistry : Registry
{
    public SqlServerRegistry(string connectionString)
    {
        For<SqlServerContext>()
            .HybridHttpOrThreadLocalScoped()
            .Use<SqlServerContext>()
            .Ctor<string>("connectionString")
                .Is(connectionString);

        For<IOrderRepository>().Use<OrderRepository>();
        For<IOperationLogRepository>().Use<OperationLogRepository>();
    }
}

and because the SqlServerContext is defined as HttpOrThreadLocal, it will be instantied ONCE and reused in multiple Repositories.

Don't know or understand DI/IoC ?

then this would also work....

private SqlServerContext _sqlServerContext;
private IOrderRepository _orderRepository;
private IOperationLogRepository _operationLogRepository;

[TestInitialize]
public void TestInitialise()
{
    _sqlServerContext = new SqlServerContext(
             ConfigurationManager.AppSettings["connectionString"]);
    _orderRepository = new OrderRepository(_sqlServerContext);
    _operationLogRepository= new OperationLogRepository(_sqlServerContext);
}

[TestMethod]
public void SomeTest()
{
    // Arrange.
    const int count = 10;

    // Act.
    var orders = _orderRepository.FindAll().Take(10).ToArray();

    // Assert.
    Assert.IsNotNull(orders);
    CollectionAssert.AllItemsAreNotNull(orders);
    Assert.AreEqual(count, orders.Length);
}

once more, that's all untested code which i just typed up, as I was thinking about answering this question.

HTH.

like image 164
Pure.Krome Avatar answered Nov 15 '22 08:11

Pure.Krome