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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With