2015-09-28 4 views
2

Мы переносим почти 2 миллиона строк кода из BDE в SQL Server в Delphi XE5 (скоро это будет DX).ADO vs. Firedac quote sign in .Locate

Мы столкнулись с большой проблемой.

Мы используем ADO, но только что были поражены тем, что Microsoft не выполнила .Locate на строку, которая одновременно имеет знаки одиночной кавычки и значки фунта. Пример:

TADOQuery1.Locate('FieldName', '2x4'' 10#', []) 

терпит неудачу с:

Аргументы имеют неправильный тип, находятся вне допустимого диапазона, или находятся в противоречии друг с другом.

Документация Microsoft ADO гласит, что это не удастся. И мы видим, что это происходит в ADODB.pas. Как для простой, так и для одной переменной, которая содержит более одной переменной.

У нас нет возможности делать эти локации в стандартных запросах с помощью строк WHERE из-за того, что они находятся в жестких петлях.

Вопросы: Есть ли проблема с FireDAC? Может кто-то сделать нам одолжение и на самом деле попробовать выше. Locate в FireDac?

Какие неприятные «сюрпризы» могут возникнуть при миграции из ADO в Firedac?

Спасибо.

+0

Вы можете сделать эту услугу самостоятельно - просто получите пробную версию DX Seattle и протестируйте все, что вам нравится за 30 дней. –

+1

. Я использовал квадрантные одинарные кавычки в подобных случаях в прошлом, поскольку кажется, что ADO также хочет, чтобы они были экранированы , Ex. 'TADOQuery1.Locate ('FieldName', '2x4' '' '10 #', [])' – Brian

+0

Цитаты и знаки фунта отклоняются ADO, а не ADODB.pas. В FireDAC код, реализующий Locate, написан на Delphi. И он не заботится о содержании ценности поиска. Там может быть все, что вам нужно. –

ответ

5

Я создал минималистский приложение FireDAC в X Е8, содержащий TFDConnection, TFDQuery и TFDGUIxWaitCursor, с TFDquery, подключенного к TDataSource, TDBGrid и TDBNavigator. Я соединил TFDConnection к базе данных MS SQLServer 2014, и редактировать строку данных, чтобы включить свое тестовое значение

2x4' 10#

в колонке VARCHAR (80).

Вызов .First, затем .Locate из FDQuery успешно расположенной строки, когда я назвал .Locate только на колонке, которая содержит тестовое значение, и когда она была частью вызова два поля.

Таким образом, это, по крайней мере, стоит проверить себя. Вы упомянули, что у вас был XE8 в том же Locate запросе на прошлой неделе.

Что касается других неприятных сюрпризов, я не могу придумать ничего из этого. Все, что я помню, это то, что было благословенное облегчение освобождения от BDE, когда мы бросили его около 2002 года в пользу Sql Server 2000 через драйвер OLEDB + Ado. Я был рад, что мы выбрали сортировку, которую мы сделали, Latin1_General_CI_AI, где CI = нечувствительность к регистру и AI = Accent Insensitive.

Моя основная оговорка о FireDAC заключается в том, что, хотя кажется, что они обрабатывают эти вещи скорее, чем «родные» объекты, такие как TAdoxxx, кажется, что они до сих пор абстрагированы от них, что я подозреваю, что вам может быть трудно получить что-либо официальное об этом в неудачном случае, что вы путешествуете по какой-то проблеме с ним.И, конечно же, сейчас в руках EMBA, которые могут сказать что-то об устранении ошибок (из-за того, что теперь они, похоже, ограничивают обновления исправлений ошибок в подписках на обновление), хотя автор действительно очень активно поддерживает его онлайн.

Btw, я не уверен, какое наблюдение вы основываете на неудаче Microsoft. Я протестировал AdoQuery.Locate с модификацией ADODB.Pas 'GetFilterExpr Я опубликовал в своем ответе на ваш другой q, и он отлично работает, поэтому, возможно, вы основываете его на чем-то другом.

По сути интереса, я решил посмотреть, если объект ADOInt.Pas Recordset может быть использован для похож на Locate, и он может и также отлично работает с поисковым значением 2x4' 10# и с другими образцами тестов я использовал :

procedure TForm1.TestRecordSetFind; 
var 
    Expr : String; 
begin 
    Expr := 'applicant = ' + QuotedStr(edLocate.Text); 
    if cbMultiField.Checked then begin 
    Expr := '(' + Expr + ') and (country = ''EP'')'; 
    end; 
    Memo1.Lines.Add(Expr); 
    AdoQuery1.RecordSet.Find(Expr, 0, adSearchForward, adBookmarkFirst); 
    AdoQuery1.Resync([]); 
end; 

несколько очевидных ограничений делать это таким образом вместо этого, конечно, является то, что RecordSet.Find это процедура, а не функция, возвращающая логическое значение, и что это не чувствительны к регистру (хотя ли это потому, что мой сервер Сопоставление, я не знаю).

+0

Спасибо, MartyA. Вы очень помогли. Мы проверим ваши предложения. Причина, по которой мы не думали, что это возможно в ADO, находится на https://support.microsoft.com/en-us/kb/245408, Microsoft заявляет: «Это некоторые сложные критерии, которые не могут быть обработаны Find или Filter. " и затем перечисляет: Описание = "# 3 Board 4" '"2' x 2''4" ' – Tom