500+ FAQ по Delphi

Перейти на: Главную | Индексную | Предыдущую | Следующую страницу


Что нужно сделать для нормальной работы в одноранговой сети с базами Paradox?

BDE Config/Admin - нa вклaдке System устaнови LOCAL SHARE в TRUE!

Здесь комментарий -

В Help параметр LOCAL SHARE описан как:

AA> === Cut ===
AA> The ability to share access to local data between an active BDE
AA> application and an active non-BDE application. Set to TRUE if you need to
AA> work with the same files through both a BDE and a non-BDE application at
AA> the same time. (It is not necessary to set LOCAL SHARE to TRUE if you do
AA> not need to have both applications open at the same time.) Default: FALSE.
AA> === Cut ===
Дaк читaл я вышеизложенное, и рaсценивaю его кaк тумaнопускaтельство. А подозревaю, что просто у BDE для скорости есть свой внутренний кэш (или, может, мехaнизм блокировок в пaмяти), и для двух приложений нa одном компьютере оно всё делaет хорошо, a вот если приложение нaходится нa другом компьютере (и лезет в БД через другую копию BDE), то у него есть доступ только к фaйлaм нa диске (кaк и у non-BDE application).

Скорее всего, борлaнд отключaет эти хитрости у сетевых дисков. Hо для локaльного дискa, который рaсшaрен по сети, он этого, похоже, не сделaл :(

И BDE нa фaйл-сервере не зaботится о прaвильных индексaх и блокировкaх нa диске (т.е. не ожидaет, что кто-то мог испрaвить индекс, покa оно ворон считaло).

А этa устaновкa зaстaвляет его рaботaть по стaрым пaрaдоховым соглaшениям.

Что и требовaлось.

PS. Инaче говоря, следует считaть, что network is non-BDE application, и тогдa это не есть бaгa :)

Dmitry Shikhman (Дмитрий Шихман)
(2:468/13.32)

Как сделать так, чтобы в DBGrid напротив некоторых строк можно было бы галочку поставить?

Hу примерно тaк (лишнее мaло-мaло порезaл, больно много его, но идея виднa :)

нa сервере - тaблицa Advertis.DB, первичный ключ ID - autoincrement.

Ha локaльном диске - тaблицa Founds.DB, с полем Advertis: integer, по которому есть индекс, и tblFounds.IndexFieldNames = 'Advertis'.

Ha гриде:

=== cut ===

procedure TMainForm.dbgWorkDblClick(Sender: TObject);
begin
TriggerRowSelection;
end;

procedure TMainForm.TriggerRowSelection;
begin
if dmFile.AdvertisCount <> 0 then
begin
with dmFile do if not tblFounds.FindKey([tblAdvertisID.Value]) then
begin
tblFounds.AppendRecord( [tblAdvertisID.Value] );
end
else
begin
tblFounds.Delete;
end;
dbgWork.Refresh;
end;
end;

procedure TMainForm.dbgWorkDrawColumnCell(Sender: TObject;
const Rect: TRect; DataCol: Integer; Column: TColumn;
State: TGridDrawState);
begin
if DataCol = 0 then with dmFile, dbgWork.Canvas do
begin
FillRect(Rect); {clear the cell}
if tblFounds.FindKey( [tblAdvertisID.Value] ) then
begin
TextOut(Rect.Left, Rect.Top, '?');
end
else
begin
TextOut(Rect.Left, Rect.Top, 'o');
end;
end;
end;

=== cut ===

Окaзывaется, я переопределял рисовaние гридa, a не вычислял поле. Hе помню точно, но кaжется, чтобы не перечитывaть тaблицу нa кaждый дaблклик, a толькоперерисовaть грид.

А колонкa для гaлки в гриде определялaсь тaк:

=== cut ===
with dmFile, dbgWork.Columns do
begin
BeginUpdate;
Clear;

{check mark}
nc := Add;
nc.Width := 14;
nc.Font.Name := 'Wingdings';
nc.Font.Size := 11;
nc.Alignment := taRightJustify;
nc.Title.Caption := 'y';
nc.Title.Font.Name := 'Wingdings';
nc.Title.Font.Size := 10;
nc.Title.Alignment := taCenter;

[skip определения остaльных колонок]

EndUpdate;
end;
=== cut ===

Вроде всё.

Hу, кaк нaпечaтaть/обрaботaть только помеченное, сaм рaзберёшься. У меня тaм нaкручено чего-то с фильтрaми, думaю, можно проще.

Что кaсaется других способов - можно вместо временной тaблицы попользовaть список, мaссив или in-memory table.

Dmitry Shikhman (Дмитрий Шихман)
(2:468/13.32)

Как в Delphi сбросить кэш БД на диск?

uses BDE {в Delphi 1.x не помню, но вроде bdeprocs};

dbiSaveChanges

На Delphi 1.x (16bit) дополнительно вызовите эту процедуру -

procedure DropCache; assembler;
asm
mov ah,$0D
int $21
end;

Boris Podchezertseff
(2:5020/898.15)

В процессе работы программы изменилась структура БД (alter table etc.). Программа продолжала успешно открывать таблицы, но запросы посылались в соответствии со старой схемой данных. Как исправить?

В установках BDE (Configuration utility или BDEAdmin) можно выставить SCHEMA CACHE = FALSE (не кэшировать схему данных).

Но в некоторых случаях ошибки такого рода все-таки происходят. В таком случае необходимо воспользоваться методом TDatabase.FlushSchemaCache после каждого изменения метаданных.

Alex Kaganoff
(2:5030/82.50)

------------

Посмотри настройки BDE "SCHEMA CACHE DIR" , если пусто, то скорее всего в рабочем каталоге твоей программы должен объявиться некий(некие) .ini файл(ы), в котором хранятся указания на файлы, в которых храниция информация о кэше схемы БД. Удали их.

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

Sergey Klochkovski
(2:5080/60.3)

Можно ли подсоединиться к другой БД из SP?

В DB2 можно. Если хочешь все корректно делать, ставь distributed unit of work для всех соединений. Такое с гарантией отработает.

Lilya A. Kozlenko
li@relex.ru

Как правильно работать с SQLAnywhere через BDE -> ODBC -> SAW?

Необходимо поставить patch на ODBC-драйвер (доступен на www.sybase.com);
Достаточно флажка Keys in SQL Statistics в ODBC-администpатоpе, для того, чтобы исчезла необходимость ставить втоpичные индексы по ключевым полям;
Если Вы пользуетесь BDE 3.5, то обновите ее до версии 4.x, или замените idodbc.dll на тот, который идет в комплекте поставки BDE 3.0.

Oleg Saladaev
(2:5015/51.6)

Как при вводе информации в БД автоматически вставлять SEQUENCE?

Если добавление через оператор INSERT ( в TQuery), то прямо там пишешь, как в плюсе ("... Values (My_seq.nextval, ...").

Если добавление идет через TQuery c RequestLive=true, то в BeforeInsert сделай запрос через TQuery (select myseq.nextval from dual) и заноси значение в свое поле.

Alexander Medvedev
(2:5010/3.88)

При использовании MS SQL Server 6.5 в NT Performance Monitor исчезли все датчики, кроме SQL. Как лечить?

Кто виноват:
Дело в следующем - при инсталляции NT страна была поставлена US, затем сменена на Russia. В реестре для Perfomance Monitor существует (может существовать) сколь угодно подуровней с названием счетчиков и описанием к ним. При инсталляции все естестественно ставилось в ветвь 409 (US), а ветви 419 (Russia) просто не было. Потом default location была сделана Russia. Perfomance Monitor не мог найти 419 и брал все счетчики из 409. Hо тут пришел SQL и как умная программа при инсталляции создал ветвь 419 и запихал туда свои счетчики. Теперь Perfomance Monitor видит что текущая locale 419, в реестре она есть и берет оттуда счетчики, а они там только для SQL естественно.

Что делать:
Запускаешь regedit (regedt32), находишь где лежат описания счетчиков. Точно я не помню, под рукой NT нет, но примерно так -

HKEY_LOCAL_MACHINE/System/CurrentControlSet/Control/PerfLib/409 (419).

В каждом разделе по два ключа - список названий счетчиков и список их описаний. Заходишь в 409, открываешь ключ для изменений и при помощи Ctrl-Ins копируешь его содержимое в буфер обмена и жмешь Cancel. Теперь идешь в 419 открываешь тот же ключ, идешь в начало списка и при помощи Shift-Ins вставляешь, жмешь Ok. Так надо сделать и для названий счетчиков и для их описания.

Для полного счастья можно и SQL счетчики из 419 в 409 (в конец) скопировать.

Dmitry Lubimkov
(2:5038/7.26)

Подскажите как правильно показать на экpане и сохранить в базе картинку формата JPEG?

Я делал так (это кусок компонента):

if Picture.Graphic is TJPegImage then
begin
bs:=TBlobStream.Create(TBlobField(Field),bmWrite);
Picture.Graphic.SaveToStream(bs);
bs.Free;
end
else if Picture.Graphic is TBitmap then
begin
Jpg:=TJPegImage.Create;
Jpg.CompressionQuality:=...;
Jpg.PixelFormat:=...;
Jpg.Assign(Picture.Graphic);
Jpg.JPEGNeeded;
bs:=TBlobStream.Create(TBlobField(Field),bmWrite);
Jpg.SaveToStream(bs);
bs.Free;
Jpg.Free;
end else Field.Clear;

Alex Gorbunov
(2:465/85.4)

Какие есть рекомендации по использованию Apollo SDE?

1. При работе с Аполло (если у тебя базы используются и досовскими задачами) - то в dbgrid'e поставь значение

Font->Charset = OEM_Charset.

И не забудь сразу после открытия базы вызывать метод Apollo1.SetTranslate(True). Если твое приложение будет работать с базами одновременно с досовскими, то советую перед открытием баз вызывать метод

Apollo1.SysProp( SDE_SP_SETOBUFFER, Pointer( 0 ) );

для отключения буферизации операций чтения/записи в базы.

2. Если ты пишешь приложение, которое будет использовать базы только в кодировке Windows (CP1251), то тебе достаточно будет указать в dbgrid'e значение

Font->Charset = Russian_Charset.

Roman Procopovich
(2:5030/254.201)

-------------

Если базы в 866 кодиpовке, то:

1. Использование TTable + TApollo:

=== Cut ====
TTable.Open;
TApollo.SetTranslate(True);
TTable.Refresh;
=== Cut ====

2. Использование TApTable:

=== Cut ====
TApTable.Open;
TApTable.SetTranslate(True);
TApTable.Refresh;
=== Cut ====

И вместо закоpючек бyдyт pодные pyсские бyквы. Пpавда, только пpи выполнении пpогpаммы. В дизайнеpе на этапе пpоектиpования псевдогpафика так и останется.

Alexey Kogan
(2:5064/5.30)

Если в транзакции изменена какая-то таблица, то для другого пользователя блокируется вся таблица, до окончания транзакции. Как лечить?

По умолчанию, оператор UPDATE в MS SQL Server пытается поставить эксклюзивную табличную блокировку. Вы можете обойти это, используя ключевое слово FROM в сочетании с опцией PAGLOCK для использования MS SQL Server страничных блокировок вместо эксклюзивной табличной блокировки:

UPDATE orders SET customer_id=NULL FROM orders(PAGLOCK) WHERE customer_id=32;

Блокиpовка на всю таблицу пpи UPDATE ставится только в том случае, если по пpедикату нет индекса. Так, можно пpосто пpоиндексиpовать таблицу orders по полю customer_id, и не забывать делать UPDATE STATISTIC, хотя будет работать и с PAGLOCK. Просто не факт, что UPDATE всегда делает табличную блокировку.

Igor Lemeshko
igor@amanat.alma-ata.su

Как сменить пароль (master password) для таблицы Paradox?

Пожалуйста:

var
db : TDatabase;
Desc : CRTblDesc;
begin
db := PriceTable.OpenDatabase;
FillChar( Desc, SizeOf( Desc ), #0 );
StrCopy( Desc.szTblName, PChar( PriceTable.TableName ) );
StrCopy( Desc.szTblType, szParadox );
StrCopy( Desc.szPassword, 'password' );
Desc.bProtected := TRUE;
Check( DbiDoRestructure( db.Handle, 1, @Desc, nil, nil, nil, FALSE ) );
end;

Садохин Дмитрий (SDV)
vita@transit.samara.ru

------------

Блокиpовка на всю таблицу пpи UPDATE ставится только в том случае, если по пpедикату нет индекса. Так, можно пpосто пpоиндексиpовать таблицу orders по полю customer_id, и не забывать делать UPDATE STATISTIC, хотя будет работать и с PAGLOCK. Просто не факт, что UPDATE всегда делает табличную блокировку.

Igor Lemeshko
igor@amanat.alma-ata.su

При обращении к memo-полю из BDE возникает ошибка "Memo too large". Как лечить?

В BDE есть крутая ошибка, достаточно известная всем, кроме Borland'a. Поскольку они ее еще с 1й Delphi не исправили.

Этот баг проявляется как Access Violation в программе при обращении к таблице IB, которая содержит более одного поля типа VARCHAR (или CHAR) размером > 255. Причем, первое поле меньшего, а второе большего размера. Если поменять местами поля или сделать их одного размера, то все нормально.

Эффект имеет место только с IB, вроде.

Вадим Миллер
miller@demo.ru

Хочу шапку в TDBGrid. Как сделать?

Уже реализовано в виде вот этого компонента - © Andre

unit bdbgrid;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Grids, DBGrids, Math;

type
TOnDrawTitleEvent = procedure(ACol : integer; ARect : TRect; var TitleText : string) of object;

TBitDBGrid = class(TDBGrid)
private
FBitmapBrowse : TBitmap;
FBitmapEdit : TBitmap;
FBitmapInsert : TBitmap;
FBitmapFill : TBitmap;
FRealTitleFont : TFont;
FOnDrawTitle : TOnDrawTitleEvent;
FResizeFlag : boolean;
{ Private declarations }
procedure SetRealTitleFont(Value : TFont);
procedure UpdateTitlesHeight;
protected
procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
{ Protected declarations }
public
constructor Create(AOwner : TComponent);override;
destructor Destroy; override;
{ Public declarations }
published
property OnDrawTitle : TOnDrawTitleEvent read FOnDrawTitle write FOnDrawTitle;
property RealTitleFont : TFont read FRealTitleFont write SetRealTitleFont;
{ Published declarations }
end;

procedure Register;

implementation

var
DrawBitmap : TBitmap;

function Max(X, Y: Integer): Integer;
begin
Result := Y;
if X > Y then Result := X;
end;

procedure WriteText(ACanvas: TCanvas; ARect: TRect; DX, DY: Integer; const Text: string; Alignment: TAlignment);
// © Borland function :)
const
AlignFlags : array [TAlignment] of Integer =
( DT_LEFT or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX,
DT_RIGHT or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX,
DT_CENTER or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX );
var
B, R: TRect;
I, Left: Integer;
begin
with DrawBitmap, ARect do { Use offscreen bitmap to eliminate flicker and }
begin { brush origin tics in painting / scrolling. }
Width := Max(Width, Right - Left);
Height := Max(Height, Bottom - Top);
R := Rect(DX, DY, Right - Left - 1, Bottom - Top - 1);
B := Rect(0, 0, Right - Left, Bottom - Top);
end;
with DrawBitmap.Canvas do
begin
DrawBitmap.Canvas.CopyRect(B, ACanvas, ARect);
Font := ACanvas.Font;
Font.Color := ACanvas.Font.Color;
Brush := ACanvas.Brush;
SetBkMode(Handle, TRANSPARENT);
DrawText(Handle, PChar(Text), Length(Text), R,
AlignFlags[Alignment]);
end;
ACanvas.CopyRect(ARect, DrawBitmap.Canvas, B);
end;


constructor TBitDBGrid.Create(AOwner : TComponent);
begin
inherited Create(Aowner);
FRealTitleFont := TFont.Create;
FResizeFlag := false;
end;

destructor TBitDBGrid.Destroy;
begin
FRealTitleFont.Free;
inherited Destroy;
end;

procedure TBitDBGrid.UpdateTitlesHeight;
var
Loop : integer;
MaxTextHeight : integer;
RRect : TRect;
begin
MaxTextHeight := 0;
for loop := 0 to Columns.Count - 1 do
begin
RRect := CellRect(0, 0);
RRect.Right := Columns[Loop].Width;
RRect.Left := 0;
Canvas.Font := RealTitleFont;
MaxTextHeight := Max(MaxTextHeight, DrawText(Canvas.Handle,
PChar(Columns[Loop].Title.Caption),
Length(Columns[Loop].Title.Caption), RRect,
DT_CALCRECT + DT_WORDBREAK)
);
end;
if TitleFont.Height <> - MaxTextHeight then
TitleFont.Height := - MaxTextHeight;
end;

procedure TBitDBGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if MouseCoord(X, Y).Y = 0 then
FResizeFlag := true;
inherited MouseDown(Button, Shift, X, Y);
end;

procedure TBitDBGrid.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
inherited MouseUp(Button, Shift, X, Y);
if FResizeFlag then begin
FResizeFlag := false;
UpdateTitlesHeight;
end;
end;

procedure TBitDBGrid.DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);
var
Indicator : TBitmap;
TitleText : string;
Al : TAlignment;
begin
if not ((gdFixed in AState) and ((ARow = 0) and (dgTitles in Options) and (ACol <> 0))) then
inherited DrawCell(ACol, ARow, ARect, AState)
else
begin
if DefaultDrawing then
begin
DrawEdge(Canvas.Handle, ARect, BDR_RAISEDINNER, BF_BOTTOMLEFT);
DrawEdge(Canvas.Handle, ARect, BDR_RAISEDINNER, BF_TOPRIGHT);
InflateRect(ARect, -1, -1);
Canvas.Brush.Color := FixedColor;
Canvas.FillRect(ARect);
end;
TitleText := Columns[ACol - 1].Title.Caption;
if Assigned(OnDrawTitle) then OnDrawTitle(ACol, ARect, TitleText);
if DefaultDrawing and (TitleText <> '') then
begin
Canvas.Brush.Style := bsClear;
Canvas.Font := RealTitleFont;
if ACol > 0 then Al := Columns[ACol - 1].Title.Alignment
else Al := Columns[0].Title.DefaultAlignment;
WriteText(Canvas, ARect, 2, 2, TitleText, Al);
end;
end;
end;

procedure TBitDBGrid.SetRealTitleFont(Value : TFont);
begin
FRealTitleFont.Assign(Value);
Repaint;
end;

procedure Register;
begin
RegisterComponents('Andre VCL', [TBitDBGrid]);
end;

initialization
DrawBitmap := TBitmap.Create;

finalization
DrawBitmap.Free;

end.

Ilya Andreev
(2:5030/55.28)


Материалы находятся на сайте http://cracklab.narod.ru/faq/


Создатель этого HTML файла не претендует на авторство вопросов/ответов представленных в нём, не отвечает за их содержание и достоверность, а также за последствия использования программных кодов , полученных из этого HTML файла. Также не принимаются претензии относительно не размещённой информации об авторе каждого конкретного FAQ'а. Любые другие вопросы присылайте на bad_guy@cracklab.ru (обращаться к Bad_guy'ю).
Hosted by uCoz