2010-09-15 71 views
5

我在考慮使用EF 4開始一個新項目,並通過一些文章去,我發現了大約EF的文章與工作(http://blogs.msdn.com/b/adonet/archive/2009/06/16/using-repository-and-unit-of-work-patterns-with-entity-framework-4-0.aspx實體框架+倉庫+單位或工作問題

的倉庫模式和單位看這篇文章,它使用ObjectContext作爲UnitOfWork,並將其傳遞給Repository。

我的問題是如果我有2個ObjectContext這意味着我將有2個工作單元,但我實際上希望在這兩個上下文中執行的所有操作都是單個工作單元,這種情況可能嗎?我不想在每個上下文中調用save,我希望它是事務性的....不使用transactionscope ...

例如,我有一個上下文來管理操作日誌和另一個管理上下文命令。讓我們說在我的業務層,我有一個名爲AddOrder()的方法。 AddOrder()將使用訂單上下文來創建新訂單,但它也將使用操作日誌上下文來創建新的操作日誌條目。由於這些都是2上下文,我將不得不打電話保存上下文提交....也許唯一的選擇是隻有一個單一的上下文....

編輯:我的意思是2不同類型的上下文例如:OperationalLogContext和OrderContext。

回答

12

是的 - 我相信這是可能的。

踢球者是如何處理您的存儲庫。

例如,每個存儲庫應該採用Context ..因此只需創建一個上下文並將其傳遞給每個存儲庫。

(代碼請!)很高興ü問:)

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

..最後,實例化。因爲你的一個好男孩/女孩/彩虹獨角獸,你將使用依賴注入..

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

而且由於SqlServerContext被定義爲HttpOrThreadLocal,它會一次instantied和在多個庫重複使用

不知道或不理解DI/IoC?

那麼這也將工作....

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

一次,那是我剛打完了,因爲我想在回答這個問題的所有未經測試的代碼。

HTH。

+0

謝謝,這有助於很多。所以唯一的辦法是隻有一個上下文......如果我有兩個上下文,那麼我將別無選擇,只能訴諸某種事務機制,這是正確的嗎? – pdiddy 2010-09-15 03:10:23

+0

nope。你可以擁有儘可能多的你想要的。注意到如何用依賴注入,我說HttpScopeOrThreadScope?你可以把它改成singleton(壞主意),或者每次請求一個對象的時候新建一個新實例的默認值。所以這取決於你:)如果你在做第二種方式(我使用測試的例子),那麼是的..你必須手動新增每個上下文,一個接一個。例如'var context1 = new SSC(..); var context 2 = new SSC(...); _or = new OR(context1); _olr =新的OLR(context2);'等.. – 2010-09-15 04:09:44

+0

我不得不更新我的答案 - 我有一個嚴重的錯誤。我用普通的'connectionString'替換了對'new EntityConnection(connectionString)'的引用,因爲如果上下文沒有創建'EntityConection'(而不是傳遞給它),那麼連接並沒有被處理掉。歡呼Ayende Rahien(來自休眠犀牛)爲修復。 – 2010-09-15 10:25:17