diff --git a/examples/EntityFrameworkCore.Ydb.Samples/AddEntity.Sample/Program.cs b/examples/EntityFrameworkCore.Ydb.Samples/AddEntity.Sample/Program.cs index d820a45a..d0de254b 100644 --- a/examples/EntityFrameworkCore.Ydb.Samples/AddEntity.Sample/Program.cs +++ b/examples/EntityFrameworkCore.Ydb.Samples/AddEntity.Sample/Program.cs @@ -1,6 +1,4 @@ -// See https://aka.ms/new-console-template for more information - -using Section_1.HR; +using Section_1.HR; InsertDepartments(); SelectDepartments(); diff --git a/examples/Ydb.Sdk.AdoNet.Dapper.QuickStart/Program.cs b/examples/Ydb.Sdk.AdoNet.Dapper.QuickStart/Program.cs index 4e050913..5555a29e 100644 --- a/examples/Ydb.Sdk.AdoNet.Dapper.QuickStart/Program.cs +++ b/examples/Ydb.Sdk.AdoNet.Dapper.QuickStart/Program.cs @@ -1,5 +1,3 @@ -// See https://aka.ms/new-console-template for more information - using Dapper; using Ydb.Sdk.Ado; diff --git a/examples/Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container/Dockerfile b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container/Dockerfile new file mode 100644 index 00000000..58f9cd5a --- /dev/null +++ b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container/Dockerfile @@ -0,0 +1,10 @@ +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY . . +RUN dotnet restore +RUN dotnet publish -c Release -r linux-x64 -o /app/build + +FROM --platform=linux/amd64 mcr.microsoft.com/dotnet/runtime:8.0 AS run +WORKDIR /app +COPY --from=build /app/build/. . +ENTRYPOINT ["dotnet", "Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container.dll"] diff --git a/examples/Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container/Program.cs b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container/Program.cs new file mode 100644 index 00000000..111184da --- /dev/null +++ b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container/Program.cs @@ -0,0 +1,33 @@ +using System.Diagnostics; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using Ydb.Sdk.Ado; +using Ydb.Sdk.Yc; + +var connectionString = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json") + .Build() + .GetConnectionString("ServerlessYDB") ?? + throw new InvalidOperationException("ConnectionString.ServerlessYDB is empty."); + +var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Information)); +var logger = loggerFactory.CreateLogger(); +var stopwatch = Stopwatch.StartNew(); +stopwatch.Start(); + +await using var dataSource = new YdbDataSource( + new YdbConnectionStringBuilder(connectionString) + { + CredentialsProvider = new MetadataProvider(loggerFactory: loggerFactory), + LoggerFactory = loggerFactory, + DisableDiscovery = true + } +); + +await using var ydbCommand = dataSource.CreateCommand(); +ydbCommand.CommandText = "SELECT 'Hello Serverless YDB from Yandex Cloud Serverless Container!'u"; +var scalar = await ydbCommand.ExecuteScalarAsync(); +stopwatch.Stop(); + +logger.LogInformation("Success request! [Ms: {Ms}], {Select}", stopwatch.ElapsedMilliseconds, scalar); \ No newline at end of file diff --git a/examples/Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container/README.md b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container/README.md new file mode 100644 index 00000000..a7469b7b --- /dev/null +++ b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container/README.md @@ -0,0 +1,46 @@ +# YDB Sdk ADO.NET for Serverless Containers in Yandex Cloud + +Sample application uses the YDB SDK for ADO.NET and can be deployed +to [Yandex Cloud Serverless Containers](https://yandex.cloud/en/docs/serverless-containers/). + +## Getting started + +1. **Setup + ** [Yandex Container Registry](https://yandex.cloud/en/docs/container-registry/operations/registry/registry-create). +2. **Build and Push Docker Image** + ```bash + docker build . -t cr.yandex//ado-net-app:latest + docker push cr.yandex//ado-net-app:latest + ``` + Replace with your actual Container Registry ID. +3. **Grant Required Permissions**. To enable your Serverless Container to access both YDB and your container image in + the Container Registry, grant the following roles to your Service Account: + + - `ydb.editor` — access to YDB, + - `container-registry.images.puller` — permission to pull images from Container Registry. + +4. **Create a new revision**. After pushing your image, create a new version of the Serverless Container as described in + the [official guide](https://yandex.cloud/en/docs/serverless-containers/quickstart/container#create-revision). + Specify your image and the necessary environment variables and secrets. + +5. **Running the Yandex Serverless Container**. + After the new revision has been rolled out, you can use your container (e.g., for a health check) by executing the + following command: + ```bash + curl --header "Authorization: Bearer $(yc iam create-token)" https:/// + ``` + Replace with your actual serverless container host. + +## ⚠️ Important Note: YdbDataSource and Connection Handling + +When using the YDB SDK in a serverless container, it is always necessary to create a new YdbDataSource for each request +or function invocation. + +This is because the network connectivity between a serverless container and external resources, such as YDB, can be +interrupted or reset during execution. If you cache or reuse existing connections, you may experience failures due to +stale or invalid connections. + +Best practice: + +_Create a fresh data source (or Driver for Topic API) for every request or function invocation in order to ensure +reliability in the serverless environment._ diff --git a/examples/Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container/Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container.csproj b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container/Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container.csproj new file mode 100644 index 00000000..5406ef55 --- /dev/null +++ b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container/Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container.csproj @@ -0,0 +1,23 @@ + + + + Exe + net8.0 + enable + enable + Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container + + + + + + + + + + + + PreserveNewest + + + diff --git a/examples/Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container/appsettings.json b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container/appsettings.json new file mode 100644 index 00000000..47870f7e --- /dev/null +++ b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container/appsettings.json @@ -0,0 +1,5 @@ +{ + "ConnectionStrings": { + "ServerlessYDB": "UseTls=true;Host=;Port=2135;Database=" + } +} diff --git a/examples/Ydb.Sdk.AdoNet.Yandex.Cloud/Ydb.Sdk.AdoNet.Yandex.Cloud.csproj b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud/Ydb.Sdk.AdoNet.Yandex.Cloud.csproj index 5702f8e1..305770ef 100644 --- a/examples/Ydb.Sdk.AdoNet.Yandex.Cloud/Ydb.Sdk.AdoNet.Yandex.Cloud.csproj +++ b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud/Ydb.Sdk.AdoNet.Yandex.Cloud.csproj @@ -12,7 +12,6 @@ - diff --git a/examples/Ydb.Sdk.QueryService.QuickStart/Program.cs b/examples/Ydb.Sdk.QueryService.QuickStart/Program.cs index 7e036265..fd59ecde 100644 --- a/examples/Ydb.Sdk.QueryService.QuickStart/Program.cs +++ b/examples/Ydb.Sdk.QueryService.QuickStart/Program.cs @@ -20,8 +20,6 @@ internal class CmdOptions public bool FallbackAnonymous { get; set; } = false; } -// See https://aka.ms/new-console-template for more information - internal static class Program { private static ServiceProvider GetServiceProvider() => diff --git a/examples/YdbExamples.sln b/examples/YdbExamples.sln index 8966b920..4e37d6b8 100644 --- a/examples/YdbExamples.sln +++ b/examples/YdbExamples.sln @@ -27,6 +27,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Schema.ManyToMany", "Entity EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Database.Operations.Tutorial", "EntityFrameworkCore.Ydb.Samples\Database.Operations.Tutorial\Database.Operations.Tutorial.csproj", "{B2B0786F-7545-4717-8D04-26DF9C181607}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container", "Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container\Ydb.Sdk.AdoNet.Yandex.Cloud.Serverless.Container.csproj", "{77625697-498B-4879-BABA-046EE93E7AF7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -81,6 +83,10 @@ Global {B2B0786F-7545-4717-8D04-26DF9C181607}.Debug|Any CPU.Build.0 = Debug|Any CPU {B2B0786F-7545-4717-8D04-26DF9C181607}.Release|Any CPU.ActiveCfg = Release|Any CPU {B2B0786F-7545-4717-8D04-26DF9C181607}.Release|Any CPU.Build.0 = Release|Any CPU + {77625697-498B-4879-BABA-046EE93E7AF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {77625697-498B-4879-BABA-046EE93E7AF7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {77625697-498B-4879-BABA-046EE93E7AF7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {77625697-498B-4879-BABA-046EE93E7AF7}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE