65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Azure Functions 和 SQLite 构建微型 Web API

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (6投票s)

2021年9月3日

CPOL

6分钟阅读

viewsIcon

14318

如何使用 Azure Functions 和 SQLite 构建一个精简、低资源、可扩展的 API 服务。

引言

在本文中,我们将使用 Azure Function 和 SQLite 作为后端来编写一个基础 API。

我们将创建一个 Web API,它根据您发送的邮政编码返回一个城市。这将是一个简单、小型服务,可用于表单和其他查找。

我们将使用一个预先填充的 SQLite 数据库,并构建一个 Azure Function 来与之交互并提供 Web API 接口。

SQLite 是一个小型、独立的 SQL 数据库引擎,非常适合处理小数据。它是一个设计精良、性能高且可靠的数据库,您可能每天都在使用它。由于其体积小和资源占用少,它在手机和其他便携式设备上无处不在。

您可以通过 Pluralsight 的 Android: SQLite Fundamentals 课程了解更多关于 SQLite 的信息。虽然它侧重于 Android 开发,但它很好地涵盖了 SQLite 的基础知识。

您可以在这里了解更多关于 Azure Functions 的信息。

数据库

此项目的数据库可在此处 下载。这将是我们正在处理的数据库。

它是一个包含城市及其对应邮政编码的数据库。数据库的架构如下所示:

Creating a Microservice with Azure Functions and SQLite

该数据库包含美国大多数城市的信息,以邮政编码作为主键。

我们将本地连接到此数据库,并将其打包随我们的 Azure Function 一起部署。

设置我们的 Azure Function

我们将需要在 Azure 中设置一个 Azure Function 来部署我们的应用程序。以下是操作步骤。

登录到您的 Azure Portal。搜索“Function App”。

Creating a Microservice with Azure Functions and SQLite

点击“创建”。您会看到一个类似下图的对话框。

Creating a Microservice with Azure Functions and SQLite

选择您的资源组,然后指定项目的名称。这将是您服务的域名。

选择“代码”进行发布,并选择 **.NET** 作为运行时堆栈。

选择版本 **3.1**。

以及您希望 Azure Function 所在的区域。

然后点击 **Review + create**(审阅 + 创建)。

创建我们的 Azure Function

打开 Visual Studio 2019(或更高版本)并创建一个新项目。

搜索 **Azure Functions** 模板,然后点击“下一步”。

Creating a Microservice with Azure Functions and SQLite

为您的项目命名,随意命名。我将其命名为“ZiptoCity”。

Creating a Microservice with Azure Functions and SQLite

确保选择:

  • .NET Core 3 (LTS)
  • Http trigger(HTTP 触发器)
  • Anonymous authorization level(匿名授权级别)

然后创建项目。

创建模型

创建一个名为 *Models* 的新文件夹,并创建一个名为 *City.cs* 的新类。这将是我们作为结果返回的模型。

向您的类添加以下属性,使其看起来像这样:

using Newtonsoft.Json;

namespace ZiptoCity.Models
{
    public class City
    {
        [JsonProperty("zipcode")]
        public int ZipCode { get; set; }

        [JsonProperty("cityname")]
        public string CityName { get; set; }

        [JsonProperty("county")]
        public string County { get; set; }

        [JsonProperty("state")]
        public string State { get; set; }

        [JsonProperty("timezone")]
        public string TimeZone { get; set; }
    }
}

这些是我们希望在 API 中公开的数据库片段。我们使用 JsonProperty 来装饰属性,因为之后它将以 JSON 格式显示。

创建我们的主函数

接下来,我们将创建访问此数据的函数。

右键单击项目文件夹,选择“添加”->“新建 Azure Function”。

Creating a Microservice with Azure Functions and SQLite

选择 **Http trigger**(HTTP 触发器)并选择 **anonymous**(匿名)身份验证。

Creating a Microservice with Azure Functions and SQLite

并添加新文件。

您会看到一个新函数。我们来做一些更改。

在自动生成的方法的签名中,您会看到这个:

public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, ILogger log)

将其更改为如下所示:

public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "city/{id}")] HttpRequest req, ILogger log, int id)

我们将从可用的 API 方法中删除 **POST**,因为我们不使用它。

然后我们将添加一个新路由,该路由接受 {id} 作为参数。这里我们将添加邮政编码。

最后,我们将使用 **int id** 来捕获该 ID。

让我们更改日志消息。

log.LogInformation("Requested city for " + id);

现在我们将连接到数据库。

注意:对于较大的应用程序,最好抽象数据库连接信息。但由于我们只执行一个操作,所以我决定将所有连接处理放在方法内部。

连接到数据库

现在我们将连接到 SQLite 数据库。确保将此数据库复制到名为 Data 的文件夹中,并将数据库设置为 **Copy always**(始终复制)。

Creating a Microservice with Azure Functions and SQLite

然后我们需要安装 SQLite Nuget 包。

Install-Package System.Data.SQLite -Version 1.0.115

在我们的 Run 方法中,添加以下内容:

var sqlite_conn = new SQLiteConnection(@"Data Source=Data\zipcode.db; Version = 3; New = True; Compress = True; ");

try
{
    sqlite_conn.Open();
}
catch (Exception ex)
{
    log.LogInformation("Error: " + ex.Message);
}

此代码连接到位于 Data 文件夹的 SQLite 数据库。如果连接出现问题,将会被记录下来。

查询数据

接下来,我们将添加一些行来创建一个 SQLiteDataReader 和一个 SQLiteCommand 来填充数据。

SQLiteDataReader sqlite_datareader;
SQLiteCommand sqlite_cmd;
sqlite_cmd = sqlite_conn.CreateCommand();

现在,我们将创建一个查询来从数据库中获取我们想要返回的数据。我们将把 id 作为参数传递给查询。

sqlite_cmd.CommandText = "SELECT zip, primaryCity, state, county, timezone FROM zip_code_database WHERE zip = '" + id + "'";

然后我们可以执行读取器。

sqlite_datareader = sqlite_cmd.ExecuteReader();

检索和分配数据

现在我们想使用读取器来填充我们要返回的 City 对象。我们将创建一个要填充的对象。

var resultCity = new City { };

我们还将创建一个布尔值,可以在发送最终结果之前进行检查。

var goodResult = false;

然后,我们将创建一个循环,如果我们的查询结果成功,该循环将运行。

if (sqlite_datareader.HasRows)
{
    goodResult = true;
    
    while (sqlite_datareader.Read())
    {
        resultCity.ZipCode = sqlite_datareader.GetInt32(0);
        resultCity.CityName = sqlite_datareader.GetString(1);
        resultCity.State = sqlite_datareader.GetString(2);
        resultCity.County = sqlite_datareader.GetString(3);
        resultCity.TimeZone = sqlite_datareader.GetString(4);
    }
}

在此循环中,我们将 goodResult 设置为 true。然后循环遍历 datareader,并将值从 datareader 分配给我们的 resultCity 对象。

现在我们可以关闭连接。

sqlite_conn.Close();

发送结果

现在我们已准备好根据查询发送结果。如果我们未从数据库收到城市,goodResult 将保持 false。

如果查询成功,我们将发送 City 对象的 JSON 表示形式。

if (goodResult)
{                
    return new OkObjectResult(resultCity);
}
else
{
    return new NotFoundResult();
}

完成!现在我们的 Azure Function 已准备好进行测试。

完整的函数

完整的函数应如下所示:

[FunctionName("ZipCodeLookup")]
public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "city/{id}")] HttpRequest req,
    ILogger log, int id)
    {
        log.LogInformation("Requested city for " + id);

        var sqlite_conn = new SQLiteConnection(@"Data Source=Data\zipcode.db; Version = 3; New = True; Compress = True; ");

        try
        {
            sqlite_conn.Open();
        }
        catch (Exception ex)
        {
            log.LogInformation("Error: " + ex.Message);
        }

        SQLiteDataReader sqlite_datareader;
        SQLiteCommand sqlite_cmd;
        sqlite_cmd = sqlite_conn.CreateCommand();

        sqlite_cmd.CommandText = "SELECT zip, primaryCity, state, county, timezone FROM zip_code_database WHERE zip = '" + id + "'";

        sqlite_datareader = sqlite_cmd.ExecuteReader();

        var resultCity = new City { };
        var goodResult = false;

        if (sqlite_datareader.HasRows)
        {
            goodResult = true;

            while (sqlite_datareader.Read())
            {
                resultCity.ZipCode = sqlite_datareader.GetInt32(0);
                resultCity.CityName = sqlite_datareader.GetString(1);
                resultCity.State = sqlite_datareader.GetString(2);
                resultCity.County = sqlite_datareader.GetString(3);
                resultCity.TimeZone = sqlite_datareader.GetString(4);
            }
        }

        sqlite_conn.Close();

        if (goodResult)
        {                
            return new OkObjectResult(resultCity);
        }
        else
        {
            return new NotFoundResult();
        }
    }
}

让我们来测试一下!

测试 Azure Function

我们现在可以通过按 5 来测试我们的 Azure Function。您会看到一个控制台窗口,显示如何连接它。

Creating a Microservice with Azure Functions and SQLite

您可以本地连接到您的函数,但使用 URL + 示例邮政编码。

Creating a Microservice with Azure Functions and SQLite

既然我们知道它没问题,就可以部署它了。

部署 Azure Function

转到 Build -> Publish(生成 -> 发布),然后选择 Azure。

Creating a Microservice with Azure Functions and SQLite

选择 Azure Function App (Windows)。

Creating a Microservice with Azure Functions and SQLite

选择您的订阅、资源组,然后选择函数应用。确保 Run from package file (recommended)(从包文件中运行(推荐))未被选中。

Creating a Microservice with Azure Functions and SQLite

按 Finish(完成),然后 Publish(发布)以部署到 Azure。

在 Azure 中运行您的应用程序

应用程序已发布到 Azure 后,您需要进行一些快速更改,它就可以准备就绪了。

在 Azure 门户中,选择您的函数。然后向下滚动到 **CORS**。

Creating a Microservice with Azure Functions and SQLite

在允许的来源中,添加通配符(**\***)字符。

注意:对于生产环境,您将需要输入允许访问此应用程序的域名。

Creating a Microservice with Azure Functions and SQLite

保存配置,您就可以开始了。

您现在可以使用浏览器或 Postman 向您的新 API 发送查询。

Creating a Microservice with Azure Functions and SQLite

就是这样!

结论

在此项目中,我们构建了一个小型 Web API,它接受邮政编码并返回城市信息。这是“微型 API”的一个很好的例子,您可以在组织中使用它。小型、精简的应用程序始终很受欢迎,通过使用 Azure Functions 和 SQLite,您可以创建性能良好且可扩展的微型应用程序。

微服务架构日益普及。构建小型、松耦合的服务和 API 可以帮助您的组织构建高性能且易于维护的应用程序。Azure Functions 通过提供小型按使用量付费的空间来构建应用程序,使这一切成为可能。

您可以在这里了解更多关于 Azure Functions 的信息。

© . All rights reserved.