應用程式從舊版升級 EF 核心 2.0Upgrading applications from previous versions to EF Core 2.0

通用的所有應用程式的程序Procedures Common to All Applications

可能需要更新現有的應用程式為 EF 核心 2.0:Updating an existing application to EF Core 2.0 may require:

  1. 升級至支援的.NET 標準 2.0 應用程式的目標.NET 平台。Upgrading the target .NET platform of the application to one that supports .NET Standard 2.0. 請參閱支援的平台如需詳細資訊。See Supported Platforms for more details.

  2. 識別目標資料庫的 EF 核心 2.0 相容的提供者。Identify a provider for the target database which is compatible with EF Core 2.0. 請參閱EF 核心 2.0 需要 2.0 資料庫提供者下方。See EF Core 2.0 requires a 2.0 database provider below.

  3. 將所有 EF 核心封裝 (執行階段和工具) 都升級為 2.0。Upgrading all the EF Core packages (runtime and tooling) to 2.0. 請參閱安裝 EF 核心如需詳細資訊。Refer to Installing EF Core for more details.

  4. 進行任何必要的程式碼變更,以彌補重大變更。Make any necessary code changes to compensate for breaking changes. 請參閱的重大變更下面章節以取得詳細資料。See the Breaking Changes section below for more details.

ASP.NET Core 應用程式ASP.NET Core applications

  1. 請特別參閱初始化應用程式的服務提供者的新模式如下所述。See in particular the new pattern for initializing the application's service provider described below.

提示

這個新模式,當更新應用程式為 2.0 強烈建議您,而且在產品功能,例如 Entity Framework Core 移轉工作的順序必要的採用狀況。The adoption of this new pattern when updating applications to 2.0 is highly recommended and is required in order for product features like Entity Framework Core Migrations to work. 其他一般的替代方式是實作IDesignTimeDbContextFactory<TContext >The other common alternative is to implement IDesignTimeDbContextFactory<TContext>.

  1. 以 ASP.NET Core 2.0 為目標的應用程式可以使用 EF 核心 2.0 不協力廠商資料庫提供者以外的其他相依性。Applications targeting ASP.NET Core 2.0 can use EF Core 2.0 without additional dependencies besides third party database providers. 不過,目標為舊版的 ASP.NET Core 應用程式必須升級至 ASP.NET Core 2.0,才能使用 EF 核心 2.0。However, applications targeting previous versions of ASP.NET Core need to upgrade to ASP.NET Core 2.0 in order to use EF Core 2.0. 如需升級為 2.0 的 ASP.NET Core 應用程式的詳細資訊,請參閱ASP.NET Core 上的文件主體For more details on upgrading ASP.NET Core applications to 2.0 see the ASP.NET Core documentation on the subject.

重大變更Breaking Changes

我們已有機會大幅改善我們的現有應用程式開發介面和 2.0 中的行為。We have taken the opportunity to significantly refine our existing APIs and behaviors in 2.0. 有幾個可能需要修改現有的應用程式程式碼的增強功能,雖然我們相信大部分的應用程式的影響會很低時,在大部分情況下,需要只重新編譯和幾乎不需要 「 引導式的變更,以取代過時的 Api。There are a few improvements that can require modifying existing application code, although we believe that for the majority of applications the impact will be low, in most cases requiring just recompilation and minimal guided changes to replace obsolete APIs.

新方法來取得應用程式服務New way of getting application services

已更新 ASP.NET Core web 應用程式的建議的模式 2.0 中斷 1.x 中使用的 EF 核心的設計階段邏輯的方式。The recommended pattern for ASP.NET Core web applications has been updated for 2.0 in a way that broke the design-time logic EF Core used in 1.x. 先前在設計階段 EF 核心會嘗試叫用Startup.ConfigureServices直接才能存取應用程式的服務提供者。Previously at design-time, EF Core would try to invoke Startup.ConfigureServices directly in order to access the application's service provider. 在 ASP.NET Core 2.0 中,設定初始化之外Startup類別。In ASP.NET Core 2.0, Configuration is initialized outside of the Startup class. 通常使用 EF 核心應用程式存取其連接字串從組態中,因此Startup本身已足夠。Applications using EF Core typically access their connection string from Configuration, so Startup by itself is no longer sufficient. 如果您升級 ASP.NET Core 1.x 應用程式,您可能會收到下列錯誤時使用的 EF 核心工具。If you upgrade an ASP.NET Core 1.x application, you may receive the following error when using the EF Core tools.

'ApplicationContext' 上找不到沒有無參數建構函式。No parameterless constructor was found on 'ApplicationContext'. 請加入 'ApplicationContext' 參數的建構函式,或新增的實作 'IDesignTimeDbContextFactory<ApplicationContext>' 中 'ApplicationContext' 相同的組件Either add a parameterless constructor to 'ApplicationContext' or add an implementation of 'IDesignTimeDbContextFactory<ApplicationContext>' in the same assembly as 'ApplicationContext'

新的設計階段攔截已加入 ASP.NET Core 2.0 的預設範本中。A new design-time hook has been added in ASP.NET Core 2.0's default template. 靜態Program.BuildWebHost方法可讓在設計階段存取應用程式的服務提供者的 EF 核心。The static Program.BuildWebHost method enables EF Core to access the application's service provider at design time. 如果您要升級的 ASP.NET Core 1.x 應用程式,您必須更新您Program類別,如下所示。If you are upgrading an ASP.NET Core 1.x application, you will need to update you Program class to resemble the following.

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();
    }
}

重新命名的 IDbContextFactoryIDbContextFactory renamed

為了支援各種不同的應用程式模式,讓使用者更充分掌控如何其DbContext會使用在設計階段,我們有,在過去,提供IDbContextFactory<TContext>介面。In order to support diverse application patterns and give users more control over how their DbContext is used at design time, we have, in the past, provided the IDbContextFactory<TContext> interface. EF 核心工具將在設計階段探索實作這個介面,在您的專案,並使用它來建立DbContext物件。At design-time, the EF Core tools will discover implementations of this interface in your project and use it to create DbContext objects.

這個介面有誤導嘗試重新使用它的其他某些使用者的一般名稱DbContext-建立案例。This interface had a very general name which mislead some users to try re-using it for other DbContext-creating scenarios. 當 EF 工具,則嘗試使用它們的實作設計階段和導致命令,例如它們Update-Databasedotnet ef database update失敗。They were caught off guard when the EF Tools then tried to use their implementation at design-time and caused commands like Update-Database or dotnet ef database update to fail.

為了傳達這個介面的強式設計階段語意,我們已經重新命名以IDesignTimeDbContextFactory<TContext>In order to communicate the strong design-time semantics of this interface, we have renamed it to IDesignTimeDbContextFactory<TContext>.

2.0 版IDbContextFactory<TContext>仍然存在,但已標記為過時。For the 2.0 release the IDbContextFactory<TContext> still exists but is marked as obsolete.

DbContextFactoryOptions 移除DbContextFactoryOptions removed

由於 ASP.NET Core 2.0 變更上面所述的情況下,我們發現DbContextFactoryOptions已不再需要針對新IDesignTimeDbContextFactory<TContext>介面。Because of the ASP.NET Core 2.0 changes described above, we found that DbContextFactoryOptions was no longer needed on the new IDesignTimeDbContextFactory<TContext> interface. 以下是您應該改為使用替代項目。Here are the alternatives you should be using instead.

DbContextFactoryOptionsDbContextFactoryOptions 替代函式Alternative
ApplicationBasePathApplicationBasePath AppContext.BaseDirectoryAppContext.BaseDirectory
ContentRootPathContentRootPath Directory.GetCurrentDirectory()Directory.GetCurrentDirectory()
EnvironmentNameEnvironmentName Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")

變更設計階段工作目錄Design-time working directory changed

ASP.NET Core 2.0 變更也會需要所使用的工作目錄dotnet ef能配合執行您的應用程式時,Visual Studio 所用的工作目錄。The ASP.NET Core 2.0 changes also required the working directory used by dotnet ef to align with the working directory used by Visual Studio when running your application. 這一個可觀察的副作用是該 SQLite 檔案名稱現在是相對於專案目錄,而非輸出目錄像以往一樣。One observable side effect of this is that SQLite filenames are now relative to the project directory and not the output directory like they used to be.

EF 核心 2.0 需要 2.0 資料庫提供者EF Core 2.0 requires a 2.0 database provider

EF 核心 2.0 我們進行了許多簡單化和增強功能的方式資料庫提供者中運作。For EF Core 2.0 we have made many simplifications and improvements in the way database providers work. 這表示 EF 核心 2.0 1.0.x 和 1.1.x 提供者將無法運作。This means that 1.0.x and 1.1.x providers will not work with EF Core 2.0.

在 SQL Server 和 SQLite 提供者所隨附的 EF 小組和 2.0 版則會一部分在 2.0 版。The SQL Server and SQLite providers are shipped by the EF team and 2.0 versions will be available as part of the 2.0 release. 開放原始碼協力廠商提供者SQL CompactPostgreSQL,和MySQL 2.0 正在更新。The open-source third party providers for SQL Compact, PostgreSQL, and MySQL are being updated for 2.0. 對於所有其他的提供者,請連絡提供者寫入器。For all other providers, please contact the provider writer.

記錄和診斷事件已變更Logging and Diagnostics events have changed

注意: 這些變更應該不會影響大部分的應用程式程式碼。Note: these changes should not impact most application code.

若要傳送之訊息的事件識別碼ILogger 2.0 中已變更。The event IDs for messages sent to an ILogger have changed in 2.0. 事件識別碼現在是唯一在 EF 核心程式碼中。The event IDs are now unique across EF Core code. 這些訊息時,現在也遵循結構化記錄使用,例如,MVC 的標準模式。These messages now also follow the standard pattern for structured logging used by, for example, MVC.

記錄器類別也已經變更。Logger categories have also changed. 現在透過一組已知的類別存取DbLoggerCategoryThere is now a well-known set of categories accessed through DbLoggerCategory.

DiagnosticSource事件現在會使用相同的事件識別碼名稱為對應ILogger訊息。DiagnosticSource events now use the same event ID names as the corresponding ILogger messages. 事件裝載是所有名義型別衍生自EventDataThe event payloads are all nominal types derived from EventData.

事件識別碼、 內容類型和類別目錄會記載於CoreEventIdRelationalEventId類別。Event IDs, payload types, and categories are documented in the CoreEventId and the RelationalEventId classes.

識別碼也已從 Microsoft.EntityFrameworkCore.Infraestructure 轉換成新的 Microsoft.EntityFrameworkCore.Diagnostics 命名空間。IDs have also moved from Microsoft.EntityFrameworkCore.Infraestructure to the new Microsoft.EntityFrameworkCore.Diagnostics namespace.

EF 核心關聯式中繼資料 API 變更EF Core relational metadata API changes

EF 核心 2.0 現在建置不同IModel每個不同提供者所使用。EF Core 2.0 will now build a different IModel for each different provider being used. 這是通常看不到應用程式。This is usually transparent to the application. 使任何存取權,這已透過實現的較低層級中繼資料 Api 簡化_common 關聯式中繼資料的概念_一定會透過呼叫.Relational而不是.SqlServer.Sqlite等等。例如,1.1.x 如下的程式碼:This has facilitated a simplification of lower-level metadata APIs such that any access to common relational metadata concepts is always made through a call to .Relational instead of .SqlServer, .Sqlite, etc. For example, 1.1.x code like this:

var tableName = context.Model.FindEntityType(typeof(User)).SqlServer().TableName;

現在應該撰寫如下:Should now be written like this:

var tableName = context.Model.FindEntityType(typeof(User)).Relational().TableName;

而不是使用類似的方法ForSqlServerToTable,擴充方法現在已可供條件式根據撰寫程式碼中使用目前的提供者。Instead of using methods like ForSqlServerToTable, extension methods are now available to write conditional code based on the current provider in use. 例如:For example:

modelBuilder.Entity<User>().ToTable(
    Database.IsSqlServer() ? "SqlServerName" : "OtherName");

請注意,這項變更只適用於應用程式開發介面/中繼資料定義的_所有_關聯式的提供者。Note that this change only applies to APIs/metadata that is defined for all relational providers. 應用程式開發介面和中繼資料保持不變時特有的單一提供者。The API and metadata remains the same when it is specific to only a single provider. 例如,叢集的索引是特定 SQL Sever,因此ForSqlServerIsClustered.SqlServer().IsClustered()仍可使用。For example, clustered indexes are specific to SQL Sever, so ForSqlServerIsClustered and .SqlServer().IsClustered() must still be used.

不會控制 EF 服務提供者Don’t take control of the EF service provider

EF 核心會使用內部IServiceProvider(也就是相依性插入容器) 的內部實作。EF Core uses an internal IServiceProvider (i.e. a dependency injection container) for its internal implementation. 應用程式應該允許建立和管理在特殊情況下除外此提供者的 EF 核心。Applications should allow EF Core to create and manage this provider except in special cases. 強烈建議您移除的任何呼叫UseInternalServiceProviderStrongly consider removing any calls to UseInternalServiceProvider. 如果應用程式需要呼叫UseInternalServiceProvider,請考慮提出問題讓我們可以調查其他方式來處理您的案例。If an application does need to call UseInternalServiceProvider, then please consider filing an issue so we can investigate other ways to handle your scenario.

呼叫AddEntityFrameworkAddEntityFrameworkSqlServer,除非,應用程式碼不需要等UseInternalServiceProvider也稱為。Calling AddEntityFramework, AddEntityFrameworkSqlServer, etc. is not required by application code unless UseInternalServiceProvider is also called. 移除任何現有的呼叫AddEntityFrameworkAddEntityFrameworkSqlServer等等AddDbContext應該仍可用於相同的方式與之前。Remove any existing calls to AddEntityFramework or AddEntityFrameworkSqlServer, etc. AddDbContext should still be used in the same way as before.

記憶體中資料庫必須命名為In-memory databases must be named

已移除全域未命名的記憶體中資料庫,而是必須命名為記憶體中的所有資料庫。The global unnamed in-memory database has been removed and instead all in-memory databases must be named. 例如:For example:

optionsBuilder.UseInMemoryDatabase("MyDatabase");

這會建立/使用名稱為"MyDatabase"的資料庫。This creates/uses a database with the name “MyDatabase”. 如果UseInMemoryDatabase會再次呼叫相同的名稱,與相同的記憶體中資料庫則會使用,讓它可以由多個內容執行個體共用。If UseInMemoryDatabase is called again with the same name, then the same in-memory database will be used, allowing it to be shared by multiple context instances.

唯讀應用程式開發介面變更Read-only API changes

IsReadOnlyBeforeSave``IsReadOnlyAferSave,和IsStoreGeneratedAlways認定為過時並取代BeforeSaveBehaviorAfterSaveBehaviorIsReadOnlyBeforeSave, IsReadOnlyAferSave, and IsStoreGeneratedAlways have been obsoleted and replaced with BeforeSaveBehavior and AfterSaveBehavior. 這些行為套用至任何屬性 (不只由存放區產生的屬性),並判斷插入資料庫的資料列時如何使用屬性的值 (BeforeSaveBehavior) 或更新現有資料庫的資料列時 (AfterSaveBehavior)。These behaviors apply to any property (not only store-generated properties) and determine how the value of the property should be used when inserting into a database row (BeforeSaveBehavior) or when updating an existing database row (AfterSaveBehavior).

屬性標記為ValueGenerated.OnAddOrUpdate (例如,用於計算資料行) 將會依預設忽略目前的屬性上設定任何值。Properties marked as ValueGenerated.OnAddOrUpdate (e.g. for computed columns) will by default ignore any value currently set on the property. 這表示存放區產生的值一律取得不論是否已設定或修改追蹤的實體上的任何值。This means that a store-generated value will always be obtained regardless of whether any value has been set or modified on the tracked entity. 可以變更此設定不同Before\AfterSaveBehaviorThis can be changed by setting a different Before\AfterSaveBehavior.

新的 ClientSetNull 刪除行為New ClientSetNull delete behavior

在舊版中, DeleteBehavior.Restrict有實體行為受到內容追蹤多個關閉相符SetNull語意。In previous releases, DeleteBehavior.Restrict had a behavior for entities tracked by the context that more closed matched SetNull semantics. 在 EF 核心 2.0 中,新ClientSetNull為選擇性的關聯性的預設值已經導入行為。In EF Core 2.0, a new ClientSetNull behavior has been introduced as the default for optional relationships. 這種行為有SetNull追蹤實體的語意和Restrict建立使用 EF 核心資料庫的行為。This behavior has SetNull semantics for tracked entities and Restrict behavior for databases created using EF Core. 在我們的經驗,這些是追蹤的實體和資料庫必須是/實用的行為。In our experience, these are the most expected/useful behaviors for tracked entities and the database. DeleteBehavior.Restrict現在接受一個選擇性的關聯性設定時的追蹤實體。DeleteBehavior.Restrict is now honored for tracked entities when set for optional relationships.

提供者的設計階段套件移除Provider design-time packages removed

Microsoft.EntityFrameworkCore.Relational.Design已移除套件。The Microsoft.EntityFrameworkCore.Relational.Design package has been removed. 它的內容已合併到Microsoft.EntityFrameworkCore.RelationalMicrosoft.EntityFrameworkCore.DesignIt's contents were consolidated into Microsoft.EntityFrameworkCore.Relational and Microsoft.EntityFrameworkCore.Design.

這會傳播到提供者的設計階段套件。This propagates into the provider design-time packages. 這些封裝 (Microsoft.EntityFrameworkCore.Sqlite.DesignMicrosoft.EntityFrameworkCore.SqlServer.Design等等) 已移除成員和其內容合併到主要提供者的封裝。Those packages (Microsoft.EntityFrameworkCore.Sqlite.Design, Microsoft.EntityFrameworkCore.SqlServer.Design, etc.) were removed and their contents consolidated into the main provider packages.

若要啟用Scaffold-DbContextdotnet ef dbcontext scaffold在 EF 核心 2.0 中,您只需要參考單一提供者封裝:To enable Scaffold-DbContext or dotnet ef dbcontext scaffold in EF Core 2.0, you only need to reference the single provider package:

<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" />