Коллега пришла ко мне сегодня с ошибкой с кодом, который работал в Windows XP, но не работает в Windows 7:
Пользователь не смог войти в систему 'SalesOrdersystem'
Моя психическая отладка сказала мне, что он выполняет запрос к закрытому соединению с базой данных или что он забыл открыть.
Начиная с ADO2.6, в Windows Vista значение по умолчанию PersistSecurityInfo
в строке подключения False
, а не True
.
До Windows Vista строка подключения, такая как:
Data Source=deathstar;User ID=SalesOrderSystem;Password=password1
, сохраняла пароль в строке подключения после открытия подключения, что делает его эквивалентным:
Data Source=deathstar;User ID=SalesOrderSystem;
Password=password1;PersistSecurityInfo=true
Начиная с Windows Vista, пароль по умолчанию удаляется из свойства ConnectionString
соединения:
Data Source=deathstar;User ID=SalesOrderSystem
, что эквивалентно
Data Source=deathstar;User ID=SalesOrderSystem;
Password=password1;PersistSecurityInfo=false
, который я зналмой коллега испытывал такое поведение при удалении пароля.И затем, пока соединение закрыто, он пытается открыть запрос (т.е. ADOQuery.Open), который без промедления пытается открыть соединение.Но без пароля, сохраненного в строке подключения, он получает свою первоначальную ошибку
Возник вопрос: «Почему вы используете соединение, не открывая его первым?»
Мы отследили егов (многопоточный код), где он использовал соединение, которое впоследствии было освобождено:
псевдокод:
customer := TCustomer.Create(ADOConnection)
ADOConnection.Free;
customer.RefreshFromDatabase;
вместо
customer := TCustomer.Create(DataModule.ADOConnection);
customer.RefreshFromDatabase;
В шутку я предложил, чтобы он мог замаскировать ошибку и оставить потенциальный сбой, изменив строку подключения, включив в нее PersistSecurityInfo=True
:
connectionString := ...+
';PersistSecurityInfo=True';
Какой онdid.
У нас есть некоторый библиотечный код, который внутренне использует объект ADOConnection
.я бы полюбил , чтобы иметь возможность изменить свой код с:
destructor TAsyncFill.Destroy;
begin
...
FreeAndNil(FADOConnection)
end;
на
destructor TAsyncFill.Destroy;
begin
...
FADOConnection.Close;
FADOConnection.ConnectionString := 'This connection object has been freed. Why are you using it?';
FreeAndNil(FADOConnection);
end;
Но я уверен это введетошибки, когда вещи случались работали.
Я имею в виду некое подобие замыкания, где я могу внедрить обработчик OnConnect
в объект подключения:
destructor Destroy;
begin
...
FADOConnection.Close;
FADOConnection.BeforeConnect := {
OutputDebugString('You''re using a connection that''s been freed!');
Windows.Beep(1000, 60000) };
FreeAndNil(FADOConnection);
end;
Но в Delphi нет анонимных обработчиков событий.
Может кто-нибудь придумать способ предупредить людей, когда они используют объект после его освобождения?
Примечание: Я понимаю, что нет поддержки того, что я спрашиваю. Я прошу идей для наилучших возможных взломов - с учетом ограничений реальности.