共用方式為


教學課程:使用 Azure Functions 和 Azure Cache for Redis 來建立寫入後置快取

本教學課程的目標是使用 Azure Cache for Redis 執行個體作為寫入後置快取。 本教學課程中的寫入後置模式示範快取的寫入如何觸發 SQL 資料庫的對應寫入 (Azure SQL Database 服務的執行個體)。

您會使用 Azure Functions 的 Redis 觸發程序來實作此功能。 在此案例中,您將了解如何使用 Azure Cache for Redis 來儲存庫存和定價資訊,同時備份 SQL 資料庫中的資訊。

每個寫入快取的新項目或新價格都會反映在資料庫的 SQL 資料表中。

在本教學課程中,您會了解如何:

  • 設定資料庫、觸發程序和連接字串。
  • 驗證觸發程序是否正常運作。
  • 將程式碼部署至函數應用程式。

必要條件

建立並設定新的 SQL 資料庫

SQL 資料庫是此範例的備份資料庫。 您可透過 Azure 入口網站或偏好的自動化方法建立 SQL 資料庫。

如需建立 SQL 資料庫的詳細資訊,請參閱快速入門:建立單一資料庫 - Azure SQL Database

此範例使用入口網站:

  1. 輸入資料庫名稱並選擇 [新建] 來建立新伺服器以保存資料庫。

    建立 Azure SQL 資源的螢幕快照。

  2. 選取 [使用 SQL 驗證],並輸入系統管理員登入和密碼。 請務必記住這些認證或將其寫下。 在實際執行環境中部署伺服器後,請改為使用 Microsoft Entra 驗證。

    Azure SQL 資源的驗證資訊螢幕快照。

  3. 移至 [網路] 索引標籤,然後選擇 [公用端點] 作為連線方法。 針對顯示的兩個防火牆規則,選擇 [是]。 此端點允許從 Azure 函數應用程式進行存取。

    Azure SQL 資源的網路設定螢幕快照。

  4. 驗證完成後,選擇 [檢閱 + 建立],然後選擇 [建立]。 SQL 資料庫開始部署。

  5. 部署完成後,請移至 Azure 入口網站中的資源,然後選擇 [查詢編輯器] 索引標籤。建立名為 [庫存] 的新資料表以保存所要寫入的資料。 使用下列 SQL 命令以建立新資料表,並包含下列兩個欄位:

    • ItemName 列出每個項目的名稱。
    • Price 儲存項目的價格。
    CREATE TABLE inventory (
        ItemName varchar(255),
        Price decimal(18,2)
        );
    

    顯示 Azure SQL 資源 查詢編輯器 中建立數據表的螢幕快照。

  6. 命令完成執行後,請展開 [資料表] 資料夾並驗證已建立新的資料表。

設定 Redis 觸發程序

首先,製作您在上 一個教學課程中使用的相同 VS Code 項目複本。 在新的名稱下複製上一個教學課程的資料夾,例如 RedisWriteBehindTrigger,並在 VS Code 中開啟。

其次,刪除 RedisBindings.csRedisTriggers.cs 檔案。

在此範例中,您會使用 pub/sub 觸發程序以在 keyevent 通知上觸發。 範例的目標如下:

  • 每次發生 SET 事件時觸發。 當新索引鍵寫入至快取執行個體或變更索引鍵值時,便會發生 SET 事件。
  • 觸發 SET 事件後,存取快取執行個體以尋找新索引鍵值。
  • 判斷 SQL 資料庫的 [庫存] 資料表是否已有該索引鍵。
    • 若有,則值為該索引鍵。
    • 若無,則使用索引鍵和其值寫入新的資料列。

若要設定觸發程序:

  1. 匯入 System.Data.SqlClient NuGet 套件以啟用與 SQL 資料庫的通訊。 移至 VS Code 終端並使用下列命令:

      dotnet add package System.Data.SqlClient
    
  2. 建立名為 RedisFunction.cs 的新檔案。 請確定您已刪除 RedisBindings.csRedisTriggers.cs 檔案。

  3. 將下列程式代碼複製並貼到 RedisFunction.cs 中,以取代現有的程式代碼:

using Microsoft.Extensions.Logging;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Extensions.Redis;
using System.Data.SqlClient;

public class WriteBehindDemo
{
    private readonly ILogger<WriteBehindDemo> logger;

    public WriteBehindDemo(ILogger<WriteBehindDemo> logger)
    {
        this.logger = logger;
    }
    
    public string SQLAddress = System.Environment.GetEnvironmentVariable("SQLConnectionString");

    //This example uses the PubSub trigger to listen to key events on the 'set' operation. A Redis Input binding is used to get the value of the key being set.
    [Function("WriteBehind")]
    public void WriteBehind(
        [RedisPubSubTrigger(Common.connectionString, "__keyevent@0__:set")] Common.ChannelMessage channelMessage,
        [RedisInput(Common.connectionString, "GET {Message}")] string setValue)
    {
        var key = channelMessage.Message; //The name of the key that was set
        var value = 0.0;

        //Check if the value is a number. If not, log an error and return.
        if (double.TryParse(setValue, out double result))
        {
            value = result; //The value that was set. (i.e. the price.)
            logger.LogInformation($"Key '{channelMessage.Message}' was set to value '{value}'");
        }
        else
        {
            logger.LogInformation($"Invalid input for key '{key}'. A number is expected.");
            return;
        }        

        // Define the name of the table you created and the column names.
        String tableName = "dbo.inventory";
        String column1Value = "ItemName";
        String column2Value = "Price";        
        
        logger.LogInformation($" '{SQLAddress}'");
        using (SqlConnection connection = new SqlConnection(SQLAddress))
            {
                connection.Open();
                using (SqlCommand command = new SqlCommand())
                {
                    command.Connection = connection;

                    //Form the SQL query to update the database. In practice, you would want to use a parameterized query to prevent SQL injection attacks.
                    //An example query would be something like "UPDATE dbo.inventory SET Price = 1.75 WHERE ItemName = 'Apple'".
                    command.CommandText = "UPDATE " + tableName + " SET " + column2Value + " = " + value + " WHERE " + column1Value + " = '" + key + "'";
                    int rowsAffected = command.ExecuteNonQuery(); //The query execution returns the number of rows affected by the query. If the key doesn't exist, it will return 0.

                    if (rowsAffected == 0) //If key doesn't exist, add it to the database
                 {
                         //Form the SQL query to update the database. In practice, you would want to use a parameterized query to prevent SQL injection attacks.
                         //An example query would be something like "INSERT INTO dbo.inventory (ItemName, Price) VALUES ('Bread', '2.55')".
                        command.CommandText = "INSERT INTO " + tableName + " (" + column1Value + ", " + column2Value + ") VALUES ('" + key + "', '" + value + "')";
                        command.ExecuteNonQuery();

                        logger.LogInformation($"Item " + key + " has been added to the database with price " + value + "");
                    }

                    else {
                        logger.LogInformation($"Item " + key + " has been updated to price " + value + "");
                    }
                }
                connection.Close();
            }

            //Log the time that the function was executed.
            logger.LogInformation($"C# Redis trigger function executed at: {DateTime.Now}");
    }
}

重要

針對教學課程,已簡化此範例。 針對實際執行環境使用,建議您使用參數化 SQL 查詢以防止 SQL 插入式攻擊。

設定連接字串

您必須更新 local.settings.json 檔案以包含 SQL 資料庫的連接字串。 在 Values 區段新增 SQLConnectionString 的項目。 您的檔案看起來應該像下列範例:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
    "redisConnectionString": "<redis-connection-string>",
    "SQLConnectionString": "<sql-connection-string>"
  }
}

若要尋找 Redis 連接字串,請移至 Azure Cache for Redis 資源中的資源功能表。 找出字串位於 [資源] 選單上的 [存取金鑰 ] 區域中。

若要尋找 SQL 資料庫連接字串,請移至 SQL 資料庫資源中的資源功能表。 在 [設定] 下,選擇 [連接字串],然後選擇 [ADO.NET] 索引標籤。字串位於 [ADO.NET (SQL 驗證)] 區域。

您必須手動輸入 SQL 資料庫連接字串的密碼,因為不會自動貼上密碼。

重要

針對教學課程,已簡化此範例。 若要使用生產環境,建議您使用 Azure 金鑰保存庫 來儲存 連接字串 資訊,或使用 Azure EntraID 進行 SQL 驗證

建置和執行專案

  1. 在 VS Code 中,移至 [執行和偵錯] 索引標籤並執行專案。

  2. 返回 Azure 入口網站中的 Azure Cache for Redis 執行個體,並選擇 [主控台] 按鈕以輸入 Redis 主控台。 嘗試使用一些指令 SET

    • SET apple 5.25
    • SET bread 2.25
    • SET apple 4.50
  3. 返回 VS Code,觸發程序正在註冊。 若要驗證觸發程序是否正常運作:

    1. 移至 Azure 入口網站中的 SQL 資料庫。

    2. 在資源功能表上,選擇 [查詢編輯器]

    3. 針對 [新增查詢],使用下列 SQL 命令建立查詢以檢視庫存資料表中的前 100 個項目:

      SELECT TOP (100) * FROM [dbo].[inventory]
      

      確認寫入 Azure Cache for Redis 值協個體的項目會在這裡顯示。

    顯示資訊已從快取實例複製到 SQL 的螢幕快照。

將程式碼部署至函數應用程式

本教學課程會以上一個教學課程為基礎來建置。 如詳細資訊,請參閱將程式碼部署至 Azure 函數

  1. 在 VS Code 中,移至 [Azure] 索引標籤。

  2. 尋找訂用帳戶並將其展開。 然後,尋找 [函數應用程式] 並展開該區段。

  3. 選擇並保存 (或以滑鼠右鍵按一下) 函數應用程式,然後選擇 [部署至函數應用程式]

新增連接字串資訊

本教學課程會以上一個教學課程為基礎來建置。 如需 redisConnectionString 的詳細資訊,請參閱新增連接字串資訊

  1. 移至 Azure 入口網站中的函數應用程式。 在資源功能表上,選取 [環境變數]。

  2. 在 [應用程式 設定] 窗格中,輸入 SQL 連線 ionString 作為新字段。 針對 [值],輸入連接字串。

  3. 選取套用

  4. 移至 [概觀] 刀鋒視窗,然後選取 [重新啟動] 以使用新的 連接字串 資訊重新啟動應用程式。

驗證部署

部署完成後,返回 Azure Cache for Redis 執行個體並使用 SET 命令以寫入更多值。 確認這些值顯示在 SQL 資料庫中。

如果您要確認函數應用程式正常運作,請移至入口網站中的應用程式並從資源功能表選擇 [記錄資料流]。 您應在這裡看到觸發程序正在執行並正在對 SQL 資料庫進行對應更新。

如果您要清除 SQL 資料庫資料表而不加以刪除,您可使用下列 SQL 查詢:

TRUNCATE TABLE [dbo].[inventory]

清除資源

如果您想要繼續使用在本文中建立的資源,請保留該資源群組。

否則,若已完成資源使用,則可刪除您建立的 Azure 資源群組,以避免衍生費用。

重要

刪除資源群組是無法回復的動作。 當您刪除資源群組時,其中包含的所有資源都將永久刪除。 請確定您不會不小心刪除錯誤的資源群組或資源。 如果您是在包含需保留資源的現有資源群組內部建立資源,則可以個別刪除每個資源,而不必刪除整個資源群組。

刪除資源群組

  1. 登入 Azure 入口網站,然後選取 [資源群組]

  2. 選取您想要刪除的資源群組。

    如果有許多資源群組,請使用 [篩選任何欄位] 方塊,並輸入您針對本文所建立資源群組的名稱。 選取結果清單中的資源群組。

    顯示工作窗格中要刪除之資源群組清單的螢幕快照。

  3. 選取 [刪除資源群組]

  4. 系統將會要求您確認是否刪除資源群組。 輸入您的資源群組名稱以進行確認,然後選取 [刪除]

    此螢幕快照顯示需要資源名稱才能確認刪除的表單。

不久後,系統便會刪除該資源群組及其所有的資源。

摘要

本教學課程和在 Azure Cache for Redis 中開始使用 Azure Functions 觸發程序示範如何使用 Azure Cache for Redis 以觸發 Azure 函數應用程式。 同時也示範如何使用 Azure Cache for Redis 作為 Azure SQL Database 的寫入後置快取。 搭配使用 Azure Cache for Redis 與 Azure Functions 是功能強大的組合,可解決許多整合和效能問題。