使用 Azure Cosmos DB 模拟器在本地进行开发
模拟器的一个常见用例是在构建应用程序时充当开发数据库。 使用模拟器进行开发可帮助你了解为 Azure Cosmos DB 等数据库创建和建模数据的特点,且不会产生任何服务费用。 此外,将模拟器用作自动化工作流的一部分,可以确保能够运行相同的集成测试套件。 模拟器可以确保在本地开发计算机和远程持续集成作业中运行相同的测试。
先决条件
- .NET 6 或更高版本、Node.js v20 或更高版本或 Python 3.7 或更高版本
- 确保在
PATH
中提供所有必需的可执行文件。
- 确保在
- Windows 模拟器
- 64 位 Windows Server 2016、2019、Windows 10 或 Windows 11。
- 最低硬件要求:
- 2-GB RAM
- 10-GB 可用硬盘空间
- Docker 模拟器
安装模拟器
模拟器有多个变体,每个变体的安装过程都相对顺畅。
要开始使用,请从 Microsoft 容器注册表 (MCR) 获取容器映像的 Linux 变体。
将
mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator
Linux 容器映像从容器注册表拉取到本地 Docker 主机。docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latest
检查以确保模拟器映像在本地 Docker 主机上可用。
docker images
要开始使用,请从 Microsoft 容器注册表 (MCR) 获取容器映像的 Linux 变体。
使用
mongodb
标记将mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator
Linux 容器映像从容器注册表拉取到本地 Docker 主机。docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:mongodb
检查以确保模拟器映像在本地 Docker 主机上可用。
docker images
模拟器的 Docker 容器变体(Linux 或 Windows)不支持 API for Apache Cassandra、API for Apache Gremlin 或 API for Table。
启动模拟器
下载后,启用指定的 API 并启动模拟器。
模拟器的 Docker 容器变体不支持 API for Apache Cassandra。
模拟器的 Docker 容器变体不支持 API for Apache Gremlin。
模拟器的 Docker 容器变体不支持 API for Table。
使用容器映像和以下配置来运行新容器:
说明 (可选) AZURE_COSMOS_EMULATOR_PARTITION_COUNT
指定要使用的分区数。 (可选) AZURE_COSMOS_EMULATOR_ENABLE_DATA_PERSISTENCE
在模拟器运行间隙启用数据持久性。 (可选) AZURE_COSMOS_EMULATOR_IP_ADDRESS_OVERRIDE
替代模拟器的默认 IP 地址。 对于 Linux 系统,请使用:
docker run \ --publish 8081:8081 \ --publish 10250-10255:10250-10255 \ --name linux-emulator \ --detach \ mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latest
对于 Windows 系统,请使用:
$parameters = @( "--publish", "8081:8081" "--publish", "10250-10255:10250-10255" "--name", "windows-emulator" "--detach" ) docker run @parameters mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latest
导航到
https://localhost:8081/_explorer/index.html
以访问数据资源管理器。
使用容器映像和以下配置来运行新容器:
说明 AZURE_COSMOS_EMULATOR_ENABLE_MONGODB_ENDPOINT
指定要使用的 MongoDB 终结点版本。 支持的终结点包括: 3.2
、3.6
或4.0
。(可选) AZURE_COSMOS_EMULATOR_PARTITION_COUNT
指定要使用的分区数。 (可选) AZURE_COSMOS_EMULATOR_ENABLE_DATA_PERSISTENCE
在模拟器运行间隙启用数据持久性。 (可选) AZURE_COSMOS_EMULATOR_IP_ADDRESS_OVERRIDE
替代模拟器的默认 IP 地址。 对于 Linux 系统,请使用:
docker run \ --publish 8081:8081 \ --publish 10250:10250 \ --env AZURE_COSMOS_EMULATOR_ENABLE_MONGODB_ENDPOINT=4.0 \ --name linux-emulator \ --detach \ mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:mongodb
对于 Windows 系统,请使用:
$parameters = @( "--publish", "8081:8081" "--publish", "10250:10250" "--env", "AZURE_COSMOS_EMULATOR_ENABLE_MONGODB_ENDPOINT=4.0" "--name", "windows-emulator" "--detach" ) docker run @parameters mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:mongodb
导航到
https://localhost:8081/_explorer/index.html
以访问数据资源管理器。
导入模拟器的 TLS/SSL 证书
导入模拟器的 TLS/SSL 证书,以便在客户端不禁用 TLS/SSL的情况下将模拟器与首选开发人员 SDK 一起使用。
模拟器的 Docker 容器变体(Linux 或 Windows)不支持 API for Apache Cassandra、API for Apache Gremlin 或 API for Table。
模拟器的证书位于正在运行的容器上的 _explorer/emulator.pem
路径中。 使用 curl
可将证书从正在运行的容器下载到本地计算机。
从正在运行的容器获取证书。
对于 Linux 系统,请使用:
curl --insecure https://localhost:8081/_explorer/emulator.pem > ~/emulatorcert.crt
对于 Windows 系统,请使用:
$parameters = @{ Uri = 'https://localhost:8081/_explorer/emulator.pem' Method = 'GET' OutFile = 'emulatorcert.crt' SkipCertificateCheck = $True } Invoke-WebRequest @parameters
使用适用于操作系统的相应命令重新生成证书捆绑包。
对于基于 Debian 的 Linux 系统(例如 Ubuntu),请使用:
sudo update-ca-certificates
对于基于 CentOS 的 Linux 系统(例如 CentOS、Fedora),请使用:
sudo update-ca-trust
对于 Windows 系统,请使用:
certutil -f -addstore "Root" ~/emulatorcert.crt
有关详细说明,请参阅特定于你的操作系统的文档。
模拟器的证书位于正在运行的容器上的 /_explorer/emulator.pem
路径中。
从正在运行的容器将证书下载到本地计算机。
对于 Linux 系统,请使用:
curl --insecure https://localhost:8081/_explorer/emulator.pem > ~/emulatorcert.crt
对于 Windows 系统,请使用:
$parameters = @{ Uri = 'https://localhost:8081/_explorer/emulator.pem' Method = 'GET' OutFile = 'emulatorcert.crt' SkipCertificateCheck = $True } Invoke-WebRequest @parameters
注意
如果以前修改过主机(或 IP 地址)和端口号,则可能需要更改这些值。
按照通常用于操作系统的过程安装证书。 例如,在 Linux 中,将证书复制到
/usr/local/share/ca-certificates/
路径。对于 Linux 系统,请使用:
cp ~/emulatorcert.crt /usr/local/share/ca-certificates/
对于 Windows 系统,请使用:
$parameters = @{ FilePath = 'emulatorcert.crt' CertStoreLocation = 'Cert:\CurrentUser\Root' } Import-Certificate @parameters
对于 Linux 系统,使用适用于 Linux 发行版的相应命令重新生成证书捆绑包。
对于基于 Debian 的 Linux 系统(例如 Ubuntu),请使用:
sudo update-ca-certificates
对于基于 CentOS 的 Linux 系统(例如 CentOS、Fedora),请使用:
sudo update-ca-trust
有关详细说明,请参阅特定于你的操作系统的文档。
从 SDK 连接到仿真器
每个 SDK 都包含一个客户端类,通常用于将 SDK 连接到 Azure Cosmos DB 帐户。 使用模拟器的凭据,可以改为将 SDK 连接到模拟器实例。
使用 Azure Cosmos DB API for NoSQL .NET SDK 从 .NET 应用程序连接到模拟器。
从空文件夹开始。
创建新的 .NET 控制台应用程序
dotnet new console
从 NuGet 添加
Microsoft.Azure.Cosmos
包。dotnet add package Microsoft.Azure.Cosmos
打开 Program.cs 文件。
删除文件中的任何现有内容。
为
Microsoft.Azure.Cosmos
命名空间添加一个 using 块。
// <imports>
using Microsoft.Azure.Cosmos;
// </imports>
// <client>
using CosmosClient client = new(
accountEndpoint: "https://localhost:8081/",
authKeyOrResourceToken: "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
);
// </client>
// <resources>
Database database = await client.CreateDatabaseIfNotExistsAsync(
id: "cosmicworks",
throughput: 400
);
Container container = await database.CreateContainerIfNotExistsAsync(
id: "products",
partitionKeyPath: "/id"
);
// </resources>
// <upsert>
var item = new
{
id = "68719518371",
name = "Kiama classic surfboard"
};
await container.UpsertItemAsync(item);
// </upsert>
- 使用仿真器的凭据创建 CosmosClient 的新实例。
// <imports>
using Microsoft.Azure.Cosmos;
// </imports>
// <client>
using CosmosClient client = new(
accountEndpoint: "https://localhost:8081/",
authKeyOrResourceToken: "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
);
// </client>
// <resources>
Database database = await client.CreateDatabaseIfNotExistsAsync(
id: "cosmicworks",
throughput: 400
);
Container container = await database.CreateContainerIfNotExistsAsync(
id: "products",
partitionKeyPath: "/id"
);
// </resources>
// <upsert>
var item = new
{
id = "68719518371",
name = "Kiama classic surfboard"
};
await container.UpsertItemAsync(item);
// </upsert>
- 使用 CreateDatabaseIfNotExistsAsync 和 CreateContainerIfNotExistsAsync 创建新的数据库和容器。
// <imports>
using Microsoft.Azure.Cosmos;
// </imports>
// <client>
using CosmosClient client = new(
accountEndpoint: "https://localhost:8081/",
authKeyOrResourceToken: "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
);
// </client>
// <resources>
Database database = await client.CreateDatabaseIfNotExistsAsync(
id: "cosmicworks",
throughput: 400
);
Container container = await database.CreateContainerIfNotExistsAsync(
id: "products",
partitionKeyPath: "/id"
);
// </resources>
// <upsert>
var item = new
{
id = "68719518371",
name = "Kiama classic surfboard"
};
await container.UpsertItemAsync(item);
// </upsert>
- 使用 UpsertItemAsync 在容器中创建新项。
// <imports>
using Microsoft.Azure.Cosmos;
// </imports>
// <client>
using CosmosClient client = new(
accountEndpoint: "https://localhost:8081/",
authKeyOrResourceToken: "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
);
// </client>
// <resources>
Database database = await client.CreateDatabaseIfNotExistsAsync(
id: "cosmicworks",
throughput: 400
);
Container container = await database.CreateContainerIfNotExistsAsync(
id: "products",
partitionKeyPath: "/id"
);
// </resources>
// <upsert>
var item = new
{
id = "68719518371",
name = "Kiama classic surfboard"
};
await container.UpsertItemAsync(item);
// </upsert>
运行 .NET 应用程序。
dotnet run
警告
如果收到 SSL 错误,可能需要为应用程序禁用 TLS/SSL。 如果在本地计算机上进行开发,在容器中使用 Azure Cosmos DB 模拟器,并且尚未导入容器的 SSL 证书,则通常会发生这种情况。 要解决此问题,请在创建客户端之前配置客户端选项,禁用 TLS/SSL 验证:
CosmosClientOptions options = new () { HttpClientFactory = () => new HttpClient(new HttpClientHandler() { ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator }), ConnectionMode = ConnectionMode.Gateway, }; using CosmosClient client = new( ..., ..., clientOptions: options );
提示
有关可使用 .NET SDK 执行的更多操作,请参阅 .NET 开发人员指南。
使用 MongoDB .NET 驱动程序 从 .NET 应用程序连接到模拟器。
从空文件夹开始。
创建新的 .NET 控制台应用程序
dotnet new console
从 NuGet 添加
MongoDB.Driver
包。dotnet add package MongoDB.Driver
打开 Program.cs 文件。
删除文件中的任何现有内容。
为
MongoDB.Driver
命名空间添加一个 using 块。
// <imports>
using MongoDB.Driver;
// </imports>
// <client>
var client = new MongoClient(
"mongodb://localhost:C2y6yDjf5%2FR%2Bob0N8A7Cgv30VRDJIWEHLM%2B4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw%2FJw%3D%3D@localhost:10255/admin?ssl=true&retrywrites=false"
);
// </client>
// <resources>
var database = client.GetDatabase("cosmicworks");
var collection = database.GetCollection<dynamic>("products");
// </resources>
// <insert>
var item = new
{
name = "Kiama classic surfboard"
};
await collection.InsertOneAsync(item);
// </insert>
- 使用模拟器的凭据创建
MongoClient
的新实例。
// <imports>
using MongoDB.Driver;
// </imports>
// <client>
var client = new MongoClient(
"mongodb://localhost:C2y6yDjf5%2FR%2Bob0N8A7Cgv30VRDJIWEHLM%2B4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw%2FJw%3D%3D@localhost:10255/admin?ssl=true&retrywrites=false"
);
// </client>
// <resources>
var database = client.GetDatabase("cosmicworks");
var collection = database.GetCollection<dynamic>("products");
// </resources>
// <insert>
var item = new
{
name = "Kiama classic surfboard"
};
await collection.InsertOneAsync(item);
// </insert>
- 使用
GetDatabase
和GetCollection<>
获取数据库和容器。
// <imports>
using MongoDB.Driver;
// </imports>
// <client>
var client = new MongoClient(
"mongodb://localhost:C2y6yDjf5%2FR%2Bob0N8A7Cgv30VRDJIWEHLM%2B4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw%2FJw%3D%3D@localhost:10255/admin?ssl=true&retrywrites=false"
);
// </client>
// <resources>
var database = client.GetDatabase("cosmicworks");
var collection = database.GetCollection<dynamic>("products");
// </resources>
// <insert>
var item = new
{
name = "Kiama classic surfboard"
};
await collection.InsertOneAsync(item);
// </insert>
- 使用
InsertOneAsync
在 XXX 中创建新项。
// <imports>
using MongoDB.Driver;
// </imports>
// <client>
var client = new MongoClient(
"mongodb://localhost:C2y6yDjf5%2FR%2Bob0N8A7Cgv30VRDJIWEHLM%2B4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw%2FJw%3D%3D@localhost:10255/admin?ssl=true&retrywrites=false"
);
// </client>
// <resources>
var database = client.GetDatabase("cosmicworks");
var collection = database.GetCollection<dynamic>("products");
// </resources>
// <insert>
var item = new
{
name = "Kiama classic surfboard"
};
await collection.InsertOneAsync(item);
// </insert>
运行 .NET 应用程序。
dotnet run
使用 Apache Cassandra .NET 驱动程序 从 .NET 应用程序连接到模拟器。
从空文件夹开始。
创建新的 .NET 控制台应用程序
dotnet new console
从 NuGet 添加
CassandraCSharpDriver
包。dotnet add package CassandraCSharpDriver
打开 Program.cs 文件。
删除文件中的任何现有内容。
为
Cassandra
命名空间添加一个 using 块。
// <imports>
using Cassandra;
// </imports>
// <client>
var options = new SSLOptions(
sslProtocol: System.Security.Authentication.SslProtocols.Tls12,
checkCertificateRevocation: true,
remoteCertValidationCallback: (_, _, _, policyErrors) => policyErrors == System.Net.Security.SslPolicyErrors.None);
using var cluster = Cluster.Builder()
.WithCredentials(
username: "localhost",
password: "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
)
.WithPort(
port: 10350
)
.AddContactPoint(
address: "localhost"
)
.WithSSL(
sslOptions: options
)
.Build();
using var session = cluster.Connect();
// </client>
// <resources>
var createKeyspace = await session.PrepareAsync("CREATE KEYSPACE IF NOT EXISTS cosmicworks WITH replication = {'class':'basicclass', 'replication_factor': 1};");
await session.ExecuteAsync(createKeyspace.Bind());
var createTable = await session.PrepareAsync("CREATE TABLE IF NOT EXISTS cosmicworks.products (id text PRIMARY KEY, name text)");
await session.ExecuteAsync(createTable.Bind());
// </resources>
// <insert>
var item = new
{
id = "68719518371",
name = "Kiama classic surfboard"
};
var createItem = await session.PrepareAsync("INSERT INTO cosmicworks.products (id, name) VALUES (?, ?)");
var createItemStatement = createItem.Bind(item.id, item.name);
await session.ExecuteAsync(createItemStatement);
// </insert>
// <imports>
using Cassandra;
// </imports>
// <client>
var options = new SSLOptions(
sslProtocol: System.Security.Authentication.SslProtocols.Tls12,
checkCertificateRevocation: true,
remoteCertValidationCallback: (_, _, _, policyErrors) => policyErrors == System.Net.Security.SslPolicyErrors.None);
using var cluster = Cluster.Builder()
.WithCredentials(
username: "localhost",
password: "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
)
.WithPort(
port: 10350
)
.AddContactPoint(
address: "localhost"
)
.WithSSL(
sslOptions: options
)
.Build();
using var session = cluster.Connect();
// </client>
// <resources>
var createKeyspace = await session.PrepareAsync("CREATE KEYSPACE IF NOT EXISTS cosmicworks WITH replication = {'class':'basicclass', 'replication_factor': 1};");
await session.ExecuteAsync(createKeyspace.Bind());
var createTable = await session.PrepareAsync("CREATE TABLE IF NOT EXISTS cosmicworks.products (id text PRIMARY KEY, name text)");
await session.ExecuteAsync(createTable.Bind());
// </resources>
// <insert>
var item = new
{
id = "68719518371",
name = "Kiama classic surfboard"
};
var createItem = await session.PrepareAsync("INSERT INTO cosmicworks.products (id, name) VALUES (?, ?)");
var createItemStatement = createItem.Bind(item.id, item.name);
await session.ExecuteAsync(createItemStatement);
// </insert>
- 使用
PrepareAsync
和ExecuteAsync
创建新的数据库和容器。
// <imports>
using Cassandra;
// </imports>
// <client>
var options = new SSLOptions(
sslProtocol: System.Security.Authentication.SslProtocols.Tls12,
checkCertificateRevocation: true,
remoteCertValidationCallback: (_, _, _, policyErrors) => policyErrors == System.Net.Security.SslPolicyErrors.None);
using var cluster = Cluster.Builder()
.WithCredentials(
username: "localhost",
password: "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
)
.WithPort(
port: 10350
)
.AddContactPoint(
address: "localhost"
)
.WithSSL(
sslOptions: options
)
.Build();
using var session = cluster.Connect();
// </client>
// <resources>
var createKeyspace = await session.PrepareAsync("CREATE KEYSPACE IF NOT EXISTS cosmicworks WITH replication = {'class':'basicclass', 'replication_factor': 1};");
await session.ExecuteAsync(createKeyspace.Bind());
var createTable = await session.PrepareAsync("CREATE TABLE IF NOT EXISTS cosmicworks.products (id text PRIMARY KEY, name text)");
await session.ExecuteAsync(createTable.Bind());
// </resources>
// <insert>
var item = new
{
id = "68719518371",
name = "Kiama classic surfboard"
};
var createItem = await session.PrepareAsync("INSERT INTO cosmicworks.products (id, name) VALUES (?, ?)");
var createItemStatement = createItem.Bind(item.id, item.name);
await session.ExecuteAsync(createItemStatement);
// </insert>
- 使用
ExecuteAsync
在表中创建新项。 使用Bind
为项分配属性。
// <imports>
using Cassandra;
// </imports>
// <client>
var options = new SSLOptions(
sslProtocol: System.Security.Authentication.SslProtocols.Tls12,
checkCertificateRevocation: true,
remoteCertValidationCallback: (_, _, _, policyErrors) => policyErrors == System.Net.Security.SslPolicyErrors.None);
using var cluster = Cluster.Builder()
.WithCredentials(
username: "localhost",
password: "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
)
.WithPort(
port: 10350
)
.AddContactPoint(
address: "localhost"
)
.WithSSL(
sslOptions: options
)
.Build();
using var session = cluster.Connect();
// </client>
// <resources>
var createKeyspace = await session.PrepareAsync("CREATE KEYSPACE IF NOT EXISTS cosmicworks WITH replication = {'class':'basicclass', 'replication_factor': 1};");
await session.ExecuteAsync(createKeyspace.Bind());
var createTable = await session.PrepareAsync("CREATE TABLE IF NOT EXISTS cosmicworks.products (id text PRIMARY KEY, name text)");
await session.ExecuteAsync(createTable.Bind());
// </resources>
// <insert>
var item = new
{
id = "68719518371",
name = "Kiama classic surfboard"
};
var createItem = await session.PrepareAsync("INSERT INTO cosmicworks.products (id, name) VALUES (?, ?)");
var createItemStatement = createItem.Bind(item.id, item.name);
await session.ExecuteAsync(createItemStatement);
// </insert>
运行 .NET 应用程序。
dotnet run
重要
在启动之前,API for Apache Gremlin 要求你在模拟器中创建资源。 创建名为 db1
的数据库和名为 coll1
的容器。 吞吐量设置与本指南无关,可以随意设置。
使用 Apache Gremlin .NET 驱动程序 从 .NET 应用程序连接到模拟器。
从空文件夹开始。
创建新的 .NET 控制台应用程序
dotnet new console
从 NuGet 添加
Gremlin.Net
包。dotnet add package Gremlin.Net
打开 Program.cs 文件。
删除文件中的任何现有内容。
为
Gremlin.Net.Driver
命名空间添加一个 using 块。
// <imports>
using Gremlin.Net.Driver;
// </imports>
// <client>
var server = new GremlinServer(
hostname: "localhost",
port: 8901,
username: "/dbs/db1/colls/coll1",
password: "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
);
using var client = new GremlinClient(
gremlinServer: server,
messageSerializer: new Gremlin.Net.Structure.IO.GraphSON.GraphSON2MessageSerializer()
);
// </client>
// <graph>
await client.SubmitAsync(
requestScript: "g.V().drop()"
);
// </graph>
// <insert>
await client.SubmitAsync(
requestScript: "g.addV('product').property('id', prop_id).property('name', prop_name)",
bindings: new Dictionary<string, object>
{
{ "prop_id", "68719518371" },
{ "prop_name", "Kiama classic surfboard" }
}
);
// </insert>
- 使用模拟器的凭据创建
GremlinServer
和GremlinClient
的新实例。
// <imports>
using Gremlin.Net.Driver;
// </imports>
// <client>
var server = new GremlinServer(
hostname: "localhost",
port: 8901,
username: "/dbs/db1/colls/coll1",
password: "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
);
using var client = new GremlinClient(
gremlinServer: server,
messageSerializer: new Gremlin.Net.Structure.IO.GraphSON.GraphSON2MessageSerializer()
);
// </client>
// <graph>
await client.SubmitAsync(
requestScript: "g.V().drop()"
);
// </graph>
// <insert>
await client.SubmitAsync(
requestScript: "g.addV('product').property('id', prop_id).property('name', prop_name)",
bindings: new Dictionary<string, object>
{
{ "prop_id", "68719518371" },
{ "prop_name", "Kiama classic surfboard" }
}
);
// </insert>
- 使用
SubmitAsync
清理图形。
// <imports>
using Gremlin.Net.Driver;
// </imports>
// <client>
var server = new GremlinServer(
hostname: "localhost",
port: 8901,
username: "/dbs/db1/colls/coll1",
password: "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
);
using var client = new GremlinClient(
gremlinServer: server,
messageSerializer: new Gremlin.Net.Structure.IO.GraphSON.GraphSON2MessageSerializer()
);
// </client>
// <graph>
await client.SubmitAsync(
requestScript: "g.V().drop()"
);
// </graph>
// <insert>
await client.SubmitAsync(
requestScript: "g.addV('product').property('id', prop_id).property('name', prop_name)",
bindings: new Dictionary<string, object>
{
{ "prop_id", "68719518371" },
{ "prop_name", "Kiama classic surfboard" }
}
);
// </insert>
- 再次使用
SubmitAsync
,可使用指定参数向图形添加新项。
// <imports>
using Gremlin.Net.Driver;
// </imports>
// <client>
var server = new GremlinServer(
hostname: "localhost",
port: 8901,
username: "/dbs/db1/colls/coll1",
password: "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
);
using var client = new GremlinClient(
gremlinServer: server,
messageSerializer: new Gremlin.Net.Structure.IO.GraphSON.GraphSON2MessageSerializer()
);
// </client>
// <graph>
await client.SubmitAsync(
requestScript: "g.V().drop()"
);
// </graph>
// <insert>
await client.SubmitAsync(
requestScript: "g.addV('product').property('id', prop_id).property('name', prop_name)",
bindings: new Dictionary<string, object>
{
{ "prop_id", "68719518371" },
{ "prop_name", "Kiama classic surfboard" }
}
);
// </insert>
运行 .NET 应用程序。
dotnet run
使用 适用于 .NET 的 Azure Tables SDK 从 .NET 应用程序连接到模拟器。
从空文件夹开始。
创建新的 .NET 控制台应用程序
dotnet new console
从 NuGet 添加
Azure.Data.Tables
包。dotnet add package Azure.Data.Tables
打开 Program.cs 文件。
删除文件中的任何现有内容。
为
Azure.Data.Tables
命名空间添加一个 using 块。
// <imports>
using Azure.Data.Tables;
// </imports>
// <client>
var serviceClient = new TableServiceClient(
connectionString: "DefaultEndpointsProtocol=http;AccountName=localhost;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==;TableEndpoint=http://localhost:8902/;"
);
// </client>
// <resources>
var client = serviceClient.GetTableClient(
tableName: "cosmicworksproducts"
);
await client.CreateIfNotExistsAsync();
// </resources>
// <upsert>
var item = new Product
{
RowKey = "68719518371",
PartitionKey = "Surfboards",
Name = "Kiama classic surfboard",
Timestamp = DateTimeOffset.Now
};
await client.UpsertEntityAsync(
entity: item,
mode: TableUpdateMode.Replace
);
// </upsert>
- 使用模拟器的凭据创建
TableServiceClient
的新实例。
// <imports>
using Azure.Data.Tables;
// </imports>
// <client>
var serviceClient = new TableServiceClient(
connectionString: "DefaultEndpointsProtocol=http;AccountName=localhost;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==;TableEndpoint=http://localhost:8902/;"
);
// </client>
// <resources>
var client = serviceClient.GetTableClient(
tableName: "cosmicworksproducts"
);
await client.CreateIfNotExistsAsync();
// </resources>
// <upsert>
var item = new Product
{
RowKey = "68719518371",
PartitionKey = "Surfboards",
Name = "Kiama classic surfboard",
Timestamp = DateTimeOffset.Now
};
await client.UpsertEntityAsync(
entity: item,
mode: TableUpdateMode.Replace
);
// </upsert>
- 使用
GetTableClient
创建带有表名称的TableClient
的新实例。 然后使用CreateIfNotExistsAsync
确保表存在。
// <imports>
using Azure.Data.Tables;
// </imports>
// <client>
var serviceClient = new TableServiceClient(
connectionString: "DefaultEndpointsProtocol=http;AccountName=localhost;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==;TableEndpoint=http://localhost:8902/;"
);
// </client>
// <resources>
var client = serviceClient.GetTableClient(
tableName: "cosmicworksproducts"
);
await client.CreateIfNotExistsAsync();
// </resources>
// <upsert>
var item = new Product
{
RowKey = "68719518371",
PartitionKey = "Surfboards",
Name = "Kiama classic surfboard",
Timestamp = DateTimeOffset.Now
};
await client.UpsertEntityAsync(
entity: item,
mode: TableUpdateMode.Replace
);
// </upsert>
- 为项创建新
record
类型。
// <entity>
public record Product : Azure.Data.Tables.ITableEntity
{
public required string RowKey { get; set; }
public required string PartitionKey { get; set; }
public required string Name { get; init; }
public Azure.ETag ETag { get; set; }
public DateTimeOffset? Timestamp { get; set; }
}
// </entity>
- 使用
UpsertEntityAsync
和Replace
模式在表中创建新项。
// <imports>
using Azure.Data.Tables;
// </imports>
// <client>
var serviceClient = new TableServiceClient(
connectionString: "DefaultEndpointsProtocol=http;AccountName=localhost;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==;TableEndpoint=http://localhost:8902/;"
);
// </client>
// <resources>
var client = serviceClient.GetTableClient(
tableName: "cosmicworksproducts"
);
await client.CreateIfNotExistsAsync();
// </resources>
// <upsert>
var item = new Product
{
RowKey = "68719518371",
PartitionKey = "Surfboards",
Name = "Kiama classic surfboard",
Timestamp = DateTimeOffset.Now
};
await client.UpsertEntityAsync(
entity: item,
mode: TableUpdateMode.Replace
);
// </upsert>
运行 .NET 应用程序。
dotnet run
在 GitHub Actions CI 工作流中使用模拟器
若要运行可自动验证应用程序的持续集成工作负载,请将 Azure Cosmos DB 模拟器与所选框架的测试套件配合使用。 GitHub Action 的托管运行器的 windows-latest
变体中预装了Azure Cosmos DB 模拟器。
使用 .NET 内置测试驱动程序和测试框架(如 MSTest、 NUnit 或 XUnit)来运行测试套件。
验证应用程序的单元测试套件是否按预期运行。
dotnet test
在 GitHub 存储库中创建新工作流,文件名为
.github/workflows/ci.yml
。将作业添加到工作流,以便使用 PowerShell 启动 Azure Cosmos DB 模拟器并运行单元测试套件。
name: Continuous Integration on: push: branches: - main jobs: unit_tests: name: Run .NET unit tests runs-on: windows-latest steps: - name: Checkout (GitHub) uses: actions/checkout@v3 - name: Start Azure Cosmos DB emulator run: | Write-Host "Launching Cosmos DB Emulator" Import-Module "$env:ProgramFiles\Azure Cosmos DB Emulator\PSModules\Microsoft.Azure.CosmosDB.Emulator" Start-CosmosDbEmulator - name: Run .NET tests run: dotnet test
注意
使用各种参数或 PowerShell 命令从命令行启动模拟器。 有关详细信息,请参阅 模拟器命令行参数。