Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions examples/src/EF_YC/CmdOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using CommandLine;

namespace EF_YC;

internal class CmdOptions
{
[Option('c', "connectionString", Required = true, HelpText = "Connection string")]
public string ConnectionString { get; set; } = null!;

[Option("saFilePath", Required = true, HelpText = "Sa Key")]
public string SaFilePath { get; set; } = null!;
}
21 changes: 21 additions & 0 deletions examples/src/EF_YC/EF_YC.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.8.0"/>
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.0"/>
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0"/>
<PackageReference Include="Ydb.Sdk.Yc.Auth" Version="0.2.0"/>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\src\EfCore.Ydb\src\EfCore.Ydb.csproj"/>
<ProjectReference Include="..\..\..\src\Ydb.Sdk\src\Ydb.Sdk.csproj"/>
</ItemGroup>
</Project>
52 changes: 52 additions & 0 deletions examples/src/EF_YC/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using CommandLine;
using EF_YC;
using EfCore.Ydb.Extensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Ydb.Sdk.Yc;

await Parser.Default.ParseArguments<CmdOptions>(args).WithParsedAsync(async cmd =>
{
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Information));
var saProvider = new ServiceAccountProvider(saFilePath: cmd.SaFilePath, loggerFactory: loggerFactory);

var options = new DbContextOptionsBuilder<AppDbContext>()
.UseYdb(cmd.ConnectionString, builder =>
{
builder.WithCredentialsProvider(saProvider);
builder.WithServerCertificates(YcCerts.GetYcServerCertificates());
})
.Options;

await using var db = new AppDbContext(options);
db.Database.EnsureCreated();

db.Users.Add(new User { Name = "Alex", Email = "[email protected]" });
db.Users.Add(new User { Name = "Kirill", Email = "[email protected]" });
db.SaveChanges();

var users = db.Users.OrderBy(u => u.Id).ToList();
Console.WriteLine("Users in database:");
foreach (var user in users)
{
Console.WriteLine($"- {user.Id}: {user.Name} ({user.Email})");
}

// Users in database:
// - 1: Alex ([email protected])
// - 2: Kirill ([email protected])
});


internal class User
{
public int Id { get; init; }
public string Name { get; init; } = string.Empty;
public string Email { get; init; } = string.Empty;
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
}

internal class AppDbContext(DbContextOptions options) : DbContext(options)
{
public DbSet<User> Users { get; set; }
}
1 change: 0 additions & 1 deletion examples/src/YC/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ await Parser.Default.ParseArguments<CmdOptions>(args).WithParsedAsync(async cmd
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Information));

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

var builder = new YdbConnectionStringBuilder
{
Expand Down
2 changes: 1 addition & 1 deletion examples/src/YC/YC.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
<PackageReference Include="Ydb.Protos" Version="1.1.1" />
<PackageReference Include="Ydb.Sdk.Yc.Auth" Version="0.1.0" />
<PackageReference Include="Ydb.Sdk.Yc.Auth" Version="0.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Ydb.Sdk\src\Ydb.Sdk.csproj" />
Expand Down
6 changes: 6 additions & 0 deletions examples/src/YdbExamples.sln
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Topic", "Topic\Topic.csproj
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EF", "EF\EF.csproj", "{0CE9DF93-1411-4E73-BA88-A66018FAB948}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EF_YC", "EF_YC\EF_YC.csproj", "{31A2E7BF-45BB-4C63-9DEC-58DD06491EF1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -57,6 +59,10 @@ Global
{0CE9DF93-1411-4E73-BA88-A66018FAB948}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0CE9DF93-1411-4E73-BA88-A66018FAB948}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0CE9DF93-1411-4E73-BA88-A66018FAB948}.Release|Any CPU.Build.0 = Release|Any CPU
{31A2E7BF-45BB-4C63-9DEC-58DD06491EF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{31A2E7BF-45BB-4C63-9DEC-58DD06491EF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{31A2E7BF-45BB-4C63-9DEC-58DD06491EF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{31A2E7BF-45BB-4C63-9DEC-58DD06491EF1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
1 change: 1 addition & 0 deletions src/EfCore.Ydb/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Supported connect to Yandex Cloud
42 changes: 33 additions & 9 deletions src/EfCore.Ydb/src/Infrastructure/Internal/YdbOptionsExtension.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using EfCore.Ydb.Extensions;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
using Ydb.Sdk.Auth;

namespace EfCore.Ydb.Infrastructure.Internal;

public class YdbOptionsExtension : RelationalOptionsExtension
{
public ICredentialsProvider? CredentialsProvider { get; private set; }

public X509Certificate2Collection? ServerCertificates { get; private set; }

private DbContextOptionsExtensionInfo? _info;

public YdbOptionsExtension()
Expand All @@ -15,22 +21,40 @@ public YdbOptionsExtension()

private YdbOptionsExtension(YdbOptionsExtension copyFrom) : base(copyFrom)
{
CredentialsProvider = copyFrom.CredentialsProvider;
ServerCertificates = copyFrom.ServerCertificates;
}

protected override RelationalOptionsExtension Clone() => new YdbOptionsExtension(this);

public override void ApplyServices(IServiceCollection services) => services.AddEntityFrameworkYdb();

public override DbContextOptionsExtensionInfo Info => _info ??= new ExtensionInfo(this);

public YdbOptionsExtension WithCredentialsProvider(ICredentialsProvider? credentialsProvider)
{
var clone = (YdbOptionsExtension)Clone();

clone.CredentialsProvider = credentialsProvider;

return clone;
}

protected override RelationalOptionsExtension Clone()
=> new YdbOptionsExtension(this);
public YdbOptionsExtension WithServerCertificates(X509Certificate2Collection? serverCertificates)
{
var clone = (YdbOptionsExtension)Clone();

public override void ApplyServices(IServiceCollection services)
=> services.AddEntityFrameworkYdb();
clone.ServerCertificates = serverCertificates;

public override DbContextOptionsExtensionInfo Info
=> _info ??= new ExtensionInfo(this);
return clone;
}

private sealed class ExtensionInfo(IDbContextOptionsExtension extension) : RelationalExtensionInfo(extension)
private sealed class ExtensionInfo(YdbOptionsExtension extension) : RelationalExtensionInfo(extension)
{
public override bool IsDatabaseProvider => true;

// TODO: Right now it's stub
public override void PopulateDebugInfo(IDictionary<string, string> debugInfo) => debugInfo["Hello"] = "World!";
public override void PopulateDebugInfo(IDictionary<string, string> debugInfo)
{
}
}
}
11 changes: 10 additions & 1 deletion src/EfCore.Ydb/src/Infrastructure/YdbDbContextOptionsBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
using System.Security.Cryptography.X509Certificates;
using EfCore.Ydb.Infrastructure.Internal;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Ydb.Sdk.Auth;

namespace EfCore.Ydb.Infrastructure;

public class YdbDbContextOptionsBuilder(DbContextOptionsBuilder optionsBuilder)
: RelationalDbContextOptionsBuilder<YdbDbContextOptionsBuilder, YdbOptionsExtension>(optionsBuilder);
: RelationalDbContextOptionsBuilder<YdbDbContextOptionsBuilder, YdbOptionsExtension>(optionsBuilder)
{
public YdbDbContextOptionsBuilder WithCredentialsProvider(ICredentialsProvider? credentialsProvider) =>
WithOption(optionsBuilder => optionsBuilder.WithCredentialsProvider(credentialsProvider));

public YdbDbContextOptionsBuilder WithServerCertificates(X509Certificate2Collection? serverCertificates) =>
WithOption(optionsBuilder => optionsBuilder.WithServerCertificates(serverCertificates));
}
29 changes: 26 additions & 3 deletions src/EfCore.Ydb/src/Storage/Internal/YdbRelationalConnection.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,38 @@
using System.Data.Common;
using System.Security.Cryptography.X509Certificates;
using EfCore.Ydb.Extensions;
using EfCore.Ydb.Infrastructure.Internal;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Ydb.Sdk.Ado;
using Ydb.Sdk.Auth;

namespace EfCore.Ydb.Storage.Internal;

public class YdbRelationalConnection(RelationalConnectionDependencies dependencies)
: RelationalConnection(dependencies), IYdbRelationalConnection
public class YdbRelationalConnection : RelationalConnection, IYdbRelationalConnection
{
protected override DbConnection CreateDbConnection() => new YdbConnection(GetValidatedConnectionString());
private readonly ICredentialsProvider? _credentialsProvider;
private readonly X509Certificate2Collection? _serverCertificates;

public YdbRelationalConnection(RelationalConnectionDependencies dependencies) : base(dependencies)
{
var ydbOptionsExtension = dependencies.ContextOptions.FindExtension<YdbOptionsExtension>() ??
new YdbOptionsExtension();

_credentialsProvider = ydbOptionsExtension.CredentialsProvider;
_serverCertificates = ydbOptionsExtension.ServerCertificates;
}

protected override DbConnection CreateDbConnection()
{
var ydbConnectionStringBuilder = new YdbConnectionStringBuilder(GetValidatedConnectionString())
{
CredentialsProvider = _credentialsProvider,
ServerCertificates = _serverCertificates
};

return new YdbConnection(ydbConnectionStringBuilder);
}

public IYdbRelationalConnection Clone()
{
Expand Down
3 changes: 3 additions & 0 deletions src/YdbSdk.sln
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Ydb.Sdk\tests\Tests.csproj", "{A27FD249-6ACB-4392-B00F-CD08FB727C98}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EfCore.Ydb", "EfCore.Ydb", "{5E7B167B-5FC7-41BD-8819-16B02ED9B961}"
ProjectSection(SolutionItems) = preProject
EfCore.Ydb\CHANGELOG.md = EfCore.Ydb\CHANGELOG.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4A4EE5F3-CC9C-4166-A8F5-3ACFDD2A75F3}"
EndProject
Expand Down
Loading