PetaPoco GetInstance()总是返回新实例?

时间:2012-07-24 02:59:20

标签: database orm petapoco

关于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;永远不会成立?

感谢大家的帮助。

2 个答案:

答案 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