web-dev-qa-db-fra.com

Exception lors de la première tentative de code pour créer une base de données

J'ai créé une nouvelle application ASP.NET MVC 4 et j'aimerais qu'elle utilise d'abord le code. Cependant, il semble que le fichier de base de données ne soit pas créé initialement s'il n'existe pas déjà. Si je supprime le fichier .mdf du dossier App_Data, j'obtiens l'exception suivante lorsque l'application tente d'accéder à la base de données:

System.Data.SqlClient.SqlException: Cannot attach the file '<path-to-db-file>.mdf' as database '<my-db-file-name>'.

Si je l'exécute dans l'application dans le débogueur, je peux voir que l'exception se produit dans la méthode InitializeSimpleMembershipAttribute :: OnActionExecuting lors de l'appel de LazyInitializer.EnsureInitialized. L'exception capturée est:

[System.Reflection.TargetInvocationException]   {"Exception has been thrown by the target of an invocation."}   System.Reflection.TargetInvocationException

À l'exception interne de:

[System.InvalidOperationException]  {"The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.Microsoft.com/fwlink/?LinkId=256588"} System.InvalidOperationException

Ce qui a alors la première exception que j'ai mentionnée ci-dessus comme exception interne à cela.

Des idées que je fais mal?

Mettre à jour

Je viens de l'essayer avec une toute nouvelle application MVC4. Je peux le reproduire en procédant comme suit:

  1. Créez l'application MVC dans l'assistant VS.
  2. Lancez l'application pour la première fois et accédez à la page de connexion (notez que le fichier mdf est maintenant généré).
  3. Supprimez le fichier mdf et revenez à la page de connexion. L'exception est maintenant levée.
24
Dan

Dans le même problème et trouvé ma solution ici . Tout ce que vous avez à faire est d’arrêter LocalDb en ouvrant la commande de développeur VS Prompt et entrez (sans guillemets):

"sqllocaldb.exe stop v11.0"

"sqllocaldb.exe delete v11.0"

La prochaine fois, EF régénérera le fichier ainsi que la base de données.

9
moranlf

Si vous creusez dans la classe InitializeSimpleMembershipAttribute de votre application, vous verrez la méthode remplacée suivante de la classe ActionFilterAttribute dont elle hérite:

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // Ensure ASP.NET Simple Membership is initialized only once per app start
        LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
    }

Remarquez ce commentaire. L'application vérifie une fois par exécution pour s'assurer que l'adhésion simple a été correctement initialisée. Regardez les variables privées en haut de la classe:

    private static SimpleMembershipInitializer _initializer;
    private static object _initializerLock = new object();
    private static bool _isInitialized;

Ils sont tous statiques et ils sont tous passés en tant que ref. Le plus important ici pour votre situation est _isInitialized. LazyInitializer.EnsureInitialized vérifie l'indicateur _isInitialized et, s'il est faux, initialise la cible de référence transmise, dans ce cas le _initializer de type SimpleMembershipInitializer. À ce stade, il positionne le drapeau sur true et passe à autre chose. Si LazyInitializer.EnsureInitialized voit que le drapeau est vrai, il ne retourne que la cible. Comme cet indicateur est une variable statique, il conserve sa valeur pendant toute la vie de l'application, ce qui signifie qu'après cette première initialisation, EnsureInitialized retournera toujours simplement la cible, même si le fichier de base de données n'existe plus. En d'autres termes, si vous supprimez le fichier .mdf après l'initialisation, l'application ne le saura pas et des exceptions seront levées lorsque l'application essaiera de lire ou d'écrire à partir de la base de données. Pour résoudre ce problème, vous devez redémarrer l'application, ce qui signifie tuer le serveur dev si c'est ce que vous utilisez ou redémarrer l'application dans IIS.

C’est donc le problème auquel vous faites face, mais je soupçonne que beaucoup de personnes rencontrées dans cette question ont un problème similaire mais différent, où elles reçoivent un message d’erreur similaire à celui-ci lorsqu’elles tentent de se connecter:

CREATE FILE a rencontré l'erreur 5 du système d'exploitation (accès refusé) lors de la tentative d'ouverture ou de création du fichier physique 'C:\chemin\de\votre\projet\App_Data\dbfile.mdf'. Echec de CREATE DATABASE. Certains noms de fichiers répertoriés n'ont pas pu être créés. Vérifier les erreurs liées.

C'est très facile à résoudre. Je vais y revenir rapidement.

Par défaut, Visual Studio 2012 utilise une version réduite de SQL Server Express appelée LocalDB. LocalDB lancera un processus enfant de l'application, et si vous exécutez votre application sur le serveur de développement de Visual Studio (par exemple, http: // localhost: [port] est ce qui apparaît dans votre navigateur), vous exécutez à la fois l'application et LocalDB sous votre compte d'utilisateur et non sous SYSTEM ou NETWORKSERVICE. Pour résoudre ce problème, il vous suffit d'attribuer des autorisations de modification à votre utilisateur pour le dossier App_Data de votre projet. Essayez à nouveau de vous connecter et le fichier .mdf devrait être créé avec succès.

Si vous êtes curieux, vous pouvez en apprendre plus sur LocalDB ici.

4
joelmdev

Vous pouvez gérer l'initialisation de la base de données Code First dans la méthode Application_Start du fichier Global.asax du dossier racine de votre projet, comme suit:

    protected void Application_Start()
    {
        Database.SetInitializer<MyDBContext>(null);
    }

Si vous transmettez null à SetInitializer, il ne créera ni modifiera vos tables de base de données, vous devrez le faire manuellement.

La raison pour laquelle la base de données n'est pas régénérée est que Application_Start n'est déclenché qu'une seule fois pendant la durée de vie de l'application.

2
Mohsen Afshin

Le code généré par MVC fonctionne avec une chaîne de connexion à la base de données nommée "DefaultConnection". Si vous avez utilisé un nom différent dans Web.config, vous devez faire référence à ce nom dans:

  1. InitializeSimpleMembershipAttribute.SimpleMembershipInitializer.ctor () dans InitializeSimpleMembershipAttribute.cs).
  2. UsersContext.ctor () dans AccountModel.cs

(ou recherchez simplement "DefaultConnection" dans votre projet).

2
ury

Vous ne devez jamais supprimer de fichiers .mdf créés automatiquement dans l'Explorateur, uniquement via les outils de gestion SQL ou dans l'explorateur d'objets. 

Le problème que vous rencontrez (et que vous pouvez répliquer à l'aide des étapes que vous avez fournies) est que la base de données est toujours enregistrée dans LocalDb.

1
Evonet

Vous devez arrêter votre instance IISExpress et la redémarrer (en appuyant sur F5 dans votre Visual Studio). Vous pourrez alors créer à nouveau la base de données.

0
Will Huang

ce qui a résolu le problème pour moi lorsque j'ai reçu cette erreur, c'est que j'ai changé la chaîne de connexion dans le fichier App.config de mon projet VS.

J'ai ajouté ceci dans la chaîne de connexion:

  <connectionStrings>
<add name="Blog" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;Integrated Security=true;AttachDbFileName=C:\Users\kostadin\Database1.mdf" providerName="System.Data.SqlClient" />

J'espère que ceci aide quelqu'un d'autre.

0