1

只是对 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;永远不会是真的?

谢谢大家的帮助。

4

2 回答 2

1

您已将 _instance 字段归因于 ThreadStatic。这意味着每个线程用于访问它的字段中都有不同的值。如果 GetInstance 总是用新线程调用,它总是有一个新值(换句话说,每次都调用构造函数)

于 2012-07-24T03:02:28.353 回答
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;
        }
}

Set the factory before you begin using any repository objects like so:

postgresqlDB.Factory = new RepoFactory(); 

That enabled me to use repository objects against a single repository instance as verified by having a populated value for the last command after each usage...

RepositoryTableClass.repo.LastCommand
于 2014-02-05T19:59:27.917 回答