Skip to content

Commit 04c471f

Browse files
dev: YDB example EF (#292)
1 parent d3b004d commit 04c471f

File tree

15 files changed

+113
-51
lines changed

15 files changed

+113
-51
lines changed

.github/workflows/tests.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,11 @@ jobs:
166166
run: |
167167
cd ./examples/src/DapperExample
168168
dotnet run
169-
- name: YDB Topic example
169+
- name: Run YDB Topic example
170170
run: |
171171
cd ./examples/src/Topic
172172
dotnet run
173+
- name: Run EF example
174+
run: |
175+
cd ./examples/src/EF
176+
dotnet run

examples/src/EF/EF.csproj

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
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+
<RootNamespace>EfCore</RootNamespace>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<ProjectReference Include="..\..\..\src\EfCore.Ydb\src\EfCore.Ydb.csproj"/>
13+
</ItemGroup>
14+
15+
</Project>

examples/src/EF/Program.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using EfCore.Ydb.Extensions;
2+
using Microsoft.EntityFrameworkCore;
3+
4+
await using var db = new BloggingContext();
5+
6+
await db.Database.EnsureCreatedAsync();
7+
8+
Console.WriteLine("Inserting a new blog");
9+
db.Add(new Blog { Url = "http://blogs.msdn.com/adonet" });
10+
await db.SaveChangesAsync();
11+
12+
Console.WriteLine("Querying for a blog");
13+
var blog = await db.Blogs
14+
.OrderBy(b => b.BlogId)
15+
.FirstAsync();
16+
17+
Console.WriteLine("Updating the blog and adding a post");
18+
blog.Url = "https://devblogs.microsoft.com/dotnet";
19+
blog.Posts.Add(new Post { Title = "Hello World", Content = "I wrote an app using EF Core!" });
20+
await db.SaveChangesAsync();
21+
22+
Console.WriteLine("Delete the blog");
23+
db.Remove(blog);
24+
await db.SaveChangesAsync();
25+
26+
internal class BloggingContext : DbContext
27+
{
28+
public DbSet<Blog> Blogs { get; set; }
29+
public DbSet<Post> Posts { get; set; }
30+
31+
protected override void OnConfiguring(DbContextOptionsBuilder options)
32+
=> options.UseYdb("Host=localhost;Port=2136;Database=/local");
33+
}
34+
35+
internal class Blog
36+
{
37+
public int BlogId { get; init; }
38+
39+
public string Url { get; set; } = string.Empty;
40+
41+
// ReSharper disable once CollectionNeverQueried.Global
42+
public List<Post> Posts { get; init; } = [];
43+
}
44+
45+
internal class Post
46+
{
47+
public int PostId { get; init; }
48+
49+
public string Title { get; init; } = string.Empty;
50+
51+
public string Content { get; init; } = string.Empty;
52+
53+
public Blog Blog { get; init; } = null!;
54+
}

examples/src/YdbExamples.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YC", "YC\YC.csproj", "{753E
1717
EndProject
1818
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Topic", "Topic\Topic.csproj", "{0FB9A1C2-4B0C-4AE4-9FA2-E0ED37802A6E}"
1919
EndProject
20+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EF", "EF\EF.csproj", "{0CE9DF93-1411-4E73-BA88-A66018FAB948}"
21+
EndProject
2022
Global
2123
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2224
Debug|Any CPU = Debug|Any CPU
@@ -51,6 +53,10 @@ Global
5153
{0FB9A1C2-4B0C-4AE4-9FA2-E0ED37802A6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
5254
{0FB9A1C2-4B0C-4AE4-9FA2-E0ED37802A6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
5355
{0FB9A1C2-4B0C-4AE4-9FA2-E0ED37802A6E}.Release|Any CPU.Build.0 = Release|Any CPU
56+
{0CE9DF93-1411-4E73-BA88-A66018FAB948}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
57+
{0CE9DF93-1411-4E73-BA88-A66018FAB948}.Debug|Any CPU.Build.0 = Debug|Any CPU
58+
{0CE9DF93-1411-4E73-BA88-A66018FAB948}.Release|Any CPU.ActiveCfg = Release|Any CPU
59+
{0CE9DF93-1411-4E73-BA88-A66018FAB948}.Release|Any CPU.Build.0 = Release|Any CPU
5460
EndGlobalSection
5561
GlobalSection(SolutionProperties) = preSolution
5662
HideSolutionNode = FALSE

src/EfCore.Ydb/src/Extensions/YdbContextOptionsBuilderExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace EfCore.Ydb.Extensions;
99

1010
public static class YdbContextOptionsBuilderExtensions
1111
{
12-
public static DbContextOptionsBuilder UseEfYdb(
12+
public static DbContextOptionsBuilder UseYdb(
1313
this DbContextOptionsBuilder optionsBuilder,
1414
string? connectionString,
1515
Action<YdbDbContextOptionsBuilder>? efYdbOptionsAction = null
@@ -24,7 +24,7 @@ public static DbContextOptionsBuilder UseEfYdb(
2424
return optionsBuilder;
2525
}
2626

27-
public static DbContextOptionsBuilder UseEfYdb(
27+
public static DbContextOptionsBuilder UseYdb(
2828
this DbContextOptionsBuilder optionsBuilder,
2929
DbConnection connection,
3030
Action<YdbDbContextOptionsBuilder>? efYdbOptionsAction = null

src/EfCore.Ydb/src/Infrastructure/EntityFrameworkYdbServicesBuilder.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ private static readonly IDictionary<Type, ServiceCharacteristics> YdbServices
2020
protected override ServiceCharacteristics GetServiceCharacteristics(Type serviceType)
2121
{
2222
var contains = YdbServices.TryGetValue(serviceType, out var characteristics);
23-
return contains
24-
? characteristics
25-
: base.GetServiceCharacteristics(serviceType);
23+
return contains ? characteristics : base.GetServiceCharacteristics(serviceType);
2624
}
2725
}

src/EfCore.Ydb/src/Infrastructure/Internal/YdbModelValidator.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace EfCore.Ydb.Infrastructure.Internal;
44

5-
// TODO: Not required for mvp
65
public class YdbModelValidator(
76
ModelValidatorDependencies dependencies,
87
RelationalModelValidatorDependencies relationalDependencies

src/EfCore.Ydb/src/Infrastructure/Internal/YdbOptionsExtension.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public YdbOptionsExtension()
1313
{
1414
}
1515

16-
protected YdbOptionsExtension(YdbOptionsExtension copyFrom) : base(copyFrom)
16+
private YdbOptionsExtension(YdbOptionsExtension copyFrom) : base(copyFrom)
1717
{
1818
}
1919

src/EfCore.Ydb/src/Query/Internal/YdbQuerySqlGenerator.cs

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System.Collections.Generic;
22
using System.Diagnostics;
3-
using System.Diagnostics.CodeAnalysis;
43
using System.Linq;
54
using System.Linq.Expressions;
65
using Microsoft.EntityFrameworkCore.Query;
@@ -9,29 +8,16 @@
98

109
namespace EfCore.Ydb.Query.Internal;
1110

12-
public class YdbQuerySqlGenerator : QuerySqlGenerator
11+
public class YdbQuerySqlGenerator(QuerySqlGeneratorDependencies dependencies) : QuerySqlGenerator(dependencies)
1312
{
14-
protected readonly ISqlGenerationHelper SqlGenerationHelper;
15-
protected readonly IRelationalTypeMappingSource TypeMappingSource;
16-
protected bool SkipAliases;
17-
18-
public YdbQuerySqlGenerator(
19-
QuerySqlGeneratorDependencies dependencies,
20-
IRelationalTypeMappingSource typeMappingSource
21-
) : base(dependencies)
22-
{
23-
SqlGenerationHelper = dependencies.SqlGenerationHelper;
24-
TypeMappingSource = typeMappingSource;
25-
}
26-
27-
[return: NotNullIfNotNull("node")]
28-
public override Expression? Visit(Expression? node) => node != null ? base.Visit(node) : null;
13+
private bool SkipAliases { get; set; }
14+
private ISqlGenerationHelper SqlGenerationHelper => Dependencies.SqlGenerationHelper;
2915

3016
protected override Expression VisitColumn(ColumnExpression columnExpression)
3117
{
3218
if (SkipAliases)
3319
{
34-
Sql.Append(SqlGenerationHelper.DelimitIdentifier(columnExpression.Name));
20+
Sql.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(columnExpression.Name));
3521
}
3622
else
3723
{
@@ -139,17 +125,17 @@ private void GenerateUpdateColumnSetters(UpdateExpression updateExpression)
139125
{
140126
foreach (var columnValueSetter in updateExpression.ColumnValueSetters.Skip(1))
141127
{
142-
Sql
143-
.AppendLine(",")
144-
.Append($"{SqlGenerationHelper.DelimitIdentifier(columnValueSetter.Column.Name)} = ");
128+
Sql.AppendLine(",")
129+
.Append(SqlGenerationHelper.DelimitIdentifier(columnValueSetter.Column.Name))
130+
.Append(" = ");
145131
SkipAliases = true;
146132
Visit(columnValueSetter.Value);
147133
SkipAliases = false;
148134
}
149135
}
150136
}
151137

152-
protected void GenerateOnSubquery(
138+
private void GenerateOnSubquery(
153139
IReadOnlyList<ColumnValueSetter>? columnValueSetters,
154140
SelectExpression select
155141
)
@@ -196,9 +182,13 @@ SelectExpression select
196182
}
197183
}
198184

185+
/// <inheritdoc />
199186
protected override void GenerateLimitOffset(SelectExpression selectExpression)
200187
{
201-
if (selectExpression.Limit == null && selectExpression.Offset == null) return;
188+
if (selectExpression.Limit == null && selectExpression.Offset == null)
189+
{
190+
return;
191+
}
202192

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

204+
// ReSharper disable once InvertIf
214205
if (selectExpression.Offset != null)
215206
{
216207
Sql.Append(" OFFSET ");
217208
Visit(selectExpression.Offset);
218209
}
219210
}
220211

221-
private bool IsComplexSelect(SelectExpression select, TableExpressionBase fromTable) =>
212+
private static bool IsComplexSelect(SelectExpression select, TableExpressionBase fromTable) =>
222213
select.Offset != null
223214
|| select.Limit != null
224215
|| select.Having != null
Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
using Microsoft.EntityFrameworkCore.Query;
2-
using Microsoft.EntityFrameworkCore.Storage;
32

43
namespace EfCore.Ydb.Query.Internal;
54

6-
public class YdbQuerySqlGeneratorFactory(
7-
QuerySqlGeneratorDependencies dependencies,
8-
IRelationalTypeMappingSource typeMappingSource
9-
) : IQuerySqlGeneratorFactory
5+
public class YdbQuerySqlGeneratorFactory(QuerySqlGeneratorDependencies dependencies) : IQuerySqlGeneratorFactory
106
{
11-
public QuerySqlGenerator Create() => new YdbQuerySqlGenerator(dependencies, typeMappingSource);
7+
public QuerySqlGenerator Create() => new YdbQuerySqlGenerator(dependencies);
128
}

0 commit comments

Comments
 (0)