En este artículo te informamos sobre uno de los errores más comunes al usar un Hosting Windows con Entity Framework y .NET.
Si un cliente intenta publicar una aplicación Web con .NET - Entity Framework, que usa SQL 2016, aparecerá el siguiente error:
System.Data.SqlClient.SqlException: CREATE DATABASE permission denied in database 'master'.
¿Por qué sucede esto?
Nuestro hosting es compartido, de modo que cada parte del entorno tiene una política de seguridad estricta que impide al cliente ver contenidos o Bases de Datos (DB) de otro cliente.
En este caso en concreto, todos los clientes SQL tienen la variable DENY configurada en el permiso "VIEW ANY DATABASE".
Es esta variable "DENY" la que no permite ver otras Bases de Datos, a excepción de la Master y la Tempdb.
De modo que, cuando se inicia la aplicación, el "Entityframework" hace una búsqueda a la tabla "sysdatabases" para ver si la DB existe. Si este no la localiza, entonces procede a recrearla desde cero (sin embargo, nuestro permiso DBA no permite crear una nueva DB), y la web nos muestra ese error.
Esto no pasaba con SQL 2014 porque había un bug donde un Login con DENY en "VIEW ANY DATABASE", podía ver metadata de todas las DB en la tabla "sysdatabases" de la Master DB.
Este bug (que llevaba ahí desde la versión SQL 2005) se corrige en la SQL 2016.
Solución
Para usar EntityFramework en nuestro Hosting compartido, debes:
<contexts>
<context type="ContosoUniversity.DAL.SchoolContext, ContosoUniversity">
<!--<databaseInitializer type="ContosoUniversity.DAL.SchoolInitializer, ContosoUniversity" />-->
</context>
</contexts>
<appSettings>
<add key="DatabaseInitializerForType ContosoUniversity.DAL.SchoolContext, ContosoUniversity" value="Disabled" />
</appSettings>
Solución alternativa (no aplicable en un hosting compartido)
Elimina la variable DENY en el permiso VIEW ANY DATABASE dentro de SQL Login.
Guía de ejemplos:
http://www.entityframeworktutorial.net/code-first/turn-off-database-initialization-in-code-first.aspx
En este caso, cuando la aplicación arranque, no comprobará si la DB existe ya que dará por hecho de que lo está.