Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2007.02.18;
Скачать: [xml.tar.bz2];

Вниз

Совместное использование одной таблицы   Найти похожие ветки 

 
DeadMeat ©   (2006-11-20 16:57) [0]

Здравствуйте.
Я в базах новичек, поэтому сильно не бейте (хотя бы не ногами).
Есть:

СУБД Microsoft SQL 2000 (SP3)
ADO (компоненты ADOConnection и ADODataSet)
EhLib (компоненты MemTableEh и DBGridEh)
Таблица (просто список людей)
Несколько пользователей (работники)

Надо:

При совместной работе с одной таблицей двух и более пользователей разруливать ситуацию с обновлением информации.

Понимаю, что сказал бред. Попробую пояснить.
Допустим пользователь ЮЗЕР1 выбрал первую запись для редактирования (первая - это образно, первая сверху). Отредактировал и сохранил обратно в базу (MemTableEh.Edit, MemTableEh.Post, MemTableEh.ApplyUpdates(0)). Если после этого пользователь ЮЗЕР2 решит отредактировать эту же запись, то выскочит ошибка "Не удается найти строку для обновления.......". Погуглив выяснилось, что проблема в том, что после редактирования найти эту запись ЮЗЕР2 уже не может, т.к. критерии поиска уже другие. Соответственно
введя первичный ключ и добавив в AfterOpen задание параметра Update Criteria значением adCriteriaKey проблема решается. Но лишь проблема появления ошибки. Т.е. получается, что ЮЗЕР2 не видя то, что записал в базу ЮЗЕР1 запишет туда что-нить свое. А вот хотелось бы отобразить изменения, которые сделал ЮЗЕР1 для всех остальных пользователей. Вводить дополнительно сетевую часть (передавать всем броадкастом информацию об обновлениях) не очень хочется. Каждый раз делать Requery перед редактированием любой записи тоже. Может есть способ еще? Как определить, что "вот эту" запись изменили, и что "вот эту" запись надо обновить? Пробовал проверять RecordStatus на rsModified - не помогло.

ЗЫ. Вполне вероятно, что гдето написал бред, но я только начал эту область осваивать.

ЗЗЫЫ. Пишу в BDS2006.


 
Sergey13 ©   (2006-11-20 17:01) [1]

А при чем тут MemTableEh? Какова ее роль?

Вопрос об обновлении данных, отредактированных другим юзером, обсуждается каждую неделю. Каждый раз это признается бессмысленной тратой ресурсов в 99.9% случаев.


 
clickmaker ©   (2006-11-20 17:02) [2]


> DeadMeat ©   (20.11.06 16:57)

Знакомая проблема, ага.
Но решений, увы, кот наплакал. Ты их практически почти перечислил. Т.е. либо есть некий сервис, который оповещает остальных, что некто Вася поменял запись 1. После 2 варианта. Либо переоткрытие датасета, либо вообще не используется грид, а например ListView. Тогда можно индивидуально управлять записями по ID.
Еще вариант, если записей не слишком много, и жесткий риалтайм не нужен, то по таймеру обновлять табличку на клиенте.


 
clickmaker ©   (2006-11-20 17:05) [3]

Для особо критичных данных иногда применяют следующее. Грид редактировать запрещают вообще. Только специальной формой. При открытии формы запись блокируется. Все остальные после этого получают либо отлуп, либо предложение открыть инфу для чтения. Эта идея с успехом используется в офисных приложениях (ворд, эксель).
Форма закрылась - блокировку снимаешь


 
DeadMeat ©   (2006-11-20 17:38) [4]


> Sergey13 ©   (20.11.06 17:01) [1]
> А при чем тут MemTableEh? Какова ее роль?

Он для "нормального" отображение данных в DBGridEh. Сортировка, отображение денег, пропорциональная полоса прокрутки ну и еще там по мелочи. С ним проще мне кажется.


> clickmaker ©   (20.11.06 17:05) [3]
> Для особо критичных данных иногда применяют следующее. Грид
> редактировать запрещают вообще. Только специальной формой.
>  При открытии формы запись блокируется. Все остальные после
> этого получают либо отлуп, либо предложение открыть инфу
> для чтения. Эта идея с успехом используется в офисных приложениях
> (ворд, эксель).Форма закрылась - блокировку снимаешь

Ну собсна у меня данные как раз отдельной формой и редактируются. Вот только вопрос как без этого дополнительного сервиса заблокировать запись, чтобы ЮЗЕРх это "понял". Т.е. как другим пользователям "объяснить", что "вот эта" запись заблокирована. Думаю осуществив этот механизм, можно сделать обновление именно "этой" записи после снятия блокировки.

В любом случае, благодарю за ответы.... Если есть еще мысли - буду рад.


 
clickmaker ©   (2006-11-20 17:42) [5]


> Т.е. как другим пользователям "объяснить", что "вот эта"
> запись заблокирована. Думаю осуществив этот механизм, можно
> сделать обновление именно "этой" записи после снятия блокировки.

поле завести в таблице. Типа user_id или session_id или вообще spid (зависит, как у вас там работа с пользователями)
Если оно не нулевое, значит запись занята


 
DeadMeat ©   (2006-11-20 23:16) [6]


> clickmaker ©   (20.11.06 17:42) [5]
> поле завести в таблице. Типа user_id или session_id
> или вообще spid (зависит, как у вас там работа с пользователями)Если
> оно не нулевое, значит запись занята

А... Другими словами все надо делать ручками. Понятно. Я просто думал есть какие способо через методы/свойства ADO и самого MSSQL. Но по всей видимости быстрее и проще всего будет руками все организовать.
Ну чтож... раз другого выхода нет - будем делать так.
Большое спасибо за информацию...


 
Kolan ©   (2006-11-20 23:22) [7]

Я тоже новичок в бд, но разве это не забота сервера разрулить ситуацию?


 
DeadMeat ©   (2006-11-20 23:29) [8]


> clickmaker ©   (20.11.06 17:42) [5]
> поле завести в таблице.

Или я просто под вечер не соображаю или что. Но вот щас подумал и вопрос возник.
Вот заведу я это поле в таблице. Каждая запись будет иметь еще одно дополнительное поле. ЮЗЕР1 открыл запись для редактирования. Перед этим записали в это поле 1 (например). Как ЮЗЕР2 сможет считать значение этого поля, когда оно изменилось? Опять же вопрос про обновление данных. Целиком обновлять или как? Или просто завести отдельную таблицу не большого размера и в ней хранить запись типа:

TableName | RecordNum
---------------------
TABLE1    | 1
TABLE2    | 3

Смысл в том, что таблица не большая и вполне можно (хотя мне и не нравится такой способ) делать Requery или даже закрывать и открывать по новой датасет.

Что посоветуете?


 
ЮЮ ©   (2006-11-21 04:04) [9]


> Таблица (просто список людей)
> Несколько пользователей (работники)


Как вообще возникает ситуация, что 2 разных работника пытаются одновременно ввести совершенно разную информацияю для просто человека? Даже если они не пересекутся по времени, то информация с точки зрения одного из работников будет неверная.


 
DeadMeat ©   (2006-11-21 08:38) [10]


> ЮЮ ©   (21.11.06 04:04) [9]

Ну тут несколько иначе. ЮЗЕР1 сделал запись. Посидели... поболтали. Тут ЮЗЕР1 просит ЮЗЕР2 сделать еще изменения, которые он забыл сделать. А просит, потому что ему надо выйти. Ну просто попросил. Вот и явный пример. Это только один пример. Но основная проблема тут в принципе в том, чтобы отобразить сделанные изменения.


 
Sergey13 ©   (2006-11-21 08:58) [11]

> [10] DeadMeat ©   (21.11.06 08:38)

А EhLib у тебя какая? Щас почитал про 4, там вроде МемТабл - это практически некий аналог CDS, раньше вроде был попроще (но и с тем я не работал 8-). Т.е. непонятно как (механизм) изменяется база.
Плюс к этому, почему после изменения одним юзером другой не может изменить ту же запись? Первичный ключ меняется что-ли? Если запись просто изменена и не закомичена, то должно вроде бы другое сообщение вылезти (типа: запись была изменена другим пользователем).


 
DeadMeat ©   (2006-11-21 09:57) [12]


> Sergey13 ©   (21.11.06 08:58) [11]

EhLib 4.1 Build 4.1.4 Russian version
Когда покупал на тот момент была последней (покупал не давно).


> Плюс к этому, почему после изменения одним юзером другой
> не может изменить ту же запись?

Сейчас ЮЗЕР2 может изменить запись, скорректированную ЮЗЕР1. Update Criteria равный adCriteriaKey и первичный ключ спасли. Без этого было только то сообщение, которое я привел ("Не удается найти строку для обновления......."), ведь ЮЗЕР2 уже не может найти ту запись, т.к. без ключа поиск можно было сделать лишь по другим полям, а они уже изменились. Почему не выдавалось другого сообщения - я не знаю.

По поводу механизма, могу лишь сказать, что все изменения (как я понял) отсылаются в DataSetDriverEh скопом (после ApplyUpdates), который затем отслыает их в ADODataSet. Хотя конечно могу и ошибаться. В моем случае, я включил CachedUpdates и FetchAllOnOpen. Т.е. все данные я забираю в память целиком, а не кусками выкачиваю с сервера. Просто на стадии разработки не хотелось заморачиваться с "подкачкой" данных. Мне казалось, что проще пока будет все отладить так, а потом уже (при надобности) делать "подкачку" с сервера порциями. Да и в принципе, основной причиной выбора MemTableEh в связке между DBGridEh и ADODataSet был пропорциональный ScrollBar (вертикальный). Почему то без него я этого добиться не смог.


 
clickmaker ©   (2006-11-21 09:59) [13]


> [8] DeadMeat ©   (20.11.06 23:29)
> Вот заведу я это поле в таблице. Каждая запись будет иметь
> еще одно дополнительное поле. ЮЗЕР1 открыл запись для редактирования.
> Перед этим записали в это поле 1 (например). Как ЮЗЕР2 сможет
> считать значение этого поля, когда оно изменилось?

Ну как... юзер1 поменял что-то, нажал ОК. Запись закоммитилась, блокировку сняли. Теперь она доступна другим, уже с измененными данными.
Другое дело - это оповещение об изменении. Тут уже зависит от критичности по времени.
В билетной системе я делал обновление схемы зала по таймеру. Интервал выбирает пользователь, а может вообще выключить. Но тогда при попытке продать уже занятое место просто вылезет сообщение.


 
Sergey13 ©   (2006-11-21 10:06) [14]

> [12] DeadMeat ©   (21.11.06 09:57)

> Да и в принципе, основной причиной выбора MemTableEh в связке
> между DBGridEh и ADODataSet был пропорциональный ScrollBar
> (вертикальный). Почему то без него я этого добиться не смог.

Скорее всего нужно было закачать все данные возвращаемые запросом на клиента. Т.е. сделать ADODastaSet.Last (или что-то вроде этого - я с АДО не работал). Плюс у гридовского скролбара Tracking выставить в истину.


 
DeadMeat ©   (2006-11-21 10:53) [15]


> clickmaker ©   (21.11.06 09:59) [13]

Общую схему я понял. Встает вопрос об обновлении несколько в другом смысле. Получается, что обновление надо будет все таки делать по таймеру. Это ладно. Смиримся. Вынесем в настройки. Но вот как после обновления попросить сервер вернуть только одну эту измененную запись, а не весь набор целиком?


> Sergey13 ©   (21.11.06 10:06) [14]

Хмм... Спасибо. Учту. Надо будет проверить. Может нужда в EhLib отпадет и вовсе.


 
clickmaker ©   (2006-11-21 11:02) [16]


> Но вот как после обновления попросить сервер вернуть только
> одну эту измененную запись, а не весь набор целиком?

Теоретически можно завести некий сервис для оповещения. Клиент, обновивший запись шлет ему сообщение, что мол обновил запись с ID=233, а сам сервер рассылает его подключенным клиентам.
Но тогда клиент должен отдельным запросом получить только одну эту запись и обновить какой либо список. Грид же обновляется только целиком, поскольку сам он списка не содержит, а просто отображает датасет.
Т.е. нужен датасет, в котором можно поменять 1 запись. Например, датасет в памяти.


 
Bless ©   (2006-11-21 15:52) [17]


> Но вот как после обновления попросить сервер вернуть только
> одну эту измененную запись, а не весь набор целиком?
>


Как-то давно, на этом форуме давали пример:

var
 q:TCustomADODataset;

...
//обновить текущую запись датасета q
 q.UpdateCursorPos;
 q.Recordset.Resync(adAffectCurrent,adResyncAllValues);
 q.Resync([rmExact]);
...


Чтобы обновление работало, как ожидается, возможно, также понадобится настроить ADODataSet1.Properties["Resync Command"].Value


 
Bless ©   (2006-11-21 15:54) [18]


> ADODataSet1.Properties["Resync Command"].Value


q.Properties["Resync Command"].Value конечно же


 
DeadMeat ©   (2006-11-22 16:25) [19]

Спасибо всем ответившим.
Проблему решил так:
1. Обновление всего списка по таймеру или по кнопке в зависимости от настроек.
2. Обновление текущей записи прямо перед открытием ее для редактирования.

Пункт 1 пришлось ввести из-за того, что пользователей не 2, а больше и изменять они могут сразу несколько записей (каждый свою), поэтому приходится обновлять весь список.
ИМХО, нужда в отдельном сервисе появится в том случае, если количество записей перевалит за предел, в результате которого время обновления увеличится секунд так до 5-6. И то, можно обойтись без этого используя подкачку. Обновлять только те записи, на которые сейчас смотрит пользователь. Думаю этого должно хватить...

Спасибо еще раз за советы... Вы мне очень помогли.

ЗЫ. После некоторых поисков по исходникам EhLib нашел тоже самое - обновление только одной записи. Поэтому пока что останусь на нем.


 
MsGuns ©   (2006-11-22 20:27) [20]

>clickmaker ©   (20.11.06 17:02) [2]
>Знакомая проблема, ага.
>Но решений, увы, кот наплакал.
(Дальше не привожу, ибо уже полный бред)

 +

>clickmaker ©   (21.11.06 09:59) [13]
>Ну как... юзер1 поменял что-то, нажал ОК. Запись закоммитилась, блокировку сняли. Теперь она доступна другим, уже с измененными данными.

Если дом построить на трясине, то, действительно, потом придется прилагать гигантские усилия, чтобы он не рухнул и не уплыл..

Я извиняюсь перед Мастером, но все же задам 2 вопроса:

1) Вы знакомы с понятием "транзакции" и "взаимовлияние транзакций" ?
и
2) в какой это предметной области Вы городите всю эту чушь ?

ЗЫ. Обратите все же внимание на пост [9]


 
MsGuns ©   (2006-11-22 20:30) [21]

>DeadMeat ©   (22.11.06 16:25) [19]
>Проблему решил так:
>1. Обновление всего списка по таймеру или по кнопке в зависимости от настроек.

Не делайте этого !

>2. Обновление текущей записи прямо перед открытием ее для редактирования.

Это ничего Вам не даст в плане актуальности этой самой записи.


 
clickmaker ©   (2006-11-23 09:49) [22]


> >clickmaker ©   (21.11.06 09:59) [13]
> >Ну как... юзер1 поменял что-то, нажал ОК. Запись закоммитилась,
> блокировку сняли. Теперь она доступна другим, уже с измененными
> данными.
>
> Если дом построить на трясине, то, действительно, потом
> придется прилагать гигантские усилия, чтобы он не рухнул
> и не уплыл..
>
> Я извиняюсь перед Мастером, но все же задам 2 вопроса:
>
> 1) Вы знакомы с понятием "транзакции" и "взаимовлияние транзакций"
> ?
> и
> 2) в какой это предметной области Вы городите всю эту чушь
> ?


причем тут транзакции?
простой пример: есть заказ. Есть 2 кассира, которые могут его поменять. Например, согласно пожеланию клиента. Если один кассир его откроет и начнет долго и мучительно выяснять у клиента, а что собственно он хочет, то о каких вообще транзакциях и уровнях их блокировок может идти речь?
При этом второй кассир ВООБЩЕ не должен иметь доступ на запись к этому заказу. Надеюсь, понимаете, почему.
Вот такая вот предметная область.
Если у Вас есть решение лучше, чем блокировка на запись с помощью доп. поля - готов выслушать


 
Anatoly Podgoretsky ©   (2006-11-23 09:56) [23]

> clickmaker  (23.11.2006 09:49:22)  [22]

Есть - это резервирование


 
clickmaker ©   (2006-11-23 10:03) [24]


> [23] Anatoly Podgoretsky ©   (23.11.06 09:56)
> > clickmaker  (23.11.2006 09:49:22)  [22]
>
> Есть - это резервирование

?


 
Anatoly Podgoretsky ©   (2006-11-23 10:06) [25]

> clickmaker  (23.11.2006 10:03:24)  [24]

Запись не блокировать, а резервировать для операции, стандартное решение для кассиров.
Сначала запись резервируется, потом редактируется, потом в или возращается из резерва или операция завершается нормально.
Всегда известно, кто и когда и никаких конфликтов и блокировок.


 
clickmaker ©   (2006-11-23 10:10) [26]


> [25] Anatoly Podgoretsky ©   (23.11.06 10:06)
> > clickmaker  (23.11.2006 10:03:24)  [24]
>
> Запись не блокировать, а резервировать для операции, стандартное
> решение для кассиров.
> Сначала запись резервируется, потом редактируется, потом
> в или возращается из резерва или операция завершается нормально

а я что предлагал?
Или я чего-то не понял, или мы просто разные термины пользуем


 
clickmaker ©   (2006-11-23 10:17) [27]


> Сначала запись резервируется

update Orders set LockUser_ID = User_ID  -- перед открытием заказа кассиром User_ID

> потом редактируется

update Orders set что-то where Order_ID = @OrderId

> возращается из резерва

update Orders set LockUser_ID = null where Order_ID = @OrderId

или я опять "полный бред" пишу?


 
clickmaker ©   (2006-11-23 10:19) [28]

Забыл добавить. Если кто-то другой попытается открыть заказ
if (LockUser_ID IS NOT NULL)
 "Заказ уже редактируется пользователем LockUser_ID. Можете открыть только для чтения"

чем не решение?


 
ANB ©   (2006-11-23 10:30) [29]

Автору - у тебя уже все готово практически.
Надо только добавить следующую фичу :
Перед редактированием (подъемом формы на редактирование) нужно изменяемую запись перечитать с блокировкой.
Решится 2 задачи :
а) в форме будут свежие данные
б) сервером запись будет заблокирована и другой юзер ее открыть не сможет (тут возможны вариации с предложением открыть на чтение, обработав ошибку).
в оракле это делается элементарно : select for update
в мс скл должна быть подобная фича (где то я про нее читал).
К сожалению, я не нашел в ADO метода для рефреша одной записи да еще и с блокировкой, в ОДАКЕ это сделано явно, там и запрос настроить ручками можно. Впрочем, ща спецы придут - подскажут.
Если никак - то можно редактировать не основной набор данных, а свежезачитанный (надеюсь искусственные ключи в таблицах есть). А так как гридовые данные все равно в локальной кэше сидят, то сможешь изгальнуться обновить их, не отправляя на сервер.


 
ANB ©   (2006-11-23 10:33) [30]

ИМХО : изобретать велосипед с блокировкой через доп.поле - вчерашний век. У этого метода есть целая куча минусов.
Оправдана работа только с резервированием, но это совсем другая тема.


 
clickmaker ©   (2006-11-23 10:35) [31]


> [30] ANB ©   (23.11.06 10:33)
> ИМХО : изобретать велосипед с блокировкой через доп.поле
> - вчерашний век. У этого метода есть целая куча минусов.
> Оправдана работа только с резервированием

каких минусов?

и растолкуйте мне тупому, что же это за магическое резервирование такое?
Может снизойдет на меня просветление


 
ANB ©   (2006-11-23 11:01) [32]


> каких минусов?
>
> и растолкуйте мне тупому, что же это за магическое резервирование
> такое?
> Может снизойдет на меня просветление

Самые элементарные минусы :
1) пока транзакцию, меняющую это поле на статус "Заблокировано" не закоммитишь, никто этой блокированности не увидит. Сие может привести к одновременной "Блокировке" двумя и более пользователями.
2) В случае сваливания клиента/сервера "блокированные" записи так такими и остануться. Значит придется изобретать всякие хитрые кнопки по аварийному разблокированию, которыми начнут пользоваться не по назначению и т.д.
Короче, я этот способ уже юзал - он довольно простой на первый взгляд, но грабли я все собрал :) Учись на моих ошибках :)
Ликбез по резервированию :
Возьмем для примера склад.
Есть остаток товара на складе, в минус его загонять нельзя. Несколько операторов шпандорят накладные. Есно, нельзя допустить, чтобы товара выписали больше, чем на складе. Чтобы этого не допустить, когда вводишь строку с товаром, запрошенное количество от отстатка минусуется и переводится в резерв (есть несколько способов реализации - тута можно поспорить). Далее готовую накладную можно либо провести, либо откатить нафиг. В первом случае резерв просто минусуется, во втором - резерв приплюсовывается обратно к остатку.
Нечто подобное реализуется и при работе билетного кассира - там места имеют несколько статусов - свободно, резерв, продано. При заказе билета они сначала резервируются, чтобы другой кассир не мог продать, а уже при их оформлении продаются. Резерв можно вернуть обратно в свободные при отказе от покупки билета или если кассир заснул. Перед продажей, есно проверяется, находится ли место в статусе резерв за этим кассиром.


 
Anatoly Podgoretsky ©   (2006-11-23 11:07) [33]

> clickmaker  (23.11.2006 10:10:26)  [26]

Я не знаю, что ты предлагал, только термин блокировка по отношению к базам имеет одназначное толкование.


 
Anatoly Podgoretsky ©   (2006-11-23 11:07) [34]

> clickmaker  (23.11.2006 10:17:27)  [27]

Вот это блокировка и есть


 
Anatoly Podgoretsky ©   (2006-11-23 11:08) [35]

> clickmaker  (23.11.2006 10:19:28)  [28]

Это тоже блокировка, да и название говорит об этом.


 
Anatoly Podgoretsky ©   (2006-11-23 11:09) [36]

> clickmaker  (23.11.2006 10:35:31)  [31]

У блокировок обычный минус - всем хана, даже некоторые аггрегатные функции не сможешь выполнить.


 
clickmaker ©   (2006-11-23 11:13) [37]


> При заказе билета они сначала резервируются, чтобы другой
> кассир не мог продать, а уже при их оформлении продаются.
> Резерв можно вернуть обратно в свободные при отказе от покупки
> билета или если кассир заснул. Перед продажей, есно проверяется,
> находится ли место в статусе резерв за этим кассиром

совершенно верно. Так и делал. У поля есть статусы "свободно", "занято", "продано". И можно узнать, кто конкретно в процессе его продажи находится.
Но меня интересует именно глубинный механизм. Что, есть для этого какие-то встроенные средства SQL? И к тому же не зависящие от СУБД


> пока транзакцию, меняющую это поле на статус "Заблокировано"
> не закоммитишь, никто этой блокированности не увидит. Сие
> может привести к одновременной "Блокировке" двумя и более
> пользователями

для этого есть хинт holdlock


 
clickmaker ©   (2006-11-23 11:15) [38]


> [36] Anatoly Podgoretsky ©   (23.11.06 11:09)
> > clickmaker  (23.11.2006 10:35:31)  [31]
>
> У блокировок обычный минус - всем хана, даже некоторые аггрегатные
> функции не сможешь выполнить

ничего не понимаю.
Я не про сиквельные блокировки. Их вообще не трогаю, потому что операция по времени гораздо длинней, чем мы можем себе позволить растянуть транзакцию.


 
ANB ©   (2006-11-23 11:25) [39]


> clickmaker ©   (23.11.06 11:15) [38]

Переходи на оракл :) В нем проблем с родными серверными блокировками нету - все функции нормально работают, только еще раз заблокировать не даст. Плюс есть еще юзеровые блокировки, вообще гибкая вещь.


 
clickmaker ©   (2006-11-23 11:30) [40]


> когда вводишь строку с товаром, запрошенное количество от
> отстатка минусуется и переводится в резерв (есть несколько
> способов реализации - тута можно поспорить). Далее готовую
> накладную можно либо провести, либо откатить нафиг. В первом
> случае резерв просто минусуется, во втором - резерв приплюсовывается
> обратно к остатку

а как в данном случае разруливается эта ситуация:

> В случае сваливания клиента/сервера "блокированные" записи
> так такими и остануться



Страницы: 1 2 3 вся ветка

Форум: "Базы";
Текущий архив: 2007.02.18;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.59 MB
Время: 0.041 c
2-1170134129
MASTAFA
2007-01-30 08:15
2007.02.18
Вопрос по связи MathCad и Delphi


2-1170059211
novill
2007-01-29 11:26
2007.02.18
Почему консольная программа некорректно выводит русский текст?


15-1169799693
AntonSimenko
2007-01-26 11:21
2007.02.18
SimpleXML.pas


15-1169771344
IMHO
2007-01-26 03:29
2007.02.18
Viewer для BDB файлов


2-1170322622
марат
2007-02-01 12:37
2007.02.18
Изменение названия поля





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский