using (var db = new TestEntities())
{
db.Database.CreateIfNotExists();
}
Для версий 4.0/5.0 все достаточно стандартно, код проверки на T-SQL выглядит следующим образом:
-- EF 4.0/5.0SELECT Count(*) FROM sys.databases WHERE [name]=N'Test'
А вот для версии 6.0 реализация изменилась и теперь представляет собой запрос вида:
-- EF 6.0IF db_id(N'Test') IS NOT NULL SELECT 1 ELSE SELECT Count(*) FROM sys.databases WHERE [name]=N'Test'
Посему у меня возник уже свой вопрос.
Для каких целей автор, в случае отсутствия БД делает дополнительное обращение к sys.databases для ее поиска, ведь функция db_id уже подтвердила отсутствие базы на сервере?
Более реалистичный вариант ответа заключается в неаккуратности реализации проверки в версии 6.0, т.е. автор, планируя изменить подход к анализу существования БД, выполнил работу наполовину. Я конечно могу заблуждаться и запрос все-таки несет какой-то скрытый смысл, но другие варианты ответа выглядят фантастическими – контроль работы db_id или с момента вызова db_id и до перехода к else БД была все-таки создана и т.п.
Самое простое решение, которое напрашивается в этой ситуации
IF db_id(N'Test') IS NOT NULL SELECT 1 ELSE SELECT 0
Здравствуйте, Olaf, Вы писали:
O>Более реалистичный вариант ответа заключается в неаккуратности реализации проверки в версии 6.0, т.е. автор, планируя изменить подход к анализу существования БД, выполнил работу наполовину. Я конечно могу заблуждаться и запрос все-таки несет какой-то скрытый смысл, но другие варианты ответа выглядят фантастическими – контроль работы db_id или с момента вызова db_id и до перехода к else БД была все-таки создана и т.п.
Возможно, действительно не доделал, хотя зачем было трогать работающую проверку
O>Для каких целей автор, в случае отсутствия БД делает дополнительное обращение к sys.databases для ее поиска, ведь функция db_id уже подтвердила отсутствие базы на сервере?
Насколько помню, поведение в обоих вариантах совпадает, вне зависимости от разрешений / статуса базы (OFFLINE etc). Подозреваю, самый простой способ узнать — спросить в обсуждениях на codeplex или на stackoverflow.
Здравствуйте, _ABC_, Вы писали:
_AB>Если у логина нет прав на view any database, то
SELECT Count(*) FROM sys.databases WHERE [name]=N'Test'
_AB>выдаст 0. Создание БД тем не менее не, разумеется, не сработает.
Так DB_ID() тоже будет молчать как партизан в этом случае. В документации раздел Permissions откровенно скопипащщен с sys.databases.
Здравствуйте, Sinix, Вы писали:
S>Так DB_ID() тоже будет молчать как партизан в этом случае. В документации раздел Permissions откровенно скопипащщен с sys.databases.
Не будет. Тут дыра. Проверено на 2012 и 2014.
Учитывая, что для более ранних версий в документации по этому поводу вообще ничего нет,
то там поведение аналогично 2012+.
Здравствуйте, _ABC_, Вы писали:
_AB>Она не работала.
_AB>Если у логина нет прав на view any database, то _AB>
_AB>SELECT Count(*) FROM sys.databases WHERE [name]=N'Test'
_AB>
_AB>выдаст 0. Создание БД тем не менее не, разумеется, не сработает.
Опять же это еще один вопрос особенностей реализации проверки до версии 6.0 в EF Потому что даже при отсутствии прав на уровне сервера deny view any database to user проверить наличие базы данных можно в случае, если она является текущей у пользователя. А производитель EF по всей видимости использует master, именно поэтому и возвращается 0.
Согласен, так будет проще, но может быть автор в новой версии попытался сохранить преемственность подхода к анализу результатов, т.е. при наличии БД возвращается 1, в противном случае 0. В вашем же варианте вернутся номер базы данных и null.
Здравствуйте, Olaf, Вы писали:
O>Опять же это еще один вопрос особенностей реализации проверки до версии 6.0 в EF Потому что даже при отсутствии прав на уровне сервера deny view any database to user проверить наличие базы данных можно в случае, если она является текущей у пользователя.
Не понял. А смысл проверять наличие БД, если контекст БД уже успешно установлен?
Кстати, проверить через sys.databases еще можно, если пользователь является database owner.
Тем не менее, в общем случае старый метод не работает. Думаю, что просто поступило описание бага
и они пофиксили бездумно, дописав в той же строке условие по db_id, как это было написано в
комментариях к багу.
O>А производитель EF по всей видимости использует master, именно поэтому и возвращается 0.
Производитель EF по всей видимости не убирает права view any database у public. И к тому же
обычно работает с БД, которые созданы тем же логином, под которым и работает приложение
(т.е. под логином database owner).
С другой стороны, в меру параноидальные DBA не позволяют приложениям самим создавать БД. А не параноидальные
не парятся с отбиранием прав у паблика. Тем более, что обходится это злоумышленниками на раз-два.
Может быть, поэтому такое поведение и дожило до 6-й версии. С одной стороны разрабы не особо парятся.
С другой DBA если и парятся, то так, что данная фича становится неприменимой.
Здравствуйте, _ABC_, Вы писали:
_AB>Здравствуйте, Olaf, Вы писали:
O>>Опять же это еще один вопрос особенностей реализации проверки до версии 6.0 в EF Потому что даже при отсутствии прав на уровне сервера deny view any database to user проверить наличие базы данных можно в случае, если она является текущей у пользователя. _AB>Не понял. А смысл проверять наличие БД, если контекст БД уже успешно установлен? _AB>Кстати, проверить через sys.databases еще можно, если пользователь является database owner.
_AB>Тем не менее, в общем случае старый метод не работает. Думаю, что просто поступило описание бага _AB>и они пофиксили бездумно, дописав в той же строке условие по db_id, как это было написано в _AB>комментариях к багу.
Спасибо, теперь всё встало на свои места. Вчера я сказал глупость, поздно было – ни о какой текущей базе речи идти не может, ведь ее еще нет на сервере, а проверка через sys.databases должна это выявить, поэтому только master.
Здравствуйте, _ABC_, Вы писали:
_AB>Здравствуйте, Sinix, Вы писали:
S>>Так DB_ID() тоже будет молчать как партизан в этом случае. В документации раздел Permissions откровенно скопипащщен с sys.databases. _AB>Не будет. Тут дыра. Проверено на 2012 и 2014.
_AB>Учитывая, что для более ранних версий в документации по этому поводу вообще ничего нет, _AB>то там поведение аналогично 2012+.
Дыру закрыли. В версии 2016 возможно с момента релиза, а в 2014 совсем недавно, т.е. с момента выпуска CU#2 для SP2: