Bonjour à tous.

J'ai expliqué ce que j'ai fais dans ce post.

Le problème vient de la fonction InitDatabaseModel :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
class DatabaseManagerContextApp : DatabaseManagerContext
{
    /// <summary>
    /// Factory pour créer l'instance de la base de données de type DatabaseManagerContextApp.
    /// </summary>
    public class DatabaseManagerContextFactoryApp : IDatabaseManagerContextFactory
    {
        public DatabaseManagerContext   CreateDatabaseManagerContext()
        {
            return new DatabaseManagerContextApp();
        }
    }
 
    static public void InitDatabaseModel()
    {
        // Analyse et migration de la base de données
        try
        {
            // Initialisation
            Configuration configuration = new Configuration();
            configuration.ContextType = typeof(DatabaseManagerContextApp);
            var migrator = new DbMigrator(configuration);
            // This will update the schema of the DB
            migrator.Update(); // This will run Seed() method
        }
        catch (AutomaticMigrationsDisabledException)
        {   // ici, pas besoin de lancer l'exception, la version de la base de données à changée
        }
        catch (Exception)
        {   // renvoyer l'exception plus haut
            throw;
        }
 
        // Ne pas faire ce code dans le catch (AutomaticMigrationsDisabledException) car si une exception
        // est levée elle ne pourra plus être catchée et il faut le faire au cas où la migration a fonctionnée
        GeneralProvider provider = new GeneralProvider();
        EntityGeneral general  = provider.GetGeneral();
 
        if (general == null)
        {   // Création de la base, ajouter le schéma actuel
            provider.Create(new EntityGeneral { SchemaVersion = App.DATABASE_SCHEMA_VERSION } );
        }
        else
        {   // La version de la BDD doit être <= à cette version de programme
            if (general.SchemaVersion >  App.DATABASE_SCHEMA_VERSION)
            {
                throw new Exception("Le programme est incompatible avec version de la base de données\n\nVeuillez mettre à jour le programme.");
            }
            else if (general.SchemaVersion <  App.DATABASE_SCHEMA_VERSION)
            {   // Mettre à jour le N° de version de la base de données en concordance avec la version du programme
                // sachant que la migration a fonctionnée donc la version actuelle du schéma est egal à celui du
                // programme
                general.SchemaVersion =  App.DATABASE_SCHEMA_VERSION;
                provider.Update(general);
            }
        }
    }
 
    /// <summary>
    /// Initialisez un nouvel objet Model.
    /// <param name=_objConnection>Objet connexion.</param>
    /// </summary>
    public DatabaseManagerContextApp()
        : base()
    {
    }
}
Il s'avère que cette fonction permet de créer la base si elle n'existe pas, puis de la migrer à la dernière version si elle exite.
Ça fonctionne très bien.

Sauf quand ça ne fonctionne pas ! En effet, si un problème survient lors de la migration ou de la création (par exemple, pour ma part un champ string trop long) la base est créée en partie avant l'exception mais comme il n'y a pas de transaction, elle reste tel quel...
Du coup, lorsque je relance, EF détecte que la base de données n'est pas à jour (forcément puisque la création a en partie échoué au dernier lancement), EF tente de mettre la base de données à jour mais comme les premières tables ont déjà étés créée, une erreur de type 'table déjà existante' est lancée et là je suis bloqué.
Pour le moment je suis en dev sur une machine de test et le problème est vite réglé : je détruis la base, la recrée et change mon champs pour la taille soit acceptée. Mais une fois en prod, si une erreur que je n'ai pas détectée pendant la phase de dev survient, je risque de gros soucis !
En encore, si c'est au moment de la création, c'est chiant mais si c'est pendant une migration ça risque d'être bien plus génant.

Ce que je voudrais c'est créer une transaction autour de cette migration, de sorte que si celà échoue, que l'on puisse rester dans l'état précécent !
Mais le fait de créer un dbContext avant celui de la migration provoque des erreurs !

Si vous avez une idée..