PetaPoco GetInstance() всегда возвращает новый экземпляр?

Просто есть вопрос касательно сгенерированного PetaPoco кода Database.cs из версии 4.0.3. Смотрите ниже фрагмент кода:

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 ответа

Решение

Я столкнулся с таким поведением сегодня и с PetaPoco. (Шляпа снята создателю (ям), так как это, как правило, приятно использовать!). В похожей ситуации я хотел получить копию самого последнего sql, переданного через PetaPoco, чтобы просмотреть его с помощью кода, подобного следующему:

Console.WriteLine(RepositoryTableClass.repo.LastCommand);

В моем случае он всегда был пустым именно по той причине, о которой говорит ОП. Нитостатический маркер ортогонален исходному вопросу. Единственное место в коде, где установлена ​​переменная _instance - это время транзакции. В результате каждый экземпляр репозитория по умолчанию используется и отменяется. (Это может быть во избежание проблем с повторным использованием одного соединения для нескольких перекрывающихся запросов \ результатов?)

В любом случае, фабричный шаблон доступен и может использоваться для принудительного использования одного экземпляра репо, если вы этого хотите. Попробуйте супер простой заводской класс, например:

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

        public postgresqlDB GetInstance()
        {
            return repo;
        }
}

Установите фабрику перед тем, как начать использовать любые объекты репозитория, например:

postgresqlDB.Factory = new RepoFactory(); 

Это позволило мне использовать объекты репозитория для одного экземпляра репозитория, что подтверждается наличием заполненного значения для последней команды после каждого использования...

RepositoryTableClass.repo.LastCommand

Вы связали поле _instance с ThreadStatic. Это означает, что в поле есть разные значения для каждого потока, используемого для доступа к нему. Если GetInstance всегда вызывается с новым потоком, у него всегда будет новое значение (другими словами, каждый раз вызывайте конструктор)

Другие вопросы по тегам