Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Nous avons profité de l’occasion pour affiner de manière significative nos API et comportements existants dans 2.0. Certaines améliorations peuvent nécessiter la modification du code d’application existant, même si nous pensons que pour la majorité des applications, l’impact sera faible, dans la plupart des cas nécessitant juste une recompilation et des modifications guidées minimes pour remplacer les API obsolètes.
La mise à jour d’une application existante vers EF Core 2.0 peut nécessiter les éléments suivants :
Mise à niveau de l’implémentation .NET cible de l’application vers une implémentation qui prend en charge .NET Standard 2.0. Pour plus d’informations, consultez Implémentations .NET prises en charge.
Identifiez un fournisseur pour la base de données cible, compatible avec EF Core 2.0. Consultez EF Core 2.0 nécessite un fournisseur de base de données 2.0 ci-dessous.
Mise à niveau de tous les packages de EF Core (runtime et outils) vers 2.0. Pour plus d’informations, reportez-vous à Installation d’EF Core.
Apportez les modifications nécessaires au code pour compenser les changements cassant décrites dans le reste de ce document.
ASP.NET Core comprend maintenant EF Core
Les applications ciblant ASP.NET Core 2.0 peuvent utiliser EF Core 2.0 sans dépendances supplémentaires en plus des fournisseurs de base de données tiers. Toutefois, les applications ciblant des versions antérieures d’ASP.NET Core doivent être mises à niveau vers ASP.NET Core 2.0 afin d’utiliser EF Core 2.0. Pour plus d’informations sur la mise à niveau des applications ASP.NET Core vers la version 2.0, consultez la documentation ASP.NET Core sur le sujet.
Nouvelle méthode d’obtention des services d’application dans ASP.NET Core
Le modèle recommandé pour les applications web ASP.NET Core a été mis à jour pour 2.0 d’une manière qui a cassé la logique au moment du design utilisée par EF Core dans 1.x. Précédemment, au moment du design, EF Core tentait d’appeler Startup.ConfigureServices
directement pour accéder au fournisseur de services de l’application. Dans ASP.NET Core 2.0, la configuration est initialisée en dehors de la classe Startup
. Les applications utilisant EF Core accèdent généralement à leur chaîne de connexion à partir de Configuration. Par conséquent, Startup
ne se suffit plus à lui-même. Si vous mettez à niveau une application ASP.NET Core 1.x, vous risquez de recevoir l’erreur suivante lors de l’utilisation des outils EF Core.
Aucun constructeur sans paramètre n’a été trouvé sur « ApplicationContext ». Ajoutez un constructeur sans paramètre à « ApplicationContext » ou ajoutez une implémentation de « IDesignTimeDbContextFactory<ApplicationContext> » dans le même assembly que « ApplicationContext »
Un nouveau crochet au moment du design a été ajouté au modèle par défaut de ASP.NET Core 2.0. La méthode Program.BuildWebHost
statique permet à EF Core d’accéder au fournisseur de services de l’application au moment du design. Si vous mettez à niveau une application ASP.NET Core 1.x, vous devez mettre à jour la classe Program
pour ressembler à ce qui suit.
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
namespace AspNetCoreDotNetCore2._0App
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
}
L’adoption de ce nouveau modèle lors de la mise à jour des applications vers 2.0 est vivement recommandée et est nécessaire pour que des fonctionnalités de produit telles que les migrations d’Entity Framework Core fonctionnent. L’autre alternative courante consiste à implémenter IDesignTimeDbContextFactory<TContext>.
IDbContextFactory renommé
Pour prendre en charge divers modèles d’application et donner aux utilisateurs plus de contrôle sur la façon dont leur DbContext
est utilisé au moment du design, nous avons, dans le passé, fourni l’interface IDbContextFactory<TContext>
. Au moment du design, les outils EF Core découvrent les implémentations de cette interface dans votre projet et l’utilisent pour créer des objets DbContext
.
Cette interface avait un nom très général qui a confus certains utilisateurs qui essayaient de la réutiliser pour d’autres scénarios de création de DbContext
. Ils ont été pris au dépourvu lorsque les outils EF ont ensuite essayé d’utiliser leur implémentation au moment du design et ont provoqué l’échec de commandes comme Update-Database
ou dotnet ef database update
.
Pour pouvoir communiquer la sémantique forte au moment du design de cette interface, nous l’avons renommée en IDesignTimeDbContextFactory<TContext>
.
Pour la version 2.0, IDbContextFactory<TContext>
existe toujours, mais est marqué comme obsolète.
DbContextFactoryOptions supprimé
En raison des modifications ASP.NET Core 2.0 décrites ci-dessus, nous avons constaté que DbContextFactoryOptions
n’était plus nécessaire sur la nouvelle interface IDesignTimeDbContextFactory<TContext>
. Voici les alternatives que vous devez utiliser à la place.
DbContextFactoryOptions | Alternative |
---|---|
ApplicationBasePath | AppContext.BaseDirectory |
ContentRootPath | Directory.GetCurrentDirectory() |
EnvironmentName | Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") |
Modification du répertoire de travail au moment du design
Les modifications ASP.NET Core 2.0 ont également requis du répertoire de travail utilisé pour dotnet ef
qu’il s’aligne sur le répertoire de travail utilisé par Visual Studio lors de l’exécution de votre application. L’un des effets secondaires observables est que les noms de fichiers SQLite sont désormais relatifs au répertoire du projet, et non au répertoire de sortie comme auparavant.
EF Core 2.0 requiert un fournisseur de base de données 2.0
Pour EF Core 2.0, nous avons apporté de nombreuses simplifications et améliorations au fonctionnement des fournisseurs de bases de données. Cela signifie que les fournisseurs 1.0.x et 1.1.x ne fonctionneront pas avec EF Core 2.0.
Les fournisseurs SQL Server et SQLite sont fournis par l’équipe EF et les versions 2.0 seront disponibles dans le cadre de la version 2.0. Les fournisseurs tiers open source pour SQL Compact, PostgreSQL etMySQL sont mis à jour pour la version 2.0. Pour tous les autres fournisseurs, contactez le rédacteur du fournisseur.
Les événements de journalisation et de diagnostic ont changé
Remarque : ces modifications ne doivent pas avoir d’impact sur la plupart du code d’application.
Les ID d’événement pour les messages envoyés à un ILogger ont été changés dans la version 2.0. Les ID d’événement sont maintenant uniques dans le code EF Core. En outre, ces messages suivent désormais le modèle standard de la journalisation structurée utilisé, par exemple, par le modèle MVC.
Les catégories d’enregistreurs d’événements ont également changé. Il existe désormais un jeu connu de catégories accessibles par le biais de DbLoggerCategory.
Les événements DiagnosticSource
utilisent désormais les mêmes noms d’ID d’événement que les messages ILogger
correspondants. Les charges utiles d’événement sont toutes des types nominaux dérivés d’EventData.
Les ID d’événement, les types de charge utile et les catégories sont documentés dans les classes CoreEventId et RelationalEventId.
Les ID ont également été déplacés de Microsoft.EntityFrameworkCore.Infrastructure vers le nouvel espace de noms Microsoft.EntityFrameworkCore.Diagnostics.
Modification de l’API de métadonnées relationnelles EF Core
EF Core 2.0 génère désormais un IModel différent par fournisseur utilisé. Cela est généralement transparent pour l’application. Il en résulte une simplification des API de métadonnées de niveau inférieur, au point que tout accès aux concepts de métadonnées relationnelles communs est toujours établi par le biais d’un appel à .Relational
au lieu de .SqlServer
, .Sqlite
, etc. Par exemple, 1.1.x code comme suit :
var tableName = context.Model.FindEntityType(typeof(User)).SqlServer().TableName;
Doit maintenant être écrit comme suit :
var tableName = context.Model.FindEntityType(typeof(User)).Relational().TableName;
Au lieu d’utiliser des méthodes telles que ForSqlServerToTable
, les méthodes d’extension sont désormais disponibles pour écrire du code conditionnel basé sur le fournisseur actuel en cours d’utilisation. Par exemple :
modelBuilder.Entity<User>().ToTable(
Database.IsSqlServer() ? "SqlServerName" : "OtherName");
Notez que cette modification s’applique uniquement aux API/métadonnées définies pour tous les fournisseurs relationnels. L’API et les métadonnées restent les mêmes lorsqu’elles sont spécifiques à un seul fournisseur. Par exemple, les index en cluster sont spécifiques à SQL Server. Par conséquent, ForSqlServerIsClustered
et .SqlServer().IsClustered()
doivent toujours être utilisés.
Ne prenez pas le contrôle du fournisseur de services EF
EF Core utilise un IServiceProvider
interne (un conteneur d’injection de dépendances) pour son implémentation interne. Les applications doivent autoriser EF Core à créer et à gérer ce fournisseur, sauf dans des cas spéciaux. Envisagez fortement de supprimer tous les appels à UseInternalServiceProvider
. Si une application doit appeler UseInternalServiceProvider
, envisagez de signaler un problème afin que nous puissions examiner d’autres façons de gérer votre scénario.
L’appel de AddEntityFramework
, AddEntityFrameworkSqlServer
, etc. n’est pas requis par le code de l’application, sauf si UseInternalServiceProvider
est également appelé. Supprimez les appels existants vers AddEntityFramework
ou AddEntityFrameworkSqlServer
, etc. AddDbContext
doit toujours être utilisé de la même façon que précédemment.
Les bases de données en mémoire doivent être nommées
La base de données en mémoire sans nom globale a été supprimée. À la place, toutes les bases de données en mémoire doivent être nommées. Par exemple :
optionsBuilder.UseInMemoryDatabase("MyDatabase");
Cela crée/utilise une base de données nommée « MyDatabase ». Si UseInMemoryDatabase
est appelée de nouveau avec le même nom, la même base de données en mémoire est utilisée, ce qui lui permet d’être partagée par plusieurs instances de contexte.
L’opération « include » du fournisseur en mémoire ne retourne plus de résultats si la navigation incluse est requise mais que sa valeur est nulle
Lorsque vous tentez d’inclure une navigation requise et que la navigation incluse a la valeur nulle, la requête ne retourne plus de résultat pour l’entité sur laquelle l’opération Include est appliquée. Pour éviter ce problème, fournissez une valeur pour la navigation requise ou modifiez la navigation pour qu’elle soit facultative.
public class Person
{
public int Id { get; set; }
public Language NativeLanguage { get; set;} // required navigation
public Person Sibling { get; set; } // optional navigation
}
...
var person = new Person();
context.People.Add(person);
await context.SaveChangesAsync();
...
// returns one result
await context.People.ToListAsync();
// returns no results because 'NativeLanguage' navigation is required but has not been provided
await context.People.Include(p => p.NativeLanguage).ToListAsync();
// returns one result because 'Sibling' navigation is optional so it doesn't have to be provided
await context.People.Include(p => p.Sibling).ToListAsync();
Modifications de l’API en lecture seule
IsReadOnlyBeforeSave
, IsReadOnlyAfterSave
et IsStoreGeneratedAlways
sont désormais obsolètes et remplacés par BeforeSaveBehavior et AfterSaveBehavior. Ces comportements s’appliquent à n’importe quelle propriété (non seulement les propriétés générées par le magasin) et déterminent comment la valeur de la propriété doit être utilisée lors de l’insertion dans une ligne de base de données (BeforeSaveBehavior
) ou lors de la mise à jour d’une ligne de base de données existante (AfterSaveBehavior
).
Les propriétés marquées comme ValueGenerated.OnAddOrUpdate (par exemple, pour les colonnes calculées) ignorent par défaut toute valeur actuellement définie sur la propriété. Cela signifie qu’une valeur générée par le magasin sera toujours obtenue, qu’une valeur ait été définie ou modifiée sur l’entité suivie. Ceci peut être modifié en définissant un Before\AfterSaveBehavior
différent.
Nouveau comportement de suppression de ClientSetNull
Dans les versions précédentes, DeleteBehavior.Restrict avait un comportement pour les entités suivies par le contexte qui correspondait davantage à la sémantique SetNull
. Dans EF Core 2.0, un nouveau comportement ClientSetNull
a été introduit comme valeur par défaut pour les relations facultatives. Ce comportement a une sémantique SetNull
pour les entités suivies et le comportement Restrict
pour les bases de données créées à l’aide d’EF Core. Dans notre expérience, il s’agit des comportements les plus attendus/utiles pour les entités suivies et la base de données. DeleteBehavior.Restrict
est maintenant respecté pour les entités suivies lorsqu’elles sont définies pour des relations facultatives.
Suppression des packages au moment du design du fournisseur
Le package Microsoft.EntityFrameworkCore.Relational.Design
a été supprimé. Son contenu a été consolidé dans Microsoft.EntityFrameworkCore.Relational
et Microsoft.EntityFrameworkCore.Design
.
Cela se propage dans les packages au moment du design du fournisseur. Ces packages (Microsoft.EntityFrameworkCore.Sqlite.Design
, Microsoft.EntityFrameworkCore.SqlServer.Design
, etc.) ont été supprimés et leur contenu a été consolidé dans les packages principaux du fournisseur.
Pour activer Scaffold-DbContext
ou dotnet ef dbcontext scaffold
dans EF Core 2.0, vous devez uniquement référencer le package de fournisseur unique :
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer"
Version="2.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools"
Version="2.0.0"
PrivateAssets="All" />
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet"
Version="2.0.0" />