2012-07-24 98 views
1

只是有一個關於PetaPoco生成的版本4.0.3的Database.cs代碼的問題。請參見下面的代碼片段:PetaPoco GetInstance()總是返回新的實例?

public partial class postgresqlDB : Database 
{ 
    public postgresqlDB() 
     : base("postgresql") 
    { 
     CommonConstruct(); 
    } 

    public postgresqlDB(string connectionStringName) 
     : base(connectionStringName) 
    { 
     CommonConstruct(); 
    } 

    partial void CommonConstruct(); 

    public interface IFactory 
    { 
     postgresqlDB GetInstance(); 
    } 

    public static IFactory Factory { get; set; } 
    public static postgresqlDB GetInstance() 
    { 
     if (_instance!=null) 
      return _instance; 

     if (Factory!=null) 
      return Factory.GetInstance(); 
     else 
      return new postgresqlDB(); 
    } 

    [ThreadStatic] static postgresqlDB _instance; 

    public override void OnBeginTransaction() 
    { 
     if (_instance==null) 
      _instance=this; 
    } 

    public override void OnEndTransaction() 
    { 
     if (_instance==this) 
      _instance=null; 
    } 
..... 
..... <snip /> 

望着GetInstance()功能,那爲什麼在return new postgresqlDB()永遠不會分配給私有變量_instance

這是不是意味着每次致電GetInstance()都會創建新實例,因爲if (_instance != null) return _instance;永遠不會是真的?

謝謝大家的幫助。

+0

你有CommonConstruct()的代碼嗎?我假設它可能在那裏設置變量 – 2012-07-24 03:03:18

+0

它是由PetaPoco通過TT模板生成的代碼。開箱即用,這就是全部。我只是好奇爲什麼在生成的代碼中沒有'_instance'的賦值。 – Spongebob 2012-07-24 03:52:14

回答

0

我今天遇到了這種行爲,以及PetaPoco。 (帽子對創作者來說很關鍵,因爲它通常是一種樂趣!)。在相關的情況下,我想拉最新的SQL通過PetaPoco過的副本,以便與類似的代碼進行審查:

Console.WriteLine(RepositoryTableClass.repo.LastCommand); 

對我來說,這是始終爲空的OP表明正是原因。線性靜態標記與原始問題是正交的。代碼中設置_instance變量的唯一地方是在事務處理期間。因此,默認情況下會使用和放棄存儲庫的每個實例。 (這可能是爲了避免重複使用單個連接進行多個重疊查詢\結果的問題)

在任何情況下,工廠模式都可用,並可用於強制依賴單個回購實例,如果這是你的願望。嘗試一個超級簡單的工廠類,如:

private class RepoFactory : postgresqlDB.IFactory 
{ 
     private static postgresqlDB repo = postgresqlDB.GetInstance(); 

     public postgresqlDB GetInstance() 
     { 
      return repo; 
     } 
} 

您開始使用任何存儲庫的對象,像這樣之前設置的工廠:

postgresqlDB.Factory = new RepoFactory(); 

這使我能夠使用資源庫對象針對單個存儲庫實例,通過驗證在每次使用後爲最後一個命令填充值...

RepositoryTableClass.repo.LastCommand 
+0

您的方法與我們的方法類似。 – Spongebob 2014-05-27 03:57:37

1

您已將_instance字段歸爲ThreadStatic。這意味着在每個線程使用它來訪問它的領域有一個不同的值。如果GetInstance總是被一個新線程調用,它將總是有一個新值(換句話說,每次調用構造函數)

+0

我明白了。如果'GetInstance()'由於某種原因在同一個線程中多次調用?那麼在這種情況下,在每個調用中它總是會返回一個新的'postgresqlDB'實例? – Spongebob 2012-07-24 03:27:53

+0

從同一個線程,它第一次調用構造函數,然後返回相同的值,我會推薦使用惰性,而不是使用實例字段,雖然... – 2012-07-24 04:20:53

+0

如果我們看看'GetInstance()'實現,在'else返回新的postgresqlDB();'語句,似乎並沒有爲創建的實例設置本地'_instance'變量。所以即使在同一個線程中,它是否也不斷返回'postgresqlDB'的新實例? – Spongebob 2012-07-24 04:40:17