-
Доброго времени суток, Мастера (о:
Подскажите, пожалуйста, по следующей проблеме. Есть некая БД на Access, расположенная в папке с общим доступом с правами на чтение/запись. Есть приложение "просмотрщик" данных, которое с определенным интервалом времени считывает информацию, а так же "редактор" данных, посредством которого информация в базу заносится. Приложения написаны на Delphi 6. Соединение устанавливается посредством ADO (MS Jet 4.0 OLE DB Provider). Суть проблемы: невозможна одновременная работа нескольких пользователей: получаю ошибку подключения к БД. Подскажите, пожалуйста, что дополнительно нужно указывать в строке подключения, или ткните носом, где почитать.
С уважением, ЕВА.
-
Может, настроен эксклюзивный доступ ?
-
По-умолчанию стоит "Share Deny None". Если я правильно читал, то это отсутствие блокировки записи/чтения. Или я не прав?
-
> что дополнительно нужно указывать в строке подключения желательно ничего... чем меньше значений и так по умолчанию устанавливаемых тем меньше вероятность ошибок. по умолчанию должно работать.
> с правами на чтение/запись. а на редактирование? а то впечатление такое, что файл блокировок первым коннектом создается, а у следующего нет прав его изменить (вписать себя)... о и получает тода минимальные. толко на чтение.
-
Гм... Так и есть. А Вы не п\могли бы подсказать где поправить (прочитать)?
-
Возможно, следует сказать, что к общей папке дан полный доступ.
-
Вообщем удалось обнаружить такую деталь: "блокирование" происходит в том случае, если приложение подсоединяется к "локальной базе по сети". Т.е. если запустить приложение на компьютере с установленной БД, указав "сетевой путь" (\\MyPC\MyApp\MyDB.mdb), то с клиентских машин соединение не уставнавливается. Если же запускать "локально" (C:\MyApp\MyDB.mdb), то клиентские машины успешно подключаются. Я понимаю, что глупо на локальной машине указывать сетевой путь, но вдруг пользователь "ткнет". К тому же это наблюдение, которое я пока не могу обосновать, грубо говоря, не могу сказать "не суй пальцы в мясорубку, потому что их отрежет ножом".
Может кто-нибудь дать направление для размышлений?
С уважением, ЕВА
-
Возможно (хотя что тут смотреть) требуется код... Кнопка подключения к БД:
Procedure TDeskTop.TestButtonClick(Sender:TObject);
Begin
DBModule.DBPath:='\\B0000011\Base\DBase.mdb';
DBModule.DBConnect:=True;
If DBModule.DBConnect
Then
TestButton.Caption:='Офигеть! Соединение установлено.'
Else
TestButton.Caption:='Не работает...';
End;
dataModule для тестов с базой:
Unit DBModuleUnit;
Interface
Uses
ADODB,Classes,DB,SysUtils;
Type
TDBModule=Class(TDataModule)
DBConnection :TADOConnection;
Procedure DataModuleCreate(Sender:TObject);
Procedure DBConnectionBeforeConnect(Sender:TObject);
Private
FDBPath :String;
Function GetDBConnect:Boolean;
Procedure SetDBConnect(Value:Boolean);
Procedure SetDBPath(Value:String);
Public
Published
Property DBConnect:Boolean
Read GetDBConnect
Write SetDBConnect;
Property DBPath:String
Read FDBPath
Write SetDBPath;
End;
Var
DBModule :TDBModule;
Implementation
Procedure TDBModule.DataModuleCreate(Sender:TObject);
Begin
FDBPath:='';
End;
Procedure TDBModule.DBConnectionBeforeConnect(Sender:TObject);
Begin
DBConnection.ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;'+
'Data Source=\"'+DBPath+'\";'+
'Persist Security Info=False;'+
'Jet OLEDB:Database Password=001007326';
End;
Function TDBModule.GetDBConnect:Boolean;
Begin
Result:=DBConnection.Connected;
End;
Procedure TDBModule.SetDBConnect(Value:Boolean);
Begin
Case Value Of
True: Begin
DBConnection.Connected:=False;
DBConnection.Connected:=True;
End;
False: DBConnection.Connected:=False;
End;
End;
Procedure TDBModule.SetDBPath(Value:String);
Begin
FDBPath:=Value;
End;
End.
-
> указав "сетевой путь" (\\MyPC\MyApp\MyDB.mdb) > запускать "локально" (C:\MyApp\MyDB.mdb)
> DBModule.DBPath:='\\B0000011\Base\DBase.mdb'; > // DBModule.DBPath:='D:\test\DBase.mdb';
не равнозначно, если конечно там не алиас в расшарке, но пока вывод - по сути делается одно, а интерпритация по несуществующему варианту... т.е. "вывод по кофейной гуще".
-
> указав "сетевой путь" (\\MyPC\MyApp\MyDB.mdb) > запускать "локально" (C:\MyApp\MyDB.mdb)
В данном случае абстрактный пример. Попробую на конкретном... Итак, на 1 машине по адресу "D:\Test\DBase.mdb" лежит БД. В сети она видна как "\\B0000011\Base\DBase.mdb". 1. Если на первой машине приложение соединяется к БД с прописанным путем "D:\Test\DBase.mdb", то другие клиенты (в сети; подключаются к "\\B0000011\Base\DBase.mdb") соединяются к БД успешно. 2. Если на первой машине приложение соединяется к БД с прописанным путем "\\B0000011\Base\DBase.mdb", то другие клиенты (в сети; подключаются к "\\B0000011\Base\DBase.mdb") не соединяются с БД. Получаю ошибку "Невозможно использовать "; файл уже используется". 3. Если сначала к БД подключился клиент (в сети; подключаются к "\\B0000011\Base\DBase.mdb"), а потом присоединяется 1 машина (так же к "\\B0000011\Base\DBase.mdb"), то соединение успешно.
Т.е. подключаясь с "сети" 1 машина создает файл подключений, который недоступен клиентам? Вот все пока что могу придумать. А как обойти даже не знаю.
С уваженем, ЕВА
-
> 2. Если на первой машине приложение соединяется к БД с прописанным > путем "\\B0000011\Base\DBase.mdb", то другие клиенты (в > сети; подключаются к "\\B0000011\Base\DBase.mdb") не соединяются > с БД. Получаю ошибку "Невозможно использовать "; файл уже > используется".
Поправлюсь: "выдают ошибку"
-
> В данном случае абстрактный пример. перенести в потрепаться? абстракциям и флуду там самое место, а не сдесь.
> Итак, на 1 машине по адресу "D:\Test\DBase.mdb" лежит БД. В сети она видна как "\\B0000011\Base\DBase.mdb". еще раз. пусть машина называется B0000011, согласен, но при расшаривании папки Test получить Base без указания его алиасом невозможно. про алиас ты не упоминал... вывод? ты подключаешься к разным базам, а вывод делаешь как будто работаешь с одной. при разных естественно никаких проблем у разных коннектов.
хотя и права у разных юзеров могут быть разными... может ты подключаешься по сети "гостем" хотя и сам к себе. владелец файла блокировок другой, могут быть разные права. хотя... "это слишком сложно чтобы быть правдой, вот с черепахой дело другое..." © смешарики - край земли. первый вариант правдоподобнее.
> Вот все пока что могу придумать. сам смотри в файл блокировок, блокнотом, и проверяй создаются там записи при каждом подключении или нет.
-
> еще раз. пусть машина называется B0000011, согласен, но > при расшаривании папки Test получить Base без указания его > алиасом невозможно. про алиас ты не упоминал... вывод? ты > подключаешься к разным базам, а вывод делаешь как будто > работаешь с одной. при разных естественно никаких проблем > у разных коннектов.
Да, конечно, используется алиас. Чтобы исключить все возможные недопонимания, уточню: открывая общий доступ к папке "D:\Test\" в поле "Общий ресурс" введено значение "Base". В разрешениях для всех ("Все") дан полный доступ ("Полный доступ").
-
тогда еще вариант. у XP ограничение на 10 коннектов извне по сети, допустим 9 у тебя уже чемто/кемто занято... тогда подключение самого к себе тоже вроде как внешнее занимает последний "слот". дальнейшие ведут к отказам -Ю ошибкам подключения.
в этом случае у тебя в event-сах (eventvwr.msc) будет полно ошибок типа TCP - превышен лимит на подключения (точность формулировки не гарантирую)... если найдешь такие, то выход перенести базу на серверную систему, у которой нет подобных ограничений . или "проредить" существующие. (есть еще хакерский вариант, но не будем об этом...)
-
sniknik ©, прошу прощения, я все таки обнаружил ситуацию описанную в [11]. Окончательно запутавшись, решил выделить кусок соединения клиента к БД. Итак. 1. Проект находится по адресу: "D:\DelphiN\Проекты\КаДР\v. 1.1\Управление доступом" 2. База данных находится по адресу: "D:\DelphiN\Проекты\КаДР\v. 1.1\Base" 3. База данных видна в локальной сети: "\\B0000011\Base" 4. Имя файла базы данных: "DBase.mdb" 5. К "\\B0000011\Base" открыт полный доступ DeskTopUnit - главная форма:
Unit DeskTopUnit;
Interface
Uses
Classes,Controls,DBModuleUnit,DBPathUnit,Dialogs,Forms,Graphics,Menus,Messages,
StdCtrls,SysUtils,Variants,Windows;
Type
TDeskTop=Class(TForm)
TestButton :TButton;
AppMenu :TMainMenu;
N1 :TMenuItem;
N2 :TMenuItem;
N3 :TMenuItem;
N4 :TMenuItem;
Procedure TestButtonClick(Sender:TObject);
procedure N2Click(Sender: TObject);
Private
Public
End;
Var
DeskTop :TDeskTop;
Implementation
Procedure TDeskTop.TestButtonClick(Sender:TObject);
Begin
Try
DBModule.DBConnect:=Not DBModule.DBConnect;
If DBModule.DBConnect
Then
TestButton.Caption:='РАЗОРВАТЬ СОЕДИНЕНИЕ'
Else
TestButton.Caption:='НА ЖМИ МЕНЯ';
Except
MessageDlg('А ВОТ ТЕБЕ, РОЖА БУРЖУЙСКАЯ, ДУЛЯ ПРОЛЕТАРСКАЯ!',mtError,[mbOK],0);
End;
End;
Procedure TDeskTop.N2Click(Sender: TObject);
Begin
DBPath.ShowModal;
End;
End.
DBModule - операции с базой данных:
Unit DBModuleUnit;
Interface
Uses
ADODB,Classes,DB,DBPathUnit,SysUtils;
Type
TDBModule=Class(TDataModule)
DBConnection :TADOConnection;
DBQuery :TADOQuery;
Procedure DBConnectionBeforeConnect(Sender:TObject);
Private
Function GetDBConnect:Boolean;
Procedure SetDBConnect(Value:Boolean);
Public
Property DBConnect:Boolean
Read GetDBConnect
Write SetDBConnect;
End;
Var
DBModule :TDBModule;
Implementation
Procedure TDBModule.DBConnectionBeforeConnect(Sender:TObject);
Var
Buffer :String;
Begin
DBConnection.ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;'+
'Data Source='+DBPath.DBPath+';'+
'Persist Security Info=False;'+
'Jet OLEDB:Database Password=0322907';
End;
Function TDBModule.GetDBConnect:Boolean;
Begin
Result:=DBConnection.Connected;
End;
Procedure TDBModule.SetDBConnect(Value:Boolean);
Begin
Case Value Of
True: Begin
If DBConnection.Connected
Then
DBConnection.Close;
DBConnection.Open;
End;
False: DBConnection.Close;
End;
End;
End.
DBPathUnit - параметры приложения
Unit DBPathUnit;
Interface
Uses
Classes,Controls,Graphics,Forms,Dialogs,Mask,Messages,
rxToolEdit,StdCtrls,SysUtils,Variants,Windows;
Type
TAppSettings=Record
DBPath :String[255];
DayCount :Integer;
End;
TDBPath=Class(TForm)
DBPathHint :TLabel;
DBPathValue :TFilenameEdit;
ButtonSave :TButton;
ButtonClose :TButton;
procedure FormCreate(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure ButtonSaveClick(Sender: TObject);
procedure ButtonCloseClick(Sender: TObject);
Private
Function GetDBPath:String;
Procedure SetDBPath(Value:String);
Public
Property DBPath:String
Read GetDBPath
Write SetDBPath;
End;
Var
DBPath :TDBPath;
Implementation
Procedure TDBPath.FormCreate(Sender:TObject);
Begin
DBPathValue.Text:='';
DBPathValue.InitialDir:=ExtractFilePath(ParamStr(0));
DBPathValue.HistoryList.Clear;
DBPathValue.FileName:='';
DBPathValue.DefaultExt:='';
End;
Procedure TDBPath.FormActivate(Sender:TObject);
Begin
DBPathValue.InitialDir:=ExtractFilePath(ParamStr(0));
DBPathValue.HistoryList.Clear;
DBPathValue.DefaultExt:='';
DBPathValue.FileName:=DBPath;
End;
Procedure TDBPath.ButtonSaveClick(Sender:TObject);
Begin
DBPath:=DBPathValue.FileName;
ModalResult:=mrOk;
End;
Procedure TDBPath.ButtonCloseClick(Sender:TObject);
Begin
ModalResult:=mrCancel;
End;
Function TDBPath.GetDBPath:String;
Var
FileSettings :File Of TAppSettings;
AppSettings :TAppSettings;
Begin
AssignFile(FileSettings,ExtractFilePath(ParamStr(0))+'\Settings.cfg');
ReSet(FileSettings);
If IOResult=0
Then
Begin
Read(FileSettings,AppSettings);
CloseFile(FileSettings);
Result:=AppSettings.DBPath;
End
Else
Begin
MessageDlg('Файл конфигурации отсутствует или поврежден.',mtWarning,[mbOk],0);
Result:='';
End;
End;
Procedure TDBPath.SetDBPath(Value:String);
Var
FileSettings :File Of TAppSettings;
AppSettings :TAppSettings;
Begin
AssignFile(FileSettings,ExtractFilePath(ParamStr(0))+'\Settings.cfg');
ReSet(FileSettings);
If IOResult=0
Then
Begin
Read(FileSettings,AppSettings);
CloseFile(FileSettings);
End
Else
Begin
AppSettings.DBPath:='';
AppSettings.DayCount:=1;
End;
AppSettings.DBPath:=Value;
ReWrite(FileSettings);
If IOResult=0
Then
Begin
Write(FileSettings,AppSettings);
CloseFile(FileSettings);
End
Else
MessageDlg('Ошибка записи файла конфигурации.',mtError,[mbOk],0);
End;
End.
Проблема: 1. Если первым подключается сервер (ПК, на котором находится БД), то клиент не подключается Файл блокировок:
B0000011 Admin
2. Если подключается клиент, а потом сервер, то соединение устанавливается у всех корректно. Файл блокировок:
B0000067 Admin B0000011 Admin
На результат не влияет задаваемый на сервере путь к базе данных ("сетевой" или "локальный"). Вот, по-моему, вся информация, имеющаяся на данный момент. Пожалуйста, подскажите как обеспечить корректную работу с БД в многопользовательском режиме (возможно где-то имеется ошибка, которую я не заметил, еще какие-либо рекомендации). Все указанное sniknik'ом проверил. С уважением, ЕВА.
-
Еще раз перечитал вышенаписанное. Проверил такой момент: 1. Подключился к БД с сервером 2. Изменил правила безопасности для файла блокировок DBase.ldb, добавив пользователя "Все" с праввми "Изменить/Чтение и выполнение/Чтение/Запись". 3. Подключился к БД клиентом. Файл блокировок:
B0000011 Admin B0000067 Admin
Т.е. можно сделать вывод, как правильно заметил sniknik, проблема в файле блокировок (посыпаю голову пеплом, ибо про то написали почти сутки назад). Как можно ее решить, если он (файл блокировок) каждый раз создается заново?
-
проблема не в файле блокировок, он то как раз честно делает то, что должен, и то что ему разрешили... проблема в правах. ("обратитесь к администратору сети") а почему у тебя файл с разными юзерами(методами подключения) создается с разными разрешениями, которые по идее они должны наследоваться от папки, на которую говоришь стоит все... х.з. привлекай админа.
-
> проблема не в файле блокировок, он то как раз честно делает > то, что должен, и то что ему разрешили... проблема в правах. >
Да, конечно. Я неверно выразился.
> а почему у тебя файл с разными юзерами(методами подключения) > создается с разными разрешениями, которые по идее они должны > наследоваться от папки, на которую говоришь стоит все... > х.з. привлекай админа.
В разрешениях папки по-умолчанию) прописаны пользователи: 1. SYSTEM 2. Администраторы (B0000011\Администраторы) 3. Пользователи (B0000011\Пользователи) 4. <Моя учетная запись> 5. СОЗДАТЕЛЬ-ВЛАДЕЛЕЦ
Владельцем являются: 1. Администраторы (B0000011\Администраторы) 2. <Моя учетная запись>
Правильным ли решением будет добавить "Все" с правами на, грубо говоря, чтение/запись/изменение?
-
Подразумевается - правильным решением, т.к. добавив указанное выше разрешение проблема исчезла.
-
> На результат не влияет задаваемый на сервере путь к базе данных ("сетевой" или "локальный"). о... а говорил влияет, и различается лиш способом подключения. тогда возможно все проще (нет неоднозначности "подключение > другой юзер"). на сервере просто прогу запускают от админа и созданный ей файл получает его владельцем, "гостям" править такой файл в разрешениях не выставлено. с обратной ситуацией, файл во владельцах имеет "гостя", такой правят все кому не лень админ тоже. и вся "загадка". но тогда получается ты обманывал когда говорил что > расположенная в папке с общим доступом с правами на чтение/запись. общих("все") прав там нет.
-
saNat © (16.04.08 10:52) [17] ну вот, подтверждение ([19]) раньше чем запостил...
-
Чаще всего про "Все" вспоминать не приходилось, потому и заблуждался о "полном доступе". Думаю, вопрос решен. sniknik ©, большое спасибо за уделенное внимание и помошь (о:
С уважением, ЕВА.
|