powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / как грамотно закрыть recordset?
25 сообщений из 84, страница 3 из 4
как грамотно закрыть recordset?
    #32817409
Lenivec
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
класс у меня определяется как
Public vМойКласс AS New МойКласс
и никаких переинициализаций при этом не возникает
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817426
Фотография Лох Позорный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lenivec2 Лох Позорный
если интересно то посмотрите внимательно что будет происходить с коллекцией DBEngine(0).Databases при создании новых рекордсетов с помощью конструкций типа:
Код: plaintext
1.
2.
3.
4.
5.
set objRst1 = CurrentDb.OpenRecordset(...)
set objRst2 = CurrentDb.OpenRecordset(...)
set objRst3 = CurrentDb.OpenRecordset(...)
set objRst4 = CurrentDb.OpenRecordset(...)
set objRst5 = CurrentDb.OpenRecordset(...)
или типа:
Код: plaintext
1.
2.
3.
4.
5.
6.
set objDb = CurrentDb
set objRst1 = objDb.OpenRecordset(...)
set objRst2 = objDb.OpenRecordset(...)
set objRst3 = objDb.OpenRecordset(...)
set objRst4 = objDb.OpenRecordset(...)
set objRst5 = objDb.OpenRecordset(...)
так вот, в первом случае на каждый отдельный рекордсет в коллекцию будет добавлен отдельный экземпляр базы данных
а во втором случае все рекордсеты будут созданы в одном единственном экземпляре базы данных

делайте выводы господа
и попробуйте доказать мне что я не прав
И что?

Да, вызов CurrentDb создает новый объект типа DAO.Database.
Да, этот созданный объект добавляется в коллекцию Databases. А почему бы ему туда не добавляться?
Открытие базы данных при этом не происходит.

Чтобы вам было понятнее - аналогичный пример с рекордсетами.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Public Function test()
    Dim db As Database
    Set db = CurrentDb
    Dim rst As Recordset, rst1 As Recordset
    
    Set rst = db.OpenRecordset("t")
    Debug.Print db.Recordsets.Count
    
    Set rst1 = rst.Clone
    Debug.Print db.Recordsets.Count
End Function
Да, клонирование рекордсета создает новый объект типа DAO.Recordset
Да, новый объект добавляется в семейство Recordsets
Открытия рекордсета - нету.

Разумеется, объекты типа Recordset, открытые на различных объектах типа Database - держат ссылки на эти самые объекты типа Database. Как только рекордсет закроется - ссылка освободится.

Вдогонку про класс
ps (как и думал - Alexey Sh предлагает обращаться не к классу а к некой глобали с типом класса - что несколько разные вещи).
Что обращение к классу по имени (MoйКласс.МояБаза), что создание глобальной переменной As New - один хрен.
Не нужен тут класс вообще.
Делается одна глобальная пропертя (с теми же самыми проверками на Nothing)

И совсем уж вдогонку
Непонятно чем это лучше, чем использование DBEngine(0)(0)
Если коллекции (QueryDefs, TableDefs и прочее) меняются - то как ни крути, они и в DBEngine(0)(0) устарели, и в сохраненной переменной в рукотворном классе.
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817442
Lenivec
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
автор
И что?

а то что имеется ограничение на колличество открытых баз данных (кстати что по вашему тогда открытая база данных как не экземпляр объекта?) и это ограничение равно всего навсего 255 и для больших проектов если раскидываться направо и налево CurrentDb, то выделенный лимит исчерпаешь очень быстро

автор
Что обращение к классу по имени (MoйКласс.МояБаза), что создание глобальной переменной As New - один хрен.
Не нужен тут класс вообще.
Делается одна глобальная пропертя (с теми же самыми проверками на Nothing)

ради бога, хозяин барин, нравится пользуйте, я не запрещаю

автор
Непонятно чем это лучше, чем использование DBEngine(0)(0)

где вы прочитали у меня что чтото лучше или хуже, я лишь указал на недостаток обращения через DBEngine(0)(0)
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817453
Alexey Sh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Лох Позорный : хелп про отличия Currentdb() от Dbengine(0)(0) мне сильно не понравился
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817511
мдя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lenivecкласс у меня определяется как
Public vМойКласс AS New МойКласс
и никаких переинициализаций при этом не возникает

Хм если быт точным, класс у вас определяется как МойКласс.

Public vМойКласс AS New МойКласс - это определение переменной а не класса

обращение к переменной не есть обращение к классу. Речь шла именно об обращениях к классу.
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817521
Alexey Sh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 мдя: в VBA классы какие-то болезненные, обращаться к ним иначе как к экзкмплярам никак не получается, ну не нашёл я там статических переменных и методов. Может плохо искал?
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817527
Фотография Лох Позорный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а кто вам таки сказал, что в COM бывают статические переменные/методы класса?
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817546
мдя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexey Sh2 мдя: в VBA классы какие-то болезненные, обращаться к ним иначе как к экзкмплярам никак не получается, ну не нашёл я там статических переменных и методов. Может плохо искал?
Да я не против объявления AS NEW, просто речь шла об обращении именно к классу. При этом (обращении собственно к классу), если класс на держит себя за ссылку (или кто нить еще не держит проинициированную им, не как NEW переменную ), происходит его Initialize, а если держит - не происходит.


МетОда с Pablic xxx As New у меня как то выпала из круга решений, то ли по дурости, то ли из за того, что надо где-то в 3-м месте (кроме класса и вызовов) ее (переменную) объявлять. Я просто делел так в самом классе

В объявлениях:
Private Self As Object
В Class_Initialize :
...
Set Self = Me

В методе Public Sub CloseMe()
...
Set Self = Nothing

при этом обьявлять дополнительную переменную мне не надо, после первого обращения к любому компоненту/методу класса он держит себя за хвост и повторного Initialize не происходит, пока не произойдет CloseMe, или ошибка - в остальном ведет себя как Ваш экземпляр.

Класс я рисовал не для CurrentDB. а для кучки линкованных DB (и Current, заодно), все инициировались напрямую в Initialize (я не закладывался на то, что кто-то снаружи закроет какую-нто ДБ - что, в отсутствии Property Set, кстати сказать и у ленивца нихто не сделает присвоением Nothing, правда метод Close, похоже закроет базу - надо бы и его как-то перекрыть, а не проверять Is Nothing всякий раз), поскольку у меня просто все вызовы написаны как вызовы методов
Set rst =МойКласс.МояБ1.OpenRecordset(...)

Да, и для транзакций он у меня не заточен, ибо воркспейс в нем у меня задается (пусть и (0)), явно.
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817592
Alexey Sh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МойКласс - это что?
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817603
Фотография Serge Gavrilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Лох ПозорныйСоветующие DLookup (и остальные DSum'ы, DMax'ы) почему-то не упоминают про то, что работает оно медленнее, чем чтение одного поля из рекордсета с одной записью. ...


Но сама-то Function CurrentDb() As Database тоже достаточно долгая.
Поэтому скорость выполнения будет зависеть от того как ее использовать.
Если в цикле гнать считывание поля рекордсета открываемого с CurrentDb, то использование Dlookup будет быстрее

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
Sub test1()
    Dim a, i, v
    a = Timer
    For i =  1  To  1000 
        v = CurrentDb.OpenRecordset("Select * From msysobjects")("id")
    Next
    Debug.Print Timer - a
End Sub
Sub test2()
    Dim a, i, v
    a = Timer
    For i =  1  To  1000 
        v = DLookup("id", "msysobjects")
    Next
    Debug.Print Timer - a
End Sub
Sub test3()
    Dim a, i, v, d
    Set d = CurrentDb
    a = Timer
    For i =  1  To  1000 
        v = d.OpenRecordset("Select * From msysobjects")("id")
    Next
    Debug.Print Timer - a
End Sub

Скорость 2 и 3 примерно одинакова.
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817608
Alexey Sh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
уже писал здесь, нефиг вызывать Application.CurrentDb() больше одного раза.
присвоить глобальной переменной и забыть.
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817609
Alexey Sh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И по имени в случае выборки в SELECT одного поля незачем обращаться, индекса 0 достаточно
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817610
Фотография Serge Gavrilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lenivec...а то что имеется ограничение на колличество открытых баз данных (кстати что по вашему тогда открытая база данных как не экземпляр объекта?) и это ограничение равно всего навсего 255 и для больших проектов если раскидываться направо и налево CurrentDb, то выделенный лимит исчерпаешь очень быстро

Я не понял, вы считаете, что если я несколько раз вызову CurrentDB, то в коллекцию Databases будут добавлены новые объекты? В какой версии Access?

For i = 1 To 1000
v = CurrentDb.OpenRecordset("Select * From msysobjects")("id")
Next
Debug.Print DBEngine(0).Databases.Count

Выводится 1

При вызове CurrentDb, если не было присвоения объектной переменной, Database как создается, так и уничтожается.
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817611
мдя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexey Sh МойКласс - это что?
в описанном мною выше - это имя (модуля) класса (т.е. "самого класса"), в котором и описан самоподхват (Set Self = Me) и все прочее. Т.е. "стандартный экземпляр класса", который не умирает пока не вызовете соответствующий метод, или не сбросите программу.
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817612
Фотография Serge Gavrilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexey ShИ по имени в случае выборки в SELECT одного поля незачем обращаться, индекса 0 достаточно
Какое это имеет отношение к тому, что я написал о сравнении скорости dlookup и CurrentDb.OpenRecordset?
Ну замените в моем примере на 0, скорость будет практически таже.
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817614
Фотография Лох Позорный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Serge Gavrilov
Но сама-то Function CurrentDb() As Database тоже достаточно долгая.
Используйте DBEngine(0)(0), оно быстрое :)

Я не понял, вы считаете, что если я несколько раз вызову CurrentDB, то в коллекцию Databases будут добавлены новые объекты? В какой версии Access?
В любой версии аксес - если сохранять ссылку на открытый рекордсет .
Так что речь идет не о том, что "вызовами CurrentDb раскидываться направо и налево", а о том, что "открытыми рекордсетами раскидываться направо и налево". Надобность держать 255 открытых курсоров - весьма сомнительна, тем не менее сгодится как аргумент.
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817615
Фотография Serge Gavrilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexey Shуже писал здесь, нефиг вызывать Application.CurrentDb() больше одного раза.
присвоить глобальной переменной и забыть.

Интересное решение :-)
Но ведь Database может меняться: может добавиться таблица, а ваша глобальная переменная это не заметит.
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817616
Alexey Sh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Serge Gavrilov Alexey Shуже писал здесь, нефиг вызывать Application.CurrentDb() больше одного раза.
присвоить глобальной переменной и забыть.

Интересное решение :-)
Но ведь Database может меняться: может добавиться таблица, а ваша глобальная переменная это не заметит.

Появление "на лету" новых таблиц, модификация их структуры - это ошибка проектирования
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817617
мдя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Serge Gavrilov Alexey Shуже писал здесь, нефиг вызывать Application.CurrentDb() больше одного раза.
присвоить глобальной переменной и забыть.

Интересное решение :-)
Но ведь Database может меняться: может добавиться таблица, а ваша глобальная переменная это не заметит.
Ну, Refresh семейств никто не отменял. Надо только делать их выборочно и выигрыш в скорости супротив повсеместного CurrentDB будет на лице
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817619
Фотография Лох Позорный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Serge Gavrilov Alexey Shуже писал здесь, нефиг вызывать Application.CurrentDb() больше одного раза.
присвоить глобальной переменной и забыть.

Интересное решение :-)
Но ведь Database может меняться: может добавиться таблица, а ваша глобальная переменная это не заметит.
не заметит этого и DBEngine(0)(0), и точно так же не заметит этого предлагаемый ленивцем чудо-класс
Метод Refresh у коллекций есть на этот случай.
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817621
мдя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Более того, я и с "темповой" LocaDB так работаю. Пока жив. (где уш тут ашипка праэктирования, когда сама LocaDB может появиться в процессе работы, не говоря о "темповых" таблицах). И при удаленном пополнении базы с данными новыми таблицами (с учетом того, что процедура эта разовая - при модификации структуры) - мне достаточно не забыть сделать Refresh семейств и все.
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817622
Фотография Serge Gavrilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Лох ПозорныйИспользуйте DBEngine(0)(0), оно быстрое :)

да Лох Позорный
В любой версии аксес - если сохранять ссылку на открытый рекордсет .
Так что речь идет не о том, что "вызовами CurrentDb раскидываться направо и налево", а о том, что "открытыми рекордсетами раскидываться направо и налево". Надобность держать 255 открытых курсоров - весьма сомнительна, тем не менее сгодится как аргумент.
согласен
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817623
Alexey Sh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще то говоря появление новой таблицы никак не мешает обратиться к ней с помощью сохранённой до её создания ссылки на CurrentDB()

Где у Карла Маркса написано, что MSYSOBJECT загружается в память намертво? Попробуйте, без всякого Refresh рекордсеты будут успешно открываться. Если уж что и грузится в память, то это коллекции Application.Containers
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817625
Фотография Serge Gavrilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexey ShПоявление "на лету" новых таблиц, модификация их структуры - это ошибка проектирования

Ну, кто-то может сказать, что и использование Access - это ошибка проектирования.
...
Рейтинг: 0 / 0
как грамотно закрыть recordset?
    #32817626
Alexey Sh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 мдя: странно, с временной db я уже лет 6 как работаю таким образом :)
...
Рейтинг: 0 / 0
25 сообщений из 84, страница 3 из 4
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / как грамотно закрыть recordset?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]