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
6 changes: 5 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,11 @@ jobs:
run: |
cd ./examples/src/DapperExample
dotnet run
- name: YDB Topic example
- name: Run YDB Topic example
run: |
cd ./examples/src/Topic
dotnet run
- name: Run EF example
run: |
cd ./examples/src/EF
dotnet run
15 changes: 15 additions & 0 deletions examples/src/EF/EF.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

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

<ItemGroup>
<ProjectReference Include="..\..\..\src\EfCore.Ydb\src\EfCore.Ydb.csproj"/>
</ItemGroup>

</Project>
54 changes: 54 additions & 0 deletions examples/src/EF/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using EfCore.Ydb.Extensions;
using Microsoft.EntityFrameworkCore;

await using var db = new BloggingContext();

await db.Database.EnsureCreatedAsync();

Console.WriteLine("Inserting a new blog");
db.Add(new Blog { Url = "http://blogs.msdn.com/adonet" });
await db.SaveChangesAsync();

Console.WriteLine("Querying for a blog");
var blog = await db.Blogs
.OrderBy(b => b.BlogId)
.FirstAsync();

Console.WriteLine("Updating the blog and adding a post");
blog.Url = "https://devblogs.microsoft.com/dotnet";
blog.Posts.Add(new Post { Title = "Hello World", Content = "I wrote an app using EF Core!" });
await db.SaveChangesAsync();

Console.WriteLine("Delete the blog");
db.Remove(blog);
await db.SaveChangesAsync();

internal class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }

protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseYdb("Host=localhost;Port=2136;Database=/local");
}

internal class Blog
{
public int BlogId { get; init; }

public string Url { get; set; } = string.Empty;

// ReSharper disable once CollectionNeverQueried.Global
public List<Post> Posts { get; init; } = [];
}

internal class Post
{
public int PostId { get; init; }

public string Title { get; init; } = string.Empty;

public string Content { get; init; } = string.Empty;

public Blog Blog { get; init; } = null!;
}
6 changes: 6 additions & 0 deletions examples/src/YdbExamples.sln
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YC", "YC\YC.csproj", "{753E
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Topic", "Topic\Topic.csproj", "{0FB9A1C2-4B0C-4AE4-9FA2-E0ED37802A6E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EF", "EF\EF.csproj", "{0CE9DF93-1411-4E73-BA88-A66018FAB948}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -51,6 +53,10 @@ Global
{0FB9A1C2-4B0C-4AE4-9FA2-E0ED37802A6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0FB9A1C2-4B0C-4AE4-9FA2-E0ED37802A6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0FB9A1C2-4B0C-4AE4-9FA2-E0ED37802A6E}.Release|Any CPU.Build.0 = Release|Any CPU
{0CE9DF93-1411-4E73-BA88-A66018FAB948}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace EfCore.Ydb.Extensions;

public static class YdbContextOptionsBuilderExtensions
{
public static DbContextOptionsBuilder UseEfYdb(
public static DbContextOptionsBuilder UseYdb(
this DbContextOptionsBuilder optionsBuilder,
string? connectionString,
Action<YdbDbContextOptionsBuilder>? efYdbOptionsAction = null
Expand All @@ -24,7 +24,7 @@ public static DbContextOptionsBuilder UseEfYdb(
return optionsBuilder;
}

public static DbContextOptionsBuilder UseEfYdb(
public static DbContextOptionsBuilder UseYdb(
this DbContextOptionsBuilder optionsBuilder,
DbConnection connection,
Action<YdbDbContextOptionsBuilder>? efYdbOptionsAction = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ private static readonly IDictionary<Type, ServiceCharacteristics> YdbServices
protected override ServiceCharacteristics GetServiceCharacteristics(Type serviceType)
{
var contains = YdbServices.TryGetValue(serviceType, out var characteristics);
return contains
? characteristics
: base.GetServiceCharacteristics(serviceType);
return contains ? characteristics : base.GetServiceCharacteristics(serviceType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace EfCore.Ydb.Infrastructure.Internal;

// TODO: Not required for mvp
public class YdbModelValidator(
ModelValidatorDependencies dependencies,
RelationalModelValidatorDependencies relationalDependencies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public YdbOptionsExtension()
{
}

protected YdbOptionsExtension(YdbOptionsExtension copyFrom) : base(copyFrom)
private YdbOptionsExtension(YdbOptionsExtension copyFrom) : base(copyFrom)
{
}

Expand Down
39 changes: 15 additions & 24 deletions src/EfCore.Ydb/src/Query/Internal/YdbQuerySqlGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore.Query;
Expand All @@ -9,29 +8,16 @@

namespace EfCore.Ydb.Query.Internal;

public class YdbQuerySqlGenerator : QuerySqlGenerator
public class YdbQuerySqlGenerator(QuerySqlGeneratorDependencies dependencies) : QuerySqlGenerator(dependencies)
{
protected readonly ISqlGenerationHelper SqlGenerationHelper;
protected readonly IRelationalTypeMappingSource TypeMappingSource;
protected bool SkipAliases;

public YdbQuerySqlGenerator(
QuerySqlGeneratorDependencies dependencies,
IRelationalTypeMappingSource typeMappingSource
) : base(dependencies)
{
SqlGenerationHelper = dependencies.SqlGenerationHelper;
TypeMappingSource = typeMappingSource;
}

[return: NotNullIfNotNull("node")]
public override Expression? Visit(Expression? node) => node != null ? base.Visit(node) : null;
private bool SkipAliases { get; set; }
private ISqlGenerationHelper SqlGenerationHelper => Dependencies.SqlGenerationHelper;

protected override Expression VisitColumn(ColumnExpression columnExpression)
{
if (SkipAliases)
{
Sql.Append(SqlGenerationHelper.DelimitIdentifier(columnExpression.Name));
Sql.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(columnExpression.Name));
}
else
{
Expand Down Expand Up @@ -139,17 +125,17 @@ private void GenerateUpdateColumnSetters(UpdateExpression updateExpression)
{
foreach (var columnValueSetter in updateExpression.ColumnValueSetters.Skip(1))
{
Sql
.AppendLine(",")
.Append($"{SqlGenerationHelper.DelimitIdentifier(columnValueSetter.Column.Name)} = ");
Sql.AppendLine(",")
.Append(SqlGenerationHelper.DelimitIdentifier(columnValueSetter.Column.Name))
.Append(" = ");
SkipAliases = true;
Visit(columnValueSetter.Value);
SkipAliases = false;
}
}
}

protected void GenerateOnSubquery(
private void GenerateOnSubquery(
IReadOnlyList<ColumnValueSetter>? columnValueSetters,
SelectExpression select
)
Expand Down Expand Up @@ -196,9 +182,13 @@ SelectExpression select
}
}

/// <inheritdoc />
protected override void GenerateLimitOffset(SelectExpression selectExpression)
{
if (selectExpression.Limit == null && selectExpression.Offset == null) return;
if (selectExpression.Limit == null && selectExpression.Offset == null)
{
return;
}

Sql.AppendLine().Append("LIMIT ");
if (selectExpression.Limit != null)
Expand All @@ -211,14 +201,15 @@ protected override void GenerateLimitOffset(SelectExpression selectExpression)
Sql.Append(ulong.MaxValue.ToString());
}

// ReSharper disable once InvertIf
if (selectExpression.Offset != null)
{
Sql.Append(" OFFSET ");
Visit(selectExpression.Offset);
}
}

private bool IsComplexSelect(SelectExpression select, TableExpressionBase fromTable) =>
private static bool IsComplexSelect(SelectExpression select, TableExpressionBase fromTable) =>
select.Offset != null
|| select.Limit != null
|| select.Having != null
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Storage;

namespace EfCore.Ydb.Query.Internal;

public class YdbQuerySqlGeneratorFactory(
QuerySqlGeneratorDependencies dependencies,
IRelationalTypeMappingSource typeMappingSource
) : IQuerySqlGeneratorFactory
public class YdbQuerySqlGeneratorFactory(QuerySqlGeneratorDependencies dependencies) : IQuerySqlGeneratorFactory
{
public QuerySqlGenerator Create() => new YdbQuerySqlGenerator(dependencies, typeMappingSource);
public QuerySqlGenerator Create() => new YdbQuerySqlGenerator(dependencies);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

namespace EfCore.Ydb.Query.Internal;

public class YdbQueryTranslationPostprocessorFactory(
public sealed class YdbQueryTranslationPostprocessorFactory(
QueryTranslationPostprocessorDependencies dependencies,
RelationalQueryTranslationPostprocessorDependencies relationalDependencies
) : IQueryTranslationPostprocessorFactory
{
public virtual QueryTranslationPostprocessor Create(QueryCompilationContext queryCompilationContext)
public QueryTranslationPostprocessor Create(QueryCompilationContext queryCompilationContext)
=> new YdbQueryTranslationPostprocessor(
dependencies,
relationalDependencies,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class YdbRelationalConnection(RelationalConnectionDependencies dependenci
public IYdbRelationalConnection Clone()
{
var connectionStringBuilder = new YdbConnectionStringBuilder(GetValidatedConnectionString());
var options = new DbContextOptionsBuilder().UseEfYdb(connectionStringBuilder.ToString()).Options;
var options = new DbContextOptionsBuilder().UseYdb(connectionStringBuilder.ToString()).Options;
return new YdbRelationalConnection(Dependencies with { ContextOptions = options });
}
}
8 changes: 4 additions & 4 deletions src/EfCore.Ydb/src/Storage/Internal/YdbTypeMappingSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@

namespace EfCore.Ydb.Storage.Internal;

public class YdbTypeMappingSource : RelationalTypeMappingSource
public sealed class YdbTypeMappingSource : RelationalTypeMappingSource
{
protected virtual ConcurrentDictionary<string, RelationalTypeMapping[]> StoreTypeMapping { get; }
protected virtual ConcurrentDictionary<Type, RelationalTypeMapping> ClrTypeMapping { get; }
private ConcurrentDictionary<string, RelationalTypeMapping[]> StoreTypeMapping { get; }
private ConcurrentDictionary<Type, RelationalTypeMapping> ClrTypeMapping { get; }

#region Mappings

Expand Down Expand Up @@ -118,7 +118,7 @@ RelationalTypeMappingSourceDependencies relationalDependencies
=> FindBaseMapping(mappingInfo)
?? base.FindMapping(mappingInfo);

protected virtual RelationalTypeMapping? FindBaseMapping(in RelationalTypeMappingInfo mappingInfo)
private RelationalTypeMapping? FindBaseMapping(in RelationalTypeMappingInfo mappingInfo)
{
var clrType = mappingInfo.ClrType;
var storeTypeName = mappingInfo.StoreTypeName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace EfCore.Ydb.FunctionalTests.AllTests.Update;
// Ignore_before_save_property_is_still_generated,
// SaveChanges_processes_all_tracked_entities.
// They're failing, but I cannot ignore them because they're not virtual
internal class UpdatesYdbTest
public class UpdatesYdbTest
: UpdatesRelationalTestBase<UpdatesYdbTest.UpdatesYdbFixture>
// , UpdatesTestBase<UpdatesYdbTest.UpdatesYdbFixture>
{
Expand All @@ -24,8 +24,7 @@ public UpdatesYdbTest(UpdatesYdbFixture fixture) : base(fixture)

public class UpdatesYdbFixture : UpdatesRelationalFixture
{
protected override ITestStoreFactory TestStoreFactory
=> YdbTestStoreFactory.Instance;
protected override ITestStoreFactory TestStoreFactory => YdbTestStoreFactory.Instance;
}

public override void Identifiers_are_generated_correctly()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ public static YdbTestStore GetOrCreate(
) => new(name: name, scriptPath: scriptPath);

public override DbContextOptionsBuilder AddProviderOptions(DbContextOptionsBuilder builder) => UseConnectionString
? builder.UseEfYdb(Connection.ConnectionString)
: builder.UseEfYdb(Connection);
? builder.UseYdb(Connection.ConnectionString)
: builder.UseYdb(Connection);

protected override async Task InitializeAsync(
Func<DbContext> createContext,
Expand Down Expand Up @@ -163,7 +163,7 @@ private static YdbCommand CreateCommand(
}


private static YdbConnection CreateConnection() => new();
private static YdbConnection CreateConnection() => new(new YdbConnectionStringBuilder());

public override async Task CleanAsync(DbContext context)
{
Expand Down
Loading