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 всегда вызывается с новым потоком, у него всегда будет новое значение (другими словами, каждый раз вызывайте конструктор)