Skip to content

Commit 90d00f8

Browse files
feat EF: Supported Connect to YC (#298)
1 parent dd5de8b commit 90d00f8

File tree

11 files changed

+165
-15
lines changed

11 files changed

+165
-15
lines changed

examples/src/EF_YC/CmdOptions.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using CommandLine;
2+
3+
namespace EF_YC;
4+
5+
internal class CmdOptions
6+
{
7+
[Option('c', "connectionString", Required = true, HelpText = "Connection string")]
8+
public string ConnectionString { get; set; } = null!;
9+
10+
[Option("saFilePath", Required = true, HelpText = "Sa Key")]
11+
public string SaFilePath { get; set; } = null!;
12+
}

examples/src/EF_YC/EF_YC.csproj

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="CommandLineParser" Version="2.8.0"/>
12+
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.0"/>
13+
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0"/>
14+
<PackageReference Include="Ydb.Sdk.Yc.Auth" Version="0.2.0"/>
15+
</ItemGroup>
16+
17+
<ItemGroup>
18+
<ProjectReference Include="..\..\..\src\EfCore.Ydb\src\EfCore.Ydb.csproj"/>
19+
<ProjectReference Include="..\..\..\src\Ydb.Sdk\src\Ydb.Sdk.csproj"/>
20+
</ItemGroup>
21+
</Project>

examples/src/EF_YC/Program.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using CommandLine;
2+
using EF_YC;
3+
using EfCore.Ydb.Extensions;
4+
using Microsoft.EntityFrameworkCore;
5+
using Microsoft.Extensions.Logging;
6+
using Ydb.Sdk.Yc;
7+
8+
await Parser.Default.ParseArguments<CmdOptions>(args).WithParsedAsync(async cmd =>
9+
{
10+
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Information));
11+
var saProvider = new ServiceAccountProvider(saFilePath: cmd.SaFilePath, loggerFactory: loggerFactory);
12+
13+
var options = new DbContextOptionsBuilder<AppDbContext>()
14+
.UseYdb(cmd.ConnectionString, builder =>
15+
{
16+
builder.WithCredentialsProvider(saProvider);
17+
builder.WithServerCertificates(YcCerts.GetYcServerCertificates());
18+
})
19+
.Options;
20+
21+
await using var db = new AppDbContext(options);
22+
db.Database.EnsureCreated();
23+
24+
db.Users.Add(new User { Name = "Alex", Email = "[email protected]" });
25+
db.Users.Add(new User { Name = "Kirill", Email = "[email protected]" });
26+
db.SaveChanges();
27+
28+
var users = db.Users.OrderBy(u => u.Id).ToList();
29+
Console.WriteLine("Users in database:");
30+
foreach (var user in users)
31+
{
32+
Console.WriteLine($"- {user.Id}: {user.Name} ({user.Email})");
33+
}
34+
35+
// Users in database:
36+
// - 1: Alex ([email protected])
37+
// - 2: Kirill ([email protected])
38+
});
39+
40+
41+
internal class User
42+
{
43+
public int Id { get; init; }
44+
public string Name { get; init; } = string.Empty;
45+
public string Email { get; init; } = string.Empty;
46+
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
47+
}
48+
49+
internal class AppDbContext(DbContextOptions options) : DbContext(options)
50+
{
51+
public DbSet<User> Users { get; set; }
52+
}

examples/src/YC/Program.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ await Parser.Default.ParseArguments<CmdOptions>(args).WithParsedAsync(async cmd
99
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Information));
1010

1111
var saProvider = new ServiceAccountProvider(saFilePath: cmd.SaFilePath, loggerFactory: loggerFactory);
12-
await saProvider.Initialize();
1312

1413
var builder = new YdbConnectionStringBuilder
1514
{

examples/src/YC/YC.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
1414
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
1515
<PackageReference Include="Ydb.Protos" Version="1.1.1" />
16-
<PackageReference Include="Ydb.Sdk.Yc.Auth" Version="0.1.0" />
16+
<PackageReference Include="Ydb.Sdk.Yc.Auth" Version="0.2.0" />
1717
</ItemGroup>
1818
<ItemGroup>
1919
<ProjectReference Include="..\..\..\src\Ydb.Sdk\src\Ydb.Sdk.csproj" />

examples/src/YdbExamples.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Topic", "Topic\Topic.csproj
1919
EndProject
2020
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EF", "EF\EF.csproj", "{0CE9DF93-1411-4E73-BA88-A66018FAB948}"
2121
EndProject
22+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EF_YC", "EF_YC\EF_YC.csproj", "{31A2E7BF-45BB-4C63-9DEC-58DD06491EF1}"
23+
EndProject
2224
Global
2325
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2426
Debug|Any CPU = Debug|Any CPU
@@ -57,6 +59,10 @@ Global
5759
{0CE9DF93-1411-4E73-BA88-A66018FAB948}.Debug|Any CPU.Build.0 = Debug|Any CPU
5860
{0CE9DF93-1411-4E73-BA88-A66018FAB948}.Release|Any CPU.ActiveCfg = Release|Any CPU
5961
{0CE9DF93-1411-4E73-BA88-A66018FAB948}.Release|Any CPU.Build.0 = Release|Any CPU
62+
{31A2E7BF-45BB-4C63-9DEC-58DD06491EF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
63+
{31A2E7BF-45BB-4C63-9DEC-58DD06491EF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
64+
{31A2E7BF-45BB-4C63-9DEC-58DD06491EF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
65+
{31A2E7BF-45BB-4C63-9DEC-58DD06491EF1}.Release|Any CPU.Build.0 = Release|Any CPU
6066
EndGlobalSection
6167
GlobalSection(SolutionProperties) = preSolution
6268
HideSolutionNode = FALSE

src/EfCore.Ydb/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Supported connect to Yandex Cloud
Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
using System.Collections.Generic;
2+
using System.Security.Cryptography.X509Certificates;
23
using EfCore.Ydb.Extensions;
34
using Microsoft.EntityFrameworkCore.Infrastructure;
45
using Microsoft.Extensions.DependencyInjection;
6+
using Ydb.Sdk.Auth;
57

68
namespace EfCore.Ydb.Infrastructure.Internal;
79

810
public class YdbOptionsExtension : RelationalOptionsExtension
911
{
12+
public ICredentialsProvider? CredentialsProvider { get; private set; }
13+
14+
public X509Certificate2Collection? ServerCertificates { get; private set; }
15+
1016
private DbContextOptionsExtensionInfo? _info;
1117

1218
public YdbOptionsExtension()
@@ -15,22 +21,40 @@ public YdbOptionsExtension()
1521

1622
private YdbOptionsExtension(YdbOptionsExtension copyFrom) : base(copyFrom)
1723
{
24+
CredentialsProvider = copyFrom.CredentialsProvider;
25+
ServerCertificates = copyFrom.ServerCertificates;
26+
}
27+
28+
protected override RelationalOptionsExtension Clone() => new YdbOptionsExtension(this);
29+
30+
public override void ApplyServices(IServiceCollection services) => services.AddEntityFrameworkYdb();
31+
32+
public override DbContextOptionsExtensionInfo Info => _info ??= new ExtensionInfo(this);
33+
34+
public YdbOptionsExtension WithCredentialsProvider(ICredentialsProvider? credentialsProvider)
35+
{
36+
var clone = (YdbOptionsExtension)Clone();
37+
38+
clone.CredentialsProvider = credentialsProvider;
39+
40+
return clone;
1841
}
1942

20-
protected override RelationalOptionsExtension Clone()
21-
=> new YdbOptionsExtension(this);
43+
public YdbOptionsExtension WithServerCertificates(X509Certificate2Collection? serverCertificates)
44+
{
45+
var clone = (YdbOptionsExtension)Clone();
2246

23-
public override void ApplyServices(IServiceCollection services)
24-
=> services.AddEntityFrameworkYdb();
47+
clone.ServerCertificates = serverCertificates;
2548

26-
public override DbContextOptionsExtensionInfo Info
27-
=> _info ??= new ExtensionInfo(this);
49+
return clone;
50+
}
2851

29-
private sealed class ExtensionInfo(IDbContextOptionsExtension extension) : RelationalExtensionInfo(extension)
52+
private sealed class ExtensionInfo(YdbOptionsExtension extension) : RelationalExtensionInfo(extension)
3053
{
3154
public override bool IsDatabaseProvider => true;
3255

33-
// TODO: Right now it's stub
34-
public override void PopulateDebugInfo(IDictionary<string, string> debugInfo) => debugInfo["Hello"] = "World!";
56+
public override void PopulateDebugInfo(IDictionary<string, string> debugInfo)
57+
{
58+
}
3559
}
3660
}
Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
1+
using System.Security.Cryptography.X509Certificates;
12
using EfCore.Ydb.Infrastructure.Internal;
23
using Microsoft.EntityFrameworkCore;
34
using Microsoft.EntityFrameworkCore.Infrastructure;
5+
using Ydb.Sdk.Auth;
46

57
namespace EfCore.Ydb.Infrastructure;
68

79
public class YdbDbContextOptionsBuilder(DbContextOptionsBuilder optionsBuilder)
8-
: RelationalDbContextOptionsBuilder<YdbDbContextOptionsBuilder, YdbOptionsExtension>(optionsBuilder);
10+
: RelationalDbContextOptionsBuilder<YdbDbContextOptionsBuilder, YdbOptionsExtension>(optionsBuilder)
11+
{
12+
public YdbDbContextOptionsBuilder WithCredentialsProvider(ICredentialsProvider? credentialsProvider) =>
13+
WithOption(optionsBuilder => optionsBuilder.WithCredentialsProvider(credentialsProvider));
14+
15+
public YdbDbContextOptionsBuilder WithServerCertificates(X509Certificate2Collection? serverCertificates) =>
16+
WithOption(optionsBuilder => optionsBuilder.WithServerCertificates(serverCertificates));
17+
}

src/EfCore.Ydb/src/Storage/Internal/YdbRelationalConnection.cs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,38 @@
11
using System.Data.Common;
2+
using System.Security.Cryptography.X509Certificates;
23
using EfCore.Ydb.Extensions;
4+
using EfCore.Ydb.Infrastructure.Internal;
35
using Microsoft.EntityFrameworkCore;
46
using Microsoft.EntityFrameworkCore.Storage;
57
using Ydb.Sdk.Ado;
8+
using Ydb.Sdk.Auth;
69

710
namespace EfCore.Ydb.Storage.Internal;
811

9-
public class YdbRelationalConnection(RelationalConnectionDependencies dependencies)
10-
: RelationalConnection(dependencies), IYdbRelationalConnection
12+
public class YdbRelationalConnection : RelationalConnection, IYdbRelationalConnection
1113
{
12-
protected override DbConnection CreateDbConnection() => new YdbConnection(GetValidatedConnectionString());
14+
private readonly ICredentialsProvider? _credentialsProvider;
15+
private readonly X509Certificate2Collection? _serverCertificates;
16+
17+
public YdbRelationalConnection(RelationalConnectionDependencies dependencies) : base(dependencies)
18+
{
19+
var ydbOptionsExtension = dependencies.ContextOptions.FindExtension<YdbOptionsExtension>() ??
20+
new YdbOptionsExtension();
21+
22+
_credentialsProvider = ydbOptionsExtension.CredentialsProvider;
23+
_serverCertificates = ydbOptionsExtension.ServerCertificates;
24+
}
25+
26+
protected override DbConnection CreateDbConnection()
27+
{
28+
var ydbConnectionStringBuilder = new YdbConnectionStringBuilder(GetValidatedConnectionString())
29+
{
30+
CredentialsProvider = _credentialsProvider,
31+
ServerCertificates = _serverCertificates
32+
};
33+
34+
return new YdbConnection(ydbConnectionStringBuilder);
35+
}
1336

1437
public IYdbRelationalConnection Clone()
1538
{

0 commit comments

Comments
 (0)