关于PetaPoco从4.0.3版生成Database.cs代码的问题。请参阅下面的代码段:
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 :(得分:1)
您已将_instance字段归因于ThreadStatic。这意味着每个线程用于访问它的字段中有不同的值。如果总是使用新线程调用GetInstance,它将始终具有新值(换句话说,每次都调用构造函数)
答案 1 :(得分:0)
今天我和PetaPoco一起遇到了这种行为。 (帽子是给创作者的,因为它通常很乐意使用!)。在相关的情况下,我想提取一份通过PetaPoco传递的最新sql的副本,以便用以下代码查看它:
Console.WriteLine(RepositoryTableClass.repo.LastCommand);
在我的情况下,正如OP建议的那样,它总是空的。 threadstatic标记与原始问题正交。设置_instance变量的代码中唯一的位置是事务的持续时间。因此,默认情况下会使用并放弃存储库的每个实例。 (这可能是为了避免重复使用单个连接来解决多个重叠查询\结果的问题?)
在任何情况下,工厂模式都可用,并且可用于强制依赖单个repo实例(如果这是您想要的)。尝试一个超级简单的工厂类,如:
private class RepoFactory : postgresqlDB.IFactory
{
private static postgresqlDB repo = postgresqlDB.GetInstance();
public postgresqlDB GetInstance()
{
return repo;
}
}
在开始使用任何存储库对象之前设置工厂:
postgresqlDB.Factory = new RepoFactory();
这使我能够针对单个存储库实例使用存储库对象,并通过在每次使用后为最后一个命令填充值来验证...
RepositoryTableClass.repo.LastCommand