Непонятно, что вы подразумеваете под термином «накладные расходы», поэтому я не знаю, как кто-нибудь мог бы ответить на ваш вопрос в качестве формулировки.
Но тема DBEngine (0) (0) и CurrentDB обсуждалась в течение многих лет в группах новостей Access. Я давно заключил мир с использованием CurrentDB, поэтому я подведу итог ситуации, как я ее вижу.
DBEngine (0) (0) намного быстрее, чем CurrentDB в этом коде:
Dim db As DAO.Database
Dim i As Integer
Debug.Print "Start CurrentDB: " & Now()
For i = 1 to 1000
Set db = CurrentDB
Set db = Nothing
Next i
Debug.Print "End CurrentDB: " & Now()
Debug.Print "Start DBEngine(0)(0): " & Now()
For i = 1 to 1000
Set db = DBEngine(0)(0)
Set db = Nothing
Next i
Debug.Print "End DBEngine(0)(0): " & Now()
Если я правильно помню, ADH97 сказал, что DBEngine (0) (0) был примерно в 17 раз быстрее.
Но посмотрите на этот код - он не проверяет ничего полезного. Помните, что как CurrentDB, так и DBEngine (0) (0) возвращают указатели на базу данных, открытую в данный момент в пользовательском интерфейсе Access (с некоторыми оговорками, ниже, для DBEngine (0) (0)). В приложении Access нет места, где либо из этих циклов будет полезен в любом случае. В реальном коде вы делаете это:
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDB
Set rs = db.OpenRecordset("a SQL SELECT")
[do something with the recordset]
rs.Close
Set rs = db.OpenRecordset("another SQL SELECT")
[do something with this other recordset]
rs.Close
Set rs = Nothing
db.Execute("A SQL DML statement")
Debug.Print db.RecordsAffected
Set db = Nothing
Хотя DBEngine (0) (0) может быть на 1700% быстрее в цикле, ЭТО НЕ имеет значения, потому что вы никогда не собираетесь повторно возвращать ссылку на базу данных, открытую в данный момент в пользовательском интерфейсе Access, достаточно для разница будет совсем незначительной (мы говорим здесь миллисекунды, хотя, конечно, CurrentDB займет больше времени для баз данных с большим количеством объектов).
Итак, прежде всего, прежде чем я объясню почему есть разница, вы должны сначала признать, что разница в производительности совершенно несущественна, поскольку единственное обстоятельство, при котором оно может превышать самое тривиальное различие, - это обстоятельство это был бы глупый код.
Теперь, почему разница?
Ну, есть две основные причины:
DBEngine (0) (0) возвращает коллекции так, как они были инициализированы, когда база данных, открытая в данный момент в пользовательском интерфейсе, была впервые открыта, если только вы не обновите коллекции вручную. Таким образом, если вы добавляете новый сохраненный QueryDef, чтобы он был доступен в коде с использованием DBEngine (0) (0), после добавления нового QueryDef вы должны вызвать
DBEngine(0)(0).QueryDefs.Refresh
Перед этим ваш новый запрос не будет Коллекция QueryDefs, но после нее она будет. CurrentDB, с другой стороны, обновляет все коллекции при каждом вызове, поэтому вам не нужно беспокоиться об обновлении любой из ваших коллекций.
DBEngine (0) (0) возвращает внутренний указатель, используемый рабочим пространством Access Jet для указания базы данных, открытой в данный момент в пользовательском интерфейсе Access. CurrentDB возвращает копию структуры базы данных, и каждый вызов CurrentDB создает новую копию. Таким образом, CurrentDB будет использовать больше памяти, потому что он создает копию структуры, которая указывает на базу данных, открытую в данный момент в пользовательском интерфейсе Access, в то время как DBEngine (0) (0) не использует дополнительную память, поскольку возвращает не копию, а просто указатель на существующую структуру памяти.
Вероятно, обновление коллекций является причиной того, что CurrentDB медленнее (на 1700%) (или каким-либо другим числом), но, вероятно, некоторое дополнительное время затрачивается на процесс настройки копии объекта базы данных. Тоже.
Опять же, ничего из этого не имеет никакого значения в реальной практике кодирования, поскольку вам просто не нужно постоянно открывать и закрывать указатели на базу данных, открытую в настоящее время в пользовательском интерфейсе Access, поскольку ЭТО НЕ ОТКРЫВАЕТСЯ И НЕ ЗАКРЫВАЕТСЯ ПОСТОЯННО.
Итак, это вещь потаэто / потахто?
Нет, потому что есть одна «ошибка» в DBEngine (0) (0), которая может привести к тому, что он возвратит неожиданный указатель базы данных (хотя это было бы технически правильно), и это происходит в определенных контекстах сразу после мастера доступа После запуска DBEngine (0) (0) вернет указатель на базу данных wizard , а не на базу данных, открытую в данный момент в интерфейсе доступа.
Это потому, что есть различие между:
база данных, открытая в данный момент в пользовательском интерфейсе Access, И
первая база данных в первом рабочем пространстве объекта DBEngine.
CurrentDB, с другой стороны, всегда возвращает ссылку на # 1 и никогда на # 2. DBEngine (0) (0), однако, может возвращать что-то еще, так как в течение очень короткого момента мастер является первой базой данных в первом рабочем пространстве объекта DBEngine сразу после его закрытия.
Теперь, вероятно, что производственный код мог когда-либо столкнуться с этой ошибкой? Вероятно, нет, поскольку маловероятно, что вы будете использовать мастера в производственном приложении. Но это также может относиться к библиотечным базам данных, и это не так уж редко встречается, особенно для опытных программистов Access.
Если существует практическая разница в производительности, DBEngine (0) (0) может того стоить, но, поскольку его нет, CurrentDB предпочтительнее, так как он на 100% надежен в возвращении ожидаемой ссылки на базу данных.
Все это говорит, я не использую ни в моих приложениях.
Вместо этого я использую функцию, которая кэширует переменную базы данных, инициализированную с помощью CurrentDB. Это означает, что мне никогда не нужно инициализировать какие-либо переменные базы данных, просто используйте мою функцию dbLocal () вместо любой переменной базы данных. Вот код:
Public Function dbLocal(Optional bolCleanup As Boolean = False) As DAO.Database
' This function started life based on a suggestion from
' Michael Kaplan in comp.databases.ms-access back in the early 2000s
' 2003/02/08 DWF added comments to explain it to myself!
' 2005/03/18 DWF changed to use Static variable instead
' uses GoTos instead of If/Then because:
' error of dbCurrent not being Nothing but dbCurrent being closed (3420)
' would then be jumping back into the middle of an If/Then statement
On Error GoTo errHandler
Static dbCurrent As DAO.Database
Dim strTest As String
If bolCleanup Then GoTo closeDB
retryDB:
If dbCurrent Is Nothing Then
Set dbCurrent = CurrentDb()
End If
' now that we know the db variable is not Nothing, test if it's Open
strTest = dbCurrent.Name
exitRoutine:
Set dbLocal = dbCurrent
Exit Function
closeDB:
If Not (dbCurrent Is Nothing) Then
'dbCurrent.close ' this never has any effect
Set dbCurrent = Nothing
End If
GoTo exitRoutine
errHandler:
Select Case Err.Number
Case 3420 ' Object invalid or no longer set.
Set dbCurrent = Nothing
If Not bolCleanup Then
Resume retryDB
Else
Resume closeDB
End If
Case Else
MsgBox Err.Number & ": " & Err.Description, vbExclamation, "Error in dbLocal()"
Resume exitRoutine
End Select
End Function
В коде вы используете это так:
Dim rs As DAO.Recordset
Set rs = dbLocal.OpenRecordset("SQL SELECT statement")
[do whatver]
rs.Close
Set rs = Nothing
dbLocal.Execute("SQL INSERT statement")
Debug.Print dbLocal.OpenRecordset("SELECT @@IDENTITY")(0)
dbLocal.Execute("SQL UPDATE statement")
Debug.Print dbLocal.RecordsAffected
При первом вызове он инициализируется с помощью CurrentDB и возвращает объект кэшированной базы данных.
Когда вы закрываете приложение, вы вызываете его с флагом bolCleanup, установленным в TRUE, чтобы очистить кэшированную переменную.
Если вы добавляете в коллекции, они не обновляются (потому что вы не вызываете CurrentDB каждый раз, просто используете переменную кэшированной базы данных, которая была инициализирована с CurrentDB), поэтому вы должны сделать это:
[add a new QueryDef]
dbLocal.QueryDefs.Refresh
И это все. Нет глобальных переменных, нет необходимости постоянно инициализировать переменные базы данных с помощью CurrentDB (или DBEngine (0) (0)). Вы просто используете это и перестаете беспокоиться об этом. Единственная техническая деталь - убедиться, что процедура завершения работы вашего приложения вызывает dbLocal (False).
Итак, это мой взгляд на DBEngine (0) (0) против CurrentDB.
Побочный вопрос об очистке переменных базы данных, инициализированных этими двумя методами:
Если вы инициализируете переменную db с помощью CurrentDB, вы не закрываете ее, просто установите для нее значение Nothing:
Dim db As DAO.Database
Set db = CurrentDB
...
'db.Close <= don't do this
Set db = Nothing
Если вы делаете выдачу базы данных. Закройте, ничего не произойдет, ни плохого, ни хорошего.
С другой стороны, в этом случае:
Dim db As DAO.Database
Set db = DBEngine(0)(0)
...
'db.Close <= don't do this
Set db = Nothing
... при выдаче db.Close в некоторых версиях Access может произойти сбой приложения.
Ни один из них на самом деле не может работать, потому что вы не можете закрыть базу данных, открытую в данный момент в пользовательском интерфейсе Access, с помощью метода Close объекта базы данных.
С другой стороны, если вы сделаете это:
Dim db As DAO.Database
Set db = DBEngine.OpenDatabase("path to external MDB file")
...
db.Close ' <=you *must* do this
Set db = Nothing
... вы действительно делаете хотите закрыть его, так как это внешняя база данных. Этот код нельзя сделать с помощью CurrentDB, потому что это единственный способ открыть ссылку на другую базу данных.