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

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

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

  1. 升級為支援.NET Standard 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 Core 2.0 相容的提供者。Identify a provider for the target database which is compatible with EF Core 2.0. 請參閱EF Core 2.0 需要 2.0 資料庫提供者下方。See EF Core 2.0 requires a 2.0 database provider below.

  3. 將所有 EF Core 封裝 (執行階段和工具) 都升級為 2.0。Upgrading all the EF Core packages (runtime and tooling) to 2.0. 請參閱安裝 EF Core如需詳細資訊。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 Core 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 Core 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

我們已大幅改善我們的現有 Api 和 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 Core 的設計階段邏輯的方式。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 Core 會嘗試叫用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 Core 應用程式存取其連接字串從組態中,因此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 Core 工具。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 Core。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 Core 工具將在設計階段探索實作這個介面,在您的專案,並使用它來建立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 Core 2.0 需要 2.0 資料庫提供者EF Core 2.0 requires a 2.0 database provider

EF Core 2.0 我們進行了許多簡單化和增強功能的方式資料庫提供者中運作。For EF Core 2.0 we have made many simplifications and improvements in the way database providers work. 這表示 EF Core 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 Core 程式碼中,事件識別碼現在是唯一的。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. 現在已有一組類別可透過 DbLoggerCategory 進行存取。There 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 Core 關聯式中繼資料 API 變更EF Core relational metadata API changes

EF Core 2.0 現在會為使用的每個不同提供者建置不同的 IModelEF Core 2.0 will now build a different IModel for each different provider being used. 應用程式通常可以看到這項作業。This is usually transparent to the application. 這已加速簡化較低階中繼資料 API;因此,任何對_一般關聯式中繼資料概念_的存取一律是透過 .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");

請注意,這項變更僅適用於已定義的 Api/metadata_所有_關聯式的提供者。Note that this change only applies to APIs/metadata that is defined for all relational providers. API 和中繼資料會保持不變時它是單一提供者所特有。The API and metadata remains the same when it is specific to only a single provider. 例如,叢集的索引是特定 SQL Server,因此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 Core 會使用內部IServiceProvider(相依性插入容器) 內部實作。EF Core uses an internal IServiceProvider (a dependency injection container) for its internal implementation. 應用程式應該允許建立和管理在特殊情況下除外此提供者的 EF Core。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. 移除任何現有的呼叫AddEntityFramework或是AddEntityFrameworkSqlServerAddDbContext應該仍可用於相同的方式和以前一樣。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.

唯讀 API 變更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 (for example, 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 Core 2.0 中,新ClientSetNull為選擇性的關聯性的預設值已經導入行為。In EF Core 2.0, a new ClientSetNull behavior has been introduced as the default for optional relationships. 這種行為有SetNull追蹤實體的語意和Restrict建立使用 EF Core 資料庫的行為。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 Core 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" />