文件首頁
MySQL Connector/NET 開發人員指南
相關文件 下載本手冊
PDF (美式信紙) - 1.3MB
PDF (A4) - 1.3MB


7.1 Entity Framework 6 支援

MySQL Connector/NET 整合了對 Entity Framework 6 (EF6) 的支援,現在也包含對 EF 6.4 版本跨平台應用程式部署的支援。本章說明如何在 Connector/NET 中設定和使用 EF6 功能。

在本節中

僅限 Windows 上的 EF6 最低需求

  • Connector/NET 6.10 或 8.0.11

  • MySQL 伺服器 5.6

  • Entity Framework 6 組件

  • .NET Framework 4.6.2

具有跨平台支援的 EF 6.4 最低需求

  • Connector/NET 8.0.22

  • MySQL 伺服器 5.6

  • Entity Framework 6.4 組件

  • .NET Standard 2.1 (.NET Core SDK 3.1 和 Visual Studio 2019 版本 16.5)

設定

注意

MySQL Connector/NET 8.0 發行系列具有與先前發行系列 (例如 6.9 和 6.10) 使用的配置不同的 EF6 組件和 NuGet 套件命名配置。若要設定 Connector/NET 6.9 或 6.10 以用於 EF6,請將本節中的組件和套件名稱替換為下列名稱

若要設定 Connector/NET 對 EF6 的支援

  1. 編輯 app.config 檔案中的設定區段,以新增連線字串和 Connector/NET 提供者。

    <connectionStrings>
        <add name="MyContext" providerName="MySql.Data.MySqlClient"
            connectionString="server=localhost;port=3306;database=mycontext;uid=root;password=********"/>
    </connectionStrings>
    <entityFramework>
        <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework"/>
        <providers>
            <provider invariantName="MySql.Data.MySqlClient"
                type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.EntityFramework"/>
            <provider invariantName="System.Data.SqlClient"
                type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/>
        </providers>
    </entityFramework>
  2. 使用下列其中一種技術來套用組件參考

    • NuGet 套件。 安裝 NuGet 套件,以在安裝期間自動將此參考新增至 app.configweb.config 檔案。例如,若要安裝 Connector/NET 8.0.22 的套件,請使用下列其中一個安裝選項

      • 命令列介面 (CLI)

        dotnet add package MySql.Data.EntityFramework -Version 8.0.22
      • 套件管理員主控台 (PMC)

        Install-Package MySql.Data.EntityFramework -Version 8.0.22
      • 搭配 NuGet 套件管理員的 Visual Studio。針對此選項,請選取 nuget.org 作為套件來源,搜尋 mysql.data,然後安裝 MySql.Data.EntityFramework 的穩定版本。

    • MySQL Connector/NET MSI 檔案。 安裝 MySQL Connector/NET,然後將 MySql.Data.EntityFramework 組件的參考新增至您的專案。根據使用的 .NET Framework 版本,組件取自 v4.0v4.5v4.8 資料夾。

    • MySQL Connector/NET 原始碼。 從原始碼建置 Connector/NET,然後將下列資料提供者資訊插入 app.configweb.config 檔案

      <system.data>
         <DbProviderFactories>
           <remove invariant="MySql.Data.MySqlClient" />
           <add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" 
                type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=8.0.22.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
         </DbProviderFactories>
      </system.data>
      重要

      務必更新版本號碼,以符合 MySql.Data.dll 組件中的版本號碼。

  3. 為 MySQL 設定新的 DbConfiguration 類別。此步驟為選用步驟,但強烈建議使用,因為它會新增 MySQL 類別的所有相依性解析器。這可以使用三種方式完成

    • 在內容類別上新增 DbConfigurationTypeAttribute

      [DbConfigurationType(typeof(MySqlEFConfiguration))]
    • 在應用程式啟動時呼叫 DbConfiguration.SetConfiguration(new MySqlEFConfiguration())

    • 在設定檔中設定 DbConfiguration 類型

      <entityFramework codeConfigurationType="MySql.Data.Entity.MySqlEFConfiguration, MySql.Data.EntityFramework">

    也可以建立自訂 DbConfiguration 類別,並新增所需的相依性解析器。

EF6 功能

以下是 Connector/NET 中實作的 Entity Framework 6 新功能

  • 跨平台支援 Connector/NET 8.0.22 實作 EF 6.4 作為初始提供者版本,包含來自 Microsoft 的 Linux 和 macOS 與 .NET Standard 2.1 的相容性。

  • 非同步查詢和儲存 新增了對 .NET 4.5 中提供的以工作為基礎的非同步模式的支援。Connector/NET 支援的新非同步方法為

    • ExecuteNonQueryAsync

    • ExecuteScalarAsync

    • PrepareAsync

  • 連線復原/重試邏輯 啟用從暫時性連線失敗自動復原。若要使用此功能,請新增至 OnCreateModel 方法

    SetExecutionStrategy(MySqlProviderInvariantName.ProviderName, () => new MySqlExecutionStrategy());
  • 以程式碼為基礎的設定 讓您可以選擇在程式碼中執行設定,而不是像傳統做法一樣在設定檔中執行設定。

  • 相依性解析 導入了對服務定位器的支援。可以取代為自訂實作的某些功能已分解出來。若要新增相依性解析器,請使用

    AddDependencyResolver(new MySqlDependencyResolver());

    可以新增下列解析器

    • DbProviderFactory -> MySqlClientFactory

    • IDbConnectionFactory -> MySqlConnectionFactory

    • MigrationSqlGenerator -> MySqlMigrationSqlGenerator

    • DbProviderServices -> MySqlProviderServices

    • IProviderInvariantName -> MySqlProviderInvariantName

    • IDbProviderFactoryResolver -> MySqlProviderFactoryResolver

    • IManifestTokenResolver -> MySqlManifestTokenResolver

    • IDbModelCacheKey -> MySqlModelCacheKeyFactory

    • IDbExecutionStrategy -> MySqlExecutionStrategy

  • 攔截/SQL 記錄 提供用於攔截 Entity Framework 作業的低階建置區塊,並在之上建置簡單 SQL 記錄

    myContext.Database.Log = delegate(string message) { Console.Write(message); };
  • DbContext 現在可以使用已開啟的 DbConnection 建立,這會在建立內容時 (例如當您無法保證連線狀態時,在元件之間共用連線) 如果可以開啟連線,則會很有幫助。

      [DbConfigurationType(typeof(MySqlEFConfiguration))]
      class JourneyContext : DbContext
      {
        public DbSet<MyPlace> MyPlaces { get; set; }
    
        public JourneyContext()
          : base()
        {
    
        }
    
        public JourneyContext(DbConnection existingConnection, bool contextOwnsConnection)
          : base(existingConnection, contextOwnsConnection)
        {
    
        }
      }
    
      using (MySqlConnection conn = new MySqlConnection("<connectionString>"))
      {
        conn.Open();
        ...
    
        using (var context = new JourneyContext(conn, false))
        {
          ...
        }
      }
  • 改善的交易支援 提供對架構外部交易的支援,以及在 Entity Framework 中建立交易的改善方式。從 Entity Framework 6 開始,如果沒有已存在的交易,Database.ExecuteSqlCommand() 預設會將命令包裝在交易中。這個方法有許多多載,可讓使用者視需要覆寫此行為。透過 ObjectContext.ExecuteFunction() 等 API 在模型中包含的預存程序執行也會執行相同的動作。也可以將現有交易傳遞至內容。

  • DbSet.AddRange/RemoveRange 提供將多個實體新增至集合或從集合中移除多個實體的最佳化方式。

Code First 功能

以下是 Connector/NET 支援的新 Code First 功能

  • Code First 對插入/更新/刪除預存程序的對應 支援

    modelBuilder.Entity<EntityType>().MapToStoredProcedures();
  • 等冪移轉腳本 允許您產生一個 SQL 腳本,該腳本可以將資料庫從任何版本升級到最新版本。若要執行此操作,請在 Package Manager Console 中執行 Update-Database -Script -SourceMigration: $InitialDatabase 命令。

  • 可設定的移轉歷史記錄表 允許您自訂移轉歷史記錄表的定義。

使用 EF6 的範例

以下 C# 程式碼範例代表 Entity Framework 6 模型的結構。

using MySql.Data.Entity;
using System.Data.Common;
using System.Data.Entity;

namespace EF6
{
  // Code-Based Configuration and Dependency resolution
  [DbConfigurationType(typeof(MySqlEFConfiguration))]
  public class Parking : DbContext
  {
    public DbSet<Car> Cars { get; set; }

    public Parking()
      : base()
    {

    }

    // Constructor to use on a DbConnection that is already opened
    public Parking(DbConnection existingConnection, bool contextOwnsConnection)
      : base(existingConnection, contextOwnsConnection)
    {

    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
      base.OnModelCreating(modelBuilder);
      modelBuilder.Entity<Car>().MapToStoredProcedures();
    }
  }

  public class Car
  {
    public int CarId { get; set; }

    public string Model { get; set; }

    public int Year { get; set; }

    public string Manufacturer { get; set; }
  }
}

以下 C# 程式碼範例顯示如何在應用程式中使用先前模型中的實體,該應用程式將資料儲存在 MySQL 表格中。

using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;

namespace EF6
{
  class Example
  {
    public static void ExecuteExample()
    {
      string connectionString = "server=localhost;port=3305;database=parking;uid=root";

      using (MySqlConnection connection = new MySqlConnection(connectionString))
      {
        // Create database if not exists
        using (Parking contextDB = new Parking(connection, false))
        {
          contextDB.Database.CreateIfNotExists();
        }

        connection.Open();
        MySqlTransaction transaction = connection.BeginTransaction();

        try
        {
          // DbConnection that is already opened
          using (Parking context = new Parking(connection, false))
          {

            // Interception/SQL logging
            context.Database.Log = (string message) => { Console.WriteLine(message); };

            // Passing an existing transaction to the context
            context.Database.UseTransaction(transaction);

            // DbSet.AddRange
            List<Car> cars = new List<Car>();

            cars.Add(new Car { Manufacturer = "Nissan", Model = "370Z", Year = 2012 });
            cars.Add(new Car { Manufacturer = "Ford", Model = "Mustang", Year = 2013 });
            cars.Add(new Car { Manufacturer = "Chevrolet", Model = "Camaro", Year = 2012 });
            cars.Add(new Car { Manufacturer = "Dodge", Model = "Charger", Year = 2013 });

            context.Cars.AddRange(cars);

            context.SaveChanges();
          }

          transaction.Commit();
        }
        catch
        {
          transaction.Rollback();
          throw;
        }
      }
    }
  }
}