2012-07-24 129 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

相关问题