1

我重新發布這個問題,因爲我認爲它有點含糊。 New PostInSingletonScope使用Ninject和Windows服務

我正在使用2分鐘計時器上的Windows服務。我首先使用EF代碼和存儲庫模式進行數據訪問。我正在使用Ninject來注入我的依賴項。我有以下的綁定在我NinjectDependencyResolver類:

ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings["Database"]; 

Bind<IDatabaseFactory>().To<DatabaseFactory>() 
         .InSingletonScope() 
         .WithConstructorArgument("connectionString", connectionStringSettings.Name); 

Bind<IUnitOfWork>().To<UnitOfWork>().InSingletonScope(); 
Bind<IMyRepository>().To<MyRepository>().InSingletonScope(); 

當我的服務運行,每2分鐘我做類似這樣的一些東西:

foreach (var row in rows) 
{ 
    var existing = myRepository.GetById(row.Id); 

    if (existing == null) 
    { 
     existing = new Row(); 

     myRepository.Add(existing); 

     unitOfWork.Commit(); 
    } 
} 

我開始看到一個錯誤在我的日誌,這些日誌說:

成功提交對數據庫的更改,但更新對象上下文時發生錯誤。 ObjectContext可能處於不一致的狀態。內部異常消息:由於對象的鍵值與ObjectStateManager中的另一個對象衝突,因此AcceptChanges無法繼續。在調用AcceptChanges之前確保鍵值是唯一的。

在Windows服務中使用Ninject時,使用InSingeltonScope是否正確?我相信我嘗試過使用InTransientScope等不同的範圍,但我只能讓InSingeltonScope使用數據訪問。錯誤消息與Scope有任何關係還是與它無關?

回答

3

假設服務不是在數據庫上運行的唯一進程,您不應該使用Singleton。在這種情況下會發生什麼情況是,您正在重新使用已緩存實體過期的DBContext。

更好的方法是以類似的方式處理服務的每個計時器執行,就像它是一個web/wcf請求併爲請求創建一個新的作業處理器。

var processor = factory.CreateRowsProcessor(); 
processor.ProcessRows(rows); 

public class RowsProcessor 
{ 
    public Processor(UoW uow, ....) 
    { 
     ... 
    } 

    public void ProcessRows(Rows[] rows) 
    { 
     foreach (var row in rows) 
     { 
      var existing = myRepository.GetById(row.Id); 

      if (existing == null) 
      { 
       existing = new Row(); 
       myRepository.Add(existing); 

       unitOfWork.Commit(); 
      } 
     } 
    } 
} 

根據不同的問題甚至可能會更好地把外循環,併爲每個單列一個新的處理器。

有關工廠的更多信息,請閱讀http://www.planetgeek.ch/2011/12/31/ninject-extensions-factory-introduction/。如果您需要將UoW注入多個類,請查看命名作用域擴展的InCallScope。 http://www.planetgeek.ch/2010/12/08/how-to-use-the-additional-ninject-scopes-of-namedscope/

+0

Remo,我讀過你關於ninject工廠的文章,但似乎這是Ninject 3.0的一部分?我目前正在使用2.2.1.4。還有其他的文章可以看嗎?當我選擇使用Windows服務的Ninject時,我似乎很難理解。任何幫助表示讚賞。 – Thomas 2012-02-09 04:07:24

+0

我建議更新。應該可以沒有任何巨大的改變。否則,你必須手動實現工廠,但其他任何事情都保持不變。 – 2012-02-09 11:08:43

+0

我會考慮Ninject 3作爲一個選項。謝謝。 – Thomas 2012-02-09 17:50:44

2

InSingletonScope將爲您的服務的整個生命週期創建單例上下文=一個上下文。它是very bad solution。因爲上下文包含所有以前時間事件的所有對象,所以它的內存消耗會增加,並且有可能獲得錯誤,就像您目前正在接收的錯誤一樣(但錯誤實際上可能與您的單例上下文無關,但很可能不是)。例外情況表明,您有兩個具有相同關鍵字標識符的不同對象 - 這是不允許的。

代替使用singleton uow,倉庫和上下文使用單例工廠,並且每次都要求從工廠請求新的新實例。在時間事件處理結束時配置上下文。

+0

Ladislav,你能指出一些代碼示例嗎?我在如何使用綁定設置單件工廠方面有些迷茫,這樣每次使用工廠時都會創建對象的新實例。任何幫助深表感謝。 – Thomas 2012-02-09 04:00:28

+0

工廠將簡單地調用您的對象的構造函數。並非所有東西都要注入。工廠的要點是要知道如何創建特定類型的實例。 – 2012-02-09 13:11:09

+0

拉迪斯拉夫,我用這個問題更清楚地描述了我正在嘗試做的事情。 HTTP://計算器。com/questions/9216006/ninject-scope-problems-with-topshelf-ninject-and -ef-code-first – Thomas 2012-02-09 17:49:58