diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 210b8249..637eeeb7 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -11,14 +11,14 @@ jobs:
strategy:
fail-fast: false
matrix:
- source-dir: ["./src/", "./examples/src/", "./slo/src/"]
+ source-dir: ["./src/", "./examples/", "./slo/src/"]
include:
- source-dir: "./src/"
solutionFile: "YdbSdk.sln"
- - source-dir: "./examples/src/"
+ - source-dir: "./examples/"
solutionFile: "YdbExamples.sln"
- source-dir: "./slo/src/"
- solutionFile: "src.sln"
+ solutionFile: "src.sln"
name: autoformat check
runs-on: ubuntu-latest
steps:
@@ -41,7 +41,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- solutionPath: ["./src/YdbSdk.sln", "./examples/src/YdbExamples.sln", "./slo/src/src.sln"]
+ solutionPath: ["./src/YdbSdk.sln", "./examples/YdbExamples.sln", "./slo/src/src.sln"]
runs-on: ubuntu-latest
name: Inspection
steps:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index b71f4a75..e0e437c0 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -182,24 +182,32 @@ jobs:
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ matrix.dotnet-version }}
- - name: Run ADO.NET example
+ - name: Run Ydb.Sdk.AdoNet.QuickStart
run: |
docker cp ydb-local:/ydb_certs/ca.pem ~/
- cd ./examples/src/AdoNet
+ cd ./examples/Ydb.Sdk.AdoNet.QuickStart
dotnet run
- - name: Run Dapper example
+ - name: Run Ydb.Sdk.AdoNet.Dapper.QuickStart
run: |
- cd ./examples/src/DapperExample
+ cd ./examples/Ydb.Sdk.AdoNet.Dapper.QuickStart
dotnet run
- - name: Run YDB Topic example
+ - name: Run Ydb.Sdk.Topic.QuickStart
run: |
- cd ./examples/src/Topic
+ cd ./examples/Ydb.Sdk.Topic.QuickStart
dotnet run
- - name: Run Entity Framework Core example
+ - name: Run EntityFrameworkCore.Ydb.QuickStart
run: |
- cd ./examples/src/EntityFrameworkCore.Ydb.QuickStart
+ cd ./examples/EntityFrameworkCore.Ydb.QuickStart
dotnet tool install --global dotnet-ef
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet ef migrations add InitialCreate
dotnet ef database update
dotnet run
+ - name: Run EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial
+ run: |
+ cd ./examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial
+ dotnet tool install --global dotnet-ef
+ dotnet add package Microsoft.EntityFrameworkCore.Design
+ dotnet ef migrations add InitialCreate
+ dotnet ef database update
+ dotnet run
\ No newline at end of file
diff --git a/examples/src/EntityFrameworkCore.Ydb.QuickStart/EntityFrameworkCore.Ydb.QuickStart.csproj b/examples/EntityFrameworkCore.Ydb.QuickStart/EntityFrameworkCore.Ydb.QuickStart.csproj
similarity index 77%
rename from examples/src/EntityFrameworkCore.Ydb.QuickStart/EntityFrameworkCore.Ydb.QuickStart.csproj
rename to examples/EntityFrameworkCore.Ydb.QuickStart/EntityFrameworkCore.Ydb.QuickStart.csproj
index b20b9a8f..0622e0c7 100644
--- a/examples/src/EntityFrameworkCore.Ydb.QuickStart/EntityFrameworkCore.Ydb.QuickStart.csproj
+++ b/examples/EntityFrameworkCore.Ydb.QuickStart/EntityFrameworkCore.Ydb.QuickStart.csproj
@@ -5,11 +5,11 @@
net8.0
enable
enable
- EntityFrameworkCore.Ydb
+ EntityFrameworkCore.Ydb.QuickStart
-
+
diff --git a/examples/src/EntityFrameworkCore.Ydb.QuickStart/Program.cs b/examples/EntityFrameworkCore.Ydb.QuickStart/Program.cs
similarity index 100%
rename from examples/src/EntityFrameworkCore.Ydb.QuickStart/Program.cs
rename to examples/EntityFrameworkCore.Ydb.QuickStart/Program.cs
diff --git a/examples/src/EntityFrameworkCore.Ydb.QuickStart/README.md b/examples/EntityFrameworkCore.Ydb.QuickStart/README.md
similarity index 76%
rename from examples/src/EntityFrameworkCore.Ydb.QuickStart/README.md
rename to examples/EntityFrameworkCore.Ydb.QuickStart/README.md
index 0d72ab69..86b56ec9 100644
--- a/examples/src/EntityFrameworkCore.Ydb.QuickStart/README.md
+++ b/examples/EntityFrameworkCore.Ydb.QuickStart/README.md
@@ -1,11 +1,13 @@
# Entity Framework Core YDB Quick Start
-A sample application from the [official documentation](https://learn.microsoft.com/en-us/ef/core/get-started/overview/first-app?tabs=netcore-cli)
+A sample application from
+the [official documentation](https://learn.microsoft.com/en-us/ef/core/get-started/overview/first-app?tabs=netcore-cli)
shows how to get started with EF, define a model, populate it with data and then query the database.
## Running QuickStart
1. Setup [YDB local](https://ydb.tech/docs/en/reference/docker/start).
+
2. Create the database:
```bash
dotnet tool install --global dotnet-ef
@@ -13,4 +15,5 @@ shows how to get started with EF, define a model, populate it with data and then
dotnet ef migrations add InitialCreate
dotnet ef database update
```
+
3. Run the app: `dotnet run`
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/AddEntity.Sample/AddEntity.Sample.csproj b/examples/EntityFrameworkCore.Ydb.Samples/AddEntity.Sample/AddEntity.Sample.csproj
new file mode 100644
index 00000000..5b482857
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/AddEntity.Sample/AddEntity.Sample.csproj
@@ -0,0 +1,21 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+ Section_1.HR
+
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/AddEntity.Sample/HRContext.cs b/examples/EntityFrameworkCore.Ydb.Samples/AddEntity.Sample/HRContext.cs
new file mode 100644
index 00000000..542a6ebf
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/AddEntity.Sample/HRContext.cs
@@ -0,0 +1,51 @@
+// using Microsoft.EntityFrameworkCore;
+
+using EntityFrameworkCore.Ydb.Extensions;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Design;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+using Microsoft.Extensions.Logging;
+
+namespace Section_1.HR;
+
+public class HRContext : DbContext
+{
+ public DbSet Employees { get; set; }
+ public DbSet Departments { get; set; }
+
+ public HRContext()
+ {
+ }
+
+ public HRContext(DbContextOptions options) : base(options)
+ {
+ }
+
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) =>
+ optionsBuilder
+ .UseYdb("Host=localhost;Port=2136;Database=/local")
+ .LogTo(Console.WriteLine, new[] { DbLoggerCategory.Database.Command.Name }, LogLevel.Information);
+}
+
+internal class HRContextContextFactory : IDesignTimeDbContextFactory
+{
+ public HRContext CreateDbContext(string[] args)
+ {
+ var optionsBuilder = new DbContextOptionsBuilder();
+
+ // IMPORTANT!
+ // Disables retries for the migrations context.
+ // Required because migration operations may use suppressed or explicit transactions,
+ // and enabling retries in this case leads to runtime errors with this provider.
+ //
+ // "System.NotSupportedException: User transaction is not supported with a TransactionSuppressed migrations or a retrying execution strategy."
+ //
+ // Bottom line: ALWAYS disable retries for design-time/migration contexts to avoid migration failures and errors.
+ return new HRContext(
+ optionsBuilder
+ .UseYdb("Host=localhost;Port=2136;Database=/local", builder => builder.DisableRetryOnFailure())
+ .ConfigureWarnings(warnings => warnings.Ignore(RelationalEventId.PendingModelChangesWarning))
+ .Options
+ );
+ }
+}
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/AddEntity.Sample/Models.cs b/examples/EntityFrameworkCore.Ydb.Samples/AddEntity.Sample/Models.cs
new file mode 100644
index 00000000..b3ae7e60
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/AddEntity.Sample/Models.cs
@@ -0,0 +1,17 @@
+namespace Section_1.HR;
+
+public class Department
+{
+ public int Id { get; set; }
+ public required string Name { get; set; }
+}
+
+public class Employee
+{
+ public int Id { get; set; }
+ public required string FirstName { get; set; }
+ public required string LastName { get; set; }
+ public required DateTime JoinedDate { get; set; }
+ public required decimal Salary { get; set; }
+ public Department? Department { get; set; }
+}
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/AddEntity.Sample/Program.cs b/examples/EntityFrameworkCore.Ydb.Samples/AddEntity.Sample/Program.cs
new file mode 100644
index 00000000..d820a45a
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/AddEntity.Sample/Program.cs
@@ -0,0 +1,39 @@
+// See https://aka.ms/new-console-template for more information
+
+using Section_1.HR;
+
+InsertDepartments();
+SelectDepartments();
+
+return;
+
+
+static void InsertDepartments()
+{
+ var departments = new List
+ {
+ new() { Name = "Sales" },
+ new() { Name = "Marketing" },
+ new() { Name = "Logistics" }
+ };
+
+ using var context = new HRContext();
+
+ foreach (var department in departments)
+ {
+ context.Departments.Add(department);
+ }
+
+ context.SaveChanges();
+}
+
+static void SelectDepartments()
+{
+ using var context = new HRContext();
+ var departments = context.Departments.ToList();
+
+ foreach (var department in departments)
+ {
+ Console.WriteLine($"{department.Id} - {department.Name}");
+ }
+}
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/AddEntity.Sample/README.md b/examples/EntityFrameworkCore.Ydb.Samples/AddEntity.Sample/README.md
new file mode 100644
index 00000000..4d600f18
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/AddEntity.Sample/README.md
@@ -0,0 +1,27 @@
+# Entity Framework Core YDB Add Entity Sample
+
+This sample introduces the basics of using EF Core with YDB.
+It covers what EF Core is, how to create a simple .NET app with EF Core, how to define a data model, set up a database connection, and perform basic CRUD operations via the EF Core API.
+
+Based on the [tutorial](https://www.csharptutorial.net/entity-framework-core-tutorial/getting-started-with-entity-framework-core/).
+
+## Running QuickStart
+
+1. Set up [YDB local](https://ydb.tech/docs/en/reference/docker/start).
+
+2. Install the EF Core CLI tool and dependencies (if needed):
+ ```bash
+ dotnet tool install --global dotnet-ef
+ dotnet add package Microsoft.EntityFrameworkCore.Design
+ ```
+
+3. Create the database and apply migrations:
+ ```bash
+ dotnet ef migrations add InitialCreate
+ dotnet ef database update
+ ```
+
+4. Run the sample:
+ ```bash
+ dotnet run
+ ```
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/Database.Operations.Tutorial.csproj b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/Database.Operations.Tutorial.csproj
new file mode 100644
index 00000000..e9e7ec20
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/Database.Operations.Tutorial.csproj
@@ -0,0 +1,22 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+ Database.Operations.Tutorial
+
+
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/Department.cs b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/Department.cs
new file mode 100644
index 00000000..6d7ec163
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/Department.cs
@@ -0,0 +1,7 @@
+namespace Database.Operations.Tutorial;
+
+public class Department
+{
+ public int Id { get; set; }
+ public required string Name { get; set; }
+}
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/Employee.cs b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/Employee.cs
new file mode 100644
index 00000000..aa36126d
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/Employee.cs
@@ -0,0 +1,22 @@
+namespace Database.Operations.Tutorial;
+
+public class Employee
+{
+ public int Id { get; set; }
+ public required string FirstName { get; set; }
+ public required string LastName { get; set; }
+ public required decimal Salary { get; set; }
+ public required DateTime JoinedDate { get; set; }
+
+ // Foreign key property to the Department
+ public int DepartmentId { get; set; }
+
+ // Reference navigation to Department
+ public Department Department { get; set; } = null!;
+
+ // Reference navigation to EmployeeProfile
+ public EmployeeProfile? Profile { get; set; }
+
+ // collection navigation to Employee
+ public List Skills { get; set; } = new();
+}
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/EmployeeProfile.cs b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/EmployeeProfile.cs
new file mode 100644
index 00000000..b1b5343b
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/EmployeeProfile.cs
@@ -0,0 +1,11 @@
+namespace Database.Operations.Tutorial;
+
+public class EmployeeProfile
+{
+ public int Id { get; set; }
+ public required string Phone { get; set; }
+ public required string Email { get; set; }
+
+ public int EmployeeId { get; set; }
+ public Employee Employee { get; set; } = null!;
+}
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/HRContext.cs b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/HRContext.cs
new file mode 100644
index 00000000..404e06e3
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/HRContext.cs
@@ -0,0 +1,38 @@
+using EntityFrameworkCore.Ydb.Extensions;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+
+namespace Database.Operations.Tutorial;
+
+public class HRContext : DbContext
+{
+ public DbSet Employees { get; set; }
+ public DbSet Departments { get; set; }
+ public DbSet EmployeeProfiles { get; set; }
+ public DbSet Skills { get; set; }
+
+ public HRContext()
+ {
+ }
+
+ public HRContext(DbContextOptions options) : base(options)
+ {
+ }
+
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ {
+ var configuration = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json")
+ .Build();
+
+ var connectionString = configuration.GetConnectionString("Local");
+
+ optionsBuilder.UseYdb(connectionString)
+ .LogTo(Console.WriteLine, new[] { DbLoggerCategory.Database.Command.Name }, LogLevel.Information)
+ .ConfigureWarnings(warnings => warnings.Ignore(RelationalEventId.PendingModelChangesWarning))
+ .EnableSensitiveDataLogging();
+ }
+}
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/HRContextFactory.cs b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/HRContextFactory.cs
new file mode 100644
index 00000000..aeebe2b5
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/HRContextFactory.cs
@@ -0,0 +1,38 @@
+using EntityFrameworkCore.Ydb.Extensions;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Design;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+using Microsoft.Extensions.Configuration;
+
+namespace Database.Operations.Tutorial;
+
+// ReSharper disable once UnusedType.Global
+internal class HRContextFactory : IDesignTimeDbContextFactory
+{
+ public HRContext CreateDbContext(string[] args)
+ {
+ var optionsBuilder = new DbContextOptionsBuilder();
+
+ var configuration = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json")
+ .Build();
+
+ var connectionString = configuration.GetConnectionString("Local");
+
+ // IMPORTANT!
+ // Disables retries for the migrations context.
+ // Required because migration operations may use suppressed or explicit transactions,
+ // and enabling retries in this case leads to runtime errors with this provider.
+ //
+ // "System.NotSupportedException: User transaction is not supported with a TransactionSuppressed migrations or a retrying execution strategy."
+ //
+ // Bottom line: ALWAYS disable retries for design-time/migration contexts to avoid migration failures and errors.
+ return new HRContext(
+ optionsBuilder
+ .UseYdb(connectionString, builder => builder.DisableRetryOnFailure())
+ .ConfigureWarnings(warnings => warnings.Ignore(RelationalEventId.PendingModelChangesWarning))
+ .Options
+ );
+ }
+}
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/Program.cs b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/Program.cs
new file mode 100644
index 00000000..2782d8c2
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/Program.cs
@@ -0,0 +1,538 @@
+using Database.Operations.Tutorial;
+using Microsoft.EntityFrameworkCore;
+
+var orderingActions = new List
+{
+ Action.ReadCsv,
+ Action.Select,
+ Action.OrderBy,
+ Action.QueryLinq,
+ Action.Where,
+ Action.InOperator,
+ Action.Like,
+ Action.InnerJoin,
+ Action.GroupBy
+};
+var actions = new Dictionary>
+{
+ { Action.ReadCsv, ReadCSV },
+ { Action.Select, Select },
+ { Action.OrderBy, OrderBy },
+ { Action.QueryLinq, QueryLinq },
+ { Action.Where, Where },
+ { Action.InOperator, InOperator },
+ { Action.Like, Like },
+ { Action.InnerJoin, InnerJoin },
+ { Action.GroupBy, GroupBy }
+};
+
+switch (args.Length)
+{
+ case > 0:
+ {
+ if (Enum.TryParse(args[0], true, out var result))
+ {
+ using var hrContext = new HRContext();
+ actions[result](hrContext);
+ break;
+ }
+
+ throw new InvalidOperationException("Not found argument: " + args[0]);
+ }
+ case 0:
+ {
+ foreach (var action in orderingActions)
+ {
+ using var context = new HRContext();
+ actions[action](context);
+ }
+
+ break;
+ }
+}
+
+return;
+
+static void GroupBy(HRContext context)
+{
+ {
+ var groups = context.Employees
+ .GroupBy(e => e.Department)
+ .Select(group => new
+ {
+ group.Key.Name,
+ Headcount = group.Count()
+ })
+ .OrderBy(dc => dc.Name)
+ .ToList();
+
+ foreach (var group in groups)
+ {
+ Console.WriteLine($"{group.Name,-20}{group.Headcount}");
+ }
+ }
+ {
+ var groups = context.Employees
+ .GroupBy(e => e.Department)
+ .Select(group => new
+ {
+ group.Key.Name,
+ Headcount = group.Count()
+ })
+ .Where(group => group.Headcount > 11)
+ .OrderBy(dc => dc.Name)
+ .ToList();
+
+ foreach (var group in groups)
+ {
+ Console.WriteLine($"{group.Name,-20}{group.Headcount}");
+ }
+ }
+}
+
+static void InnerJoin(HRContext context)
+{
+ {
+ Console.WriteLine("Get employees & departments");
+
+ var employees = context.Employees.Include(e => e.Department)
+ .OrderBy(e => e.FirstName)
+ .ToList();
+
+ foreach (var e in employees)
+ {
+ Console.WriteLine($"{e.FirstName} {e.LastName} - {e.Department.Name}");
+ }
+ }
+ {
+ Console.WriteLine("EF Core Inner Join in a many-to-many relationship");
+ var employees = context.Employees.Include(e => e.Skills)
+ .OrderBy(e => e.FirstName)
+ .ToList();
+
+ foreach (var e in employees)
+ {
+ Console.WriteLine($"{e.FirstName} {e.LastName}");
+
+ foreach (var skill in e.Skills)
+ {
+ Console.WriteLine($"- {skill.Title}");
+ }
+ }
+ }
+ {
+ Console.WriteLine("Using multiple joins");
+ var employees = context.Employees.Include(e => e.Department)
+ .Include(e => e.Skills)
+ .OrderBy(e => e.FirstName)
+ .ToList();
+
+ foreach (var e in employees)
+ {
+ Console.WriteLine($"{e.FirstName} {e.LastName} - {e.Department.Name}");
+
+ foreach (var skill in e.Skills)
+ {
+ Console.WriteLine($"- {skill.Title}");
+ }
+ }
+ }
+}
+
+static void Like(HRContext context)
+{
+ {
+ Console.WriteLine("Using the % wildcard character");
+
+ var keyword = "%ac%";
+ var employees = context.Employees
+ .Where(e => EF.Functions.Like(e.FirstName, keyword))
+ .ToList();
+
+ foreach (var e in employees)
+ {
+ Console.WriteLine($"{e.FirstName} {e.LastName}");
+ }
+ }
+ {
+ var keyword = "da%";
+ var employees = context.Employees
+ .Where(e => EF.Functions.Like(e.FirstName, keyword))
+ .ToList();
+
+ foreach (var e in employees)
+ {
+ Console.WriteLine($"{e.FirstName} {e.LastName}");
+ }
+ }
+ {
+ Console.WriteLine("Using the _ wildcard character");
+
+ var keyword = "H_n%";
+ var employees = context.Employees
+ .Where(e => EF.Functions.Like(e.FirstName, keyword))
+ .ToList();
+
+ foreach (var e in employees)
+ {
+ Console.WriteLine($"{e.FirstName} {e.LastName}");
+ }
+ }
+}
+
+static void InOperator(HRContext context)
+{
+ {
+ Console.WriteLine("Introduction to EF Core Where In");
+
+ int[] ids = [1, 2, 3];
+
+ var employees = context.Employees
+ .Where(e => ids.Contains(e.Id))
+ .ToList();
+
+ foreach (var e in employees)
+ {
+ Console.WriteLine($"{e.Id} - {e.FirstName} {e.LastName}");
+ }
+ }
+
+ {
+ Console.WriteLine("NOT IN");
+
+ int[] ids = [1, 2, 3];
+
+ var employees = context.Employees
+ .Where(e => !ids.Contains(e.Id))
+ .ToList();
+
+ foreach (var e in employees)
+ {
+ Console.WriteLine($"{e.Id} - {e.FirstName} {e.LastName}");
+ }
+ }
+}
+
+static void Where(HRContext context)
+{
+ {
+ Console.WriteLine("Using the Where() method with the equal operator");
+ // ReSharper disable once RedundantAssignment
+ var employees = context.Employees
+ .Where(e => e.FirstName == "Alexander")
+ .ToList();
+
+ // ReSharper disable once ConvertToConstant.Local
+ var firstName = "Alexander";
+ employees = context.Employees
+ .Where(e => e.FirstName == firstName)
+ .ToList();
+
+ foreach (var e in employees)
+ {
+ Console.WriteLine($"{e.FirstName} {e.LastName}");
+ }
+ }
+ {
+ Console.WriteLine("Using AND operator");
+ var firstName = "Alexander";
+ var lastName = "Young";
+
+ var employees = context.Employees
+ .Where(e => e.FirstName == firstName && e.LastName == lastName)
+ .ToList();
+
+ foreach (var e in employees)
+ {
+ Console.WriteLine($"{e.FirstName} {e.LastName}");
+ }
+ }
+ {
+ var startDate = new DateTime(2023, 3, 1);
+ var endDate = new DateTime(2023, 3, 31);
+
+ var employees = context.Employees
+ .Where(e => e.JoinedDate >= startDate && e.JoinedDate <= endDate)
+ .ToList();
+
+ foreach (var e in employees)
+ {
+ Console.WriteLine($"{e.FirstName} {e.LastName} - {e.JoinedDate.ToShortDateString()}");
+ }
+ }
+ {
+ Console.WriteLine("Using OR operator");
+ var firstName = "Emily";
+ var lastName = "Brown";
+
+ var employees = context.Employees
+ .Where(e => e.FirstName == firstName || e.LastName == lastName)
+ .ToList();
+
+ foreach (var e in employees)
+ {
+ Console.WriteLine($"{e.FirstName} {e.LastName}");
+ }
+ }
+}
+
+static void QueryLinq(HRContext context)
+{
+ {
+ Console.WriteLine("EF Core Query flow");
+
+ var departments = (from d in context.Departments select d).ToList();
+
+ foreach (var department in departments)
+ {
+ Console.WriteLine($"{department.Id}: {department.Name}");
+ }
+ }
+ {
+ Console.WriteLine("Query enumeration");
+
+ foreach (var d in context.Departments)
+ {
+ Console.WriteLine($"{d.Id} {d.Name}");
+ }
+ }
+ {
+ Console.WriteLine("Filtering data (WHERE Name == 'Sales')");
+ var name = "Sales";
+ // ReSharper disable once RedundantAssignment
+ var department = context.Departments
+ .Where(d => d.Name == "Sales")
+ .ToList();
+
+ department = context.Departments
+ .Where(d => d.Name == name)
+ .ToList();
+
+ foreach (var d in department)
+ {
+ Console.WriteLine($"{d.Id} {d.Name}");
+ }
+ }
+ {
+ Console.WriteLine("Filtering partial texts (LIKE)");
+ var keyword = "i";
+ var departments = context.Departments
+ .Where(d => EF.Functions.Like(d.Name, $"%{keyword}%"))
+ .ToList();
+
+ foreach (var d in departments)
+ {
+ Console.WriteLine($"{d.Id} {d.Name}");
+ }
+ }
+ {
+ Console.WriteLine("Finding an entity by its key value");
+ var department = context.Departments.Find(1);
+
+ Console.WriteLine($"{department?.Id} {department?.Name}");
+ }
+}
+
+static void OrderBy(HRContext context)
+{
+ Console.WriteLine("Sorting by one column in ascending order");
+
+ var listByOneColumnInAscendingOrder = context.Employees
+ .OrderBy(e => e.FirstName)
+ .Take(7)
+ .ToList();
+
+ foreach (var e in listByOneColumnInAscendingOrder)
+ {
+ Console.WriteLine(e.FirstName);
+ }
+
+ Console.WriteLine("Sorting by two or more columns in ascending order");
+
+ var listByTwoOrMoreColumnsInAscendingOrder = context.Employees
+ .OrderBy(e => e.FirstName)
+ .ThenBy(e => e.LastName)
+ .Take(7)
+ .ToList();
+
+ foreach (var e in listByTwoOrMoreColumnsInAscendingOrder)
+ {
+ Console.WriteLine($"{e.FirstName} {e.LastName}");
+ }
+
+ Console.WriteLine("Sorting by one column in descending order");
+
+ var listByOneColumnInDescendingOrder = context.Employees
+ .OrderByDescending(e => e.FirstName)
+ .Take(7)
+ .ToList();
+
+ foreach (var e in listByOneColumnInDescendingOrder)
+ {
+ Console.WriteLine(e.FirstName);
+ }
+
+ Console.WriteLine("Sorting by two or more columns in descending order");
+
+ var listByTwoOrMoreColumnsInDescendingOrder = context.Employees
+ .OrderByDescending(e => e.FirstName)
+ .ThenByDescending(e => e.LastName)
+ .Take(7)
+ .ToList();
+
+ foreach (var e in listByTwoOrMoreColumnsInDescendingOrder)
+ {
+ Console.WriteLine(e.FirstName);
+ }
+
+ Console.WriteLine("Sorting one column in ascending order and another column in descending order");
+
+ var list = context.Employees
+ .OrderBy(e => e.JoinedDate)
+ .ThenByDescending(e => e.FirstName)
+ .Take(6)
+ .ToList();
+
+ foreach (var e in list)
+ {
+ Console.WriteLine($"{e.JoinedDate.ToShortDateString()} {e.LastName}");
+ }
+}
+
+static void Select(HRContext context)
+{
+ Console.WriteLine("Selecting all rows from a table");
+
+ var employees = context.Employees.ToList();
+
+ foreach (var e in employees)
+ {
+ Console.WriteLine($"{e.FirstName} {e.LastName}");
+ }
+
+ Console.WriteLine("Selecting some columns from a table");
+
+ var names = context.Employees
+ .Select(e => $"{e.FirstName} {e.LastName}")
+ .ToList();
+
+ foreach (var name in names)
+ {
+ Console.WriteLine(name);
+ }
+
+ Console.WriteLine("Returning a list of anonymous objects");
+
+ var list = context.Employees
+ .Select(e => new { e.FirstName, e.JoinedDate })
+ .ToList();
+
+ foreach (var e in list)
+ {
+ Console.WriteLine($"{e.FirstName} - {e.JoinedDate.ToShortDateString()}");
+ }
+}
+
+static void ReadCSV(HRContext context)
+{
+ var employees = new List();
+ var skills = new List();
+ var departments = new List();
+
+ using var reader = new StreamReader("data.csv");
+
+ // Read the header line
+ _ = reader.ReadLine();
+
+ while (!reader.EndOfStream)
+ {
+ var line = reader.ReadLine();
+ if (line == null)
+ {
+ break;
+ }
+
+ // Split the line by comma
+ var values = line.Split(',');
+
+ if (values.Length == 8)
+ {
+ var firstName = values[0];
+ var lastName = values[1];
+ var salary = values[2];
+ var joinedDate = DateTime.ParseExact(values[3], "M/d/yyyy", null);
+ var phone = values[4];
+ var email = values[5];
+ var departmentName = values[6];
+ var skillTitles = values[7].Split(';');
+
+ // Create Department object if it doesn't exist
+ var department = departments.Find(d => d.Name == departmentName);
+ if (department == null)
+ {
+ department = new Department
+ {
+ Name = departmentName
+ };
+ departments.Add(department);
+ }
+
+ // Create EmployeeProfile object
+ var profile = new EmployeeProfile
+ {
+ Phone = phone,
+ Email = email
+ };
+
+ // Create Employee object
+ var employee = new Employee
+ {
+ FirstName = firstName,
+ LastName = lastName,
+ Salary = decimal.Parse(salary),
+ JoinedDate = joinedDate,
+ Department = department,
+ Profile = profile
+ };
+ employees.Add(employee);
+
+ // Create Skill objects
+ foreach (var skillTitle in skillTitles)
+ {
+ var skill = skills.Find(s => s.Title == skillTitle);
+ if (skill == null)
+ {
+ skill = new Skill
+ {
+ Title = skillTitle
+ };
+ skills.Add(skill);
+ }
+
+ // Add skill to the employee's Skills collection
+ employee.Skills.Add(skill);
+ }
+ }
+ }
+
+ Console.WriteLine($"{employees.Count} row(s) found");
+ foreach (var employee in employees)
+ {
+ context.Add(employee);
+ }
+
+ context.SaveChanges();
+}
+
+internal enum Action
+{
+ ReadCsv,
+ Select,
+ OrderBy,
+ QueryLinq,
+ Where,
+ InOperator,
+ Like,
+ InnerJoin,
+ GroupBy
+}
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/README.md b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/README.md
new file mode 100644
index 00000000..45a23410
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/README.md
@@ -0,0 +1,44 @@
+# Querying data using LINQ from Entity Framework Core YDB
+
+This sample demonstrates how to query data from YDB using Entity Framework Core and LINQ.
+
+Based on the [tutorial](https://www.csharptutorial.net/entity-framework-core-tutorial/).
+
+## Running
+
+1. Set up [YDB local](https://ydb.tech/docs/en/reference/docker/start).
+
+2. Install the EF Core CLI tool and dependencies (if needed):
+ ```bash
+ dotnet tool install --global dotnet-ef
+ dotnet add package Microsoft.EntityFrameworkCore.Design
+ ```
+
+3. Create the database and apply migrations:
+ ```bash
+ dotnet ef migrations add InitialCreate
+ dotnet ef database update
+ ```
+
+4. Run all operations sequentially with:
+ ```bash
+ dotnet run
+ ```
+
+## Available Operations
+
+You can execute individual operations by specifying the desired action as a command-line argument. Available actions:
+
+- ReadCsv
+- Select
+- OrderBy
+- QueryLinq
+- Where
+- InOperator
+- Like
+- InnerJoin
+- GroupBy
+
+```bash
+dotnet run Select
+```
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/Skill.cs b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/Skill.cs
new file mode 100644
index 00000000..c04e2ed6
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/Skill.cs
@@ -0,0 +1,10 @@
+namespace Database.Operations.Tutorial;
+
+public class Skill
+{
+ public int Id { get; set; }
+ public required string Title { get; set; }
+
+ // collection navigation to Employee
+ public List Employees { get; set; } = new();
+}
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/appsettings.json b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/appsettings.json
new file mode 100644
index 00000000..d649f8bb
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/appsettings.json
@@ -0,0 +1,5 @@
+{
+ "ConnectionStrings": {
+ "Local": "Host=localhost;Port=2136;Database=/local"
+ }
+}
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/data.csv b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/data.csv
new file mode 100644
index 00000000..0c04609b
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Database.Operations.Tutorial/data.csv
@@ -0,0 +1,61 @@
+First Name,Last Name,Salary,Joined Date,Phone,Email,Department,Skills
+John,Doe,89475,1/15/2023,(415) 555-1234,john.doe@test.com,Sales,Sales Strategy;Client Management
+Jane,Smith,194669,2/10/2023,(408) 555-5678,jane.smith@test.com,Marketing,Market Research;Digital Marketing
+Michael,Johnson,229772,3/5/2023,(650) 555-9876,michael.johnson@test.com,Finance,Financial Analysis;Budgeting
+Emily,Brown,190682,4/20/2023,(213) 555-2468,emily.brown@test.com,Sales,Client Relationship;Sales Planning
+William,Taylor,242917,5/3/2023,(714) 555-1357,william.taylor@test.com,Marketing,Content Creation;Social Media Marketing
+Olivia,Anderson,83995,6/8/2023,(909) 555-7890,olivia.anderson@test.com,Finance,Financial Reporting;Risk Management
+Benjamin,Lee,142247,7/11/2023,(925) 555-3698,benjamin.lee@test.com,Engineering,Software Development;Database Management
+Sophia,Wilson,237992,8/17/2023,(562) 555-2580,sophia.wilson@test.com,Operations,Process Improvement;Supply Chain Management
+Daniel,Clark,218336,9/25/2023,(650) 555-7410,daniel.clark@test.com,Marketing,Market Analysis;Campaign Management
+Isabella,Walker,119856,10/30/2023,(916) 555-9632,isabella.walker@test.com,Finance,Financial Planning;Investment Analysis
+Ethan,Hall,172377,11/12/2023,(818) 555-7531,ethan.hall@test.com,Engineering,Software Engineering;Systems Architecture
+Mia,Lopez,203546,12/5/2023,(619) 555-4876,mia.lopez@test.com,Sales,Sales Operations;Lead Generation
+James,Green,248710,1/1/2023,(408) 555-9517,james.green@test.com,Operations,Logistics Management;Inventory Control
+Ava,Hernandez,190830,2/14/2023,(213) 555-3698,ava.hernandez@test.com,Marketing,Brand Management;Product Launch
+Alexander,Young,97092,3/18/2023,(714) 555-8025,alexander.young@test.com,Finance,Financial Modeling;Cost Analysis
+Charlotte,King,117417,4/22/2023,(925) 555-6479,charlotte.king@test.com,Engineering,Product Design;Quality Assurance
+Logan,Hill,225291,5/27/2023,(562) 555-3216,logan.hill@test.com,Sales,Account Management;Negotiation
+Amelia,Scott,183392,6/30/2023,(650) 555-4567,amelia.scott@test.com,Operations,Process Optimization;Facilities Management
+Daniel,Lewis,103561,7/5/2023,(916) 555-7890,daniel.lewis@test.com,Engineering,Hardware Development;Embedded Systems
+Abigail,Adams,225228,8/9/2023,(818) 555-8524,abigail.adams@test.com,Marketing,Marketing Strategy;Market Segmentation
+Oliver,Allen,161033,9/13/2023,(619) 555-9632,oliver.allen@test.com,Finance,Financial Forecasting;Tax Planning
+Sophia,Lee,248627,10/18/2023,(415) 555-1478,sophia.lee@test.com,Operations,Supply Chain Optimization;Process Automation
+Emily,Harris,208887,11/21/2023,(408) 555-3698,emily.harris@test.com,Sales,Business Development;Key Account Management
+Jacob,Turner,182322,12/25/2023,(213) 555-7531,jacob.turner@test.com,Marketing,SEO;Content Marketing
+Madison,Wright,80164,1/29/2023,(714) 555-2580,madison.wright@test.com,Finance,Financial Compliance;Auditing
+Lucas,Hill,223297,2/23/2023,(925) 555-9517,lucas.hill@test.com,Engineering,Network Engineering;Cloud Computing
+Sofia,Thomas,127653,3/17/2023,(562) 555-3698,sofia.thomas@test.com,Operations,Project Management;Quality Management
+Henry,Lopez,141701,4/10/2023,(650) 555-7410,henry.lopez@test.com,Sales,Inside Sales;Sales Forecasting
+Avery,Adams,82895,5/4/2023,(916) 555-9632,avery.adams@test.com,Marketing,Influencer Marketing;Event Planning
+Alexander,Green,215160,6/28/2023,(818) 555-7890,alexander.green@test.com,Finance,Financial Risk Management;Investment Banking
+Ella,Baker,120032,7/22/2023,(619) 555-4567,ella.baker@test.com,Engineering,Data Science;Machine Learning
+Jackson,Evans,139075,8/16/2023,(415) 555-8025,jackson.evans@test.com,Operations,Continuous Improvement;Lean Manufacturing
+Scarlett,Gonzalez,175443,9/10/2023,(408) 555-3698,scarlett.gonzalez@test.com,Sales,Outside Sales;Sales Presentations
+Aiden,Wright,154326,10/4/2023,(213) 555-9632,aiden.wright@test.com,Marketing,Market Trend Analysis;Brand Development
+Penelope,Lee,230399,11/28/2023,(714) 555-1478,penelope.lee@test.com,Finance,Financial Valuation;Mergers and Acquisitions
+Mason,Hernandez,178930,12/22/2023,(925) 555-3698,mason.hernandez@test.com,Engineering,Software Testing;Quality Assurance
+Lily,Turner,160080,1/16/2023,(562) 555-8524,lily.turner@test.com,Operations,Inventory Management;Supplier Relationship Management
+Liam,Scott,108406,2/9/2023,(650) 555-7410,liam.scott@test.com,Sales,Strategic Account Management;Sales Analytics
+Chloe,Young,248731,3/5/2023,(916) 555-8524,chloe.young@test.com,Marketing,Content Strategy;Social Media Management
+Jacob,Lopez,219674,4/29/2023,(818) 555-2580,jacob.lopez@test.com,Finance,Financial Planning;Financial Reporting
+Grace,Allen,216574,5/23/2023,(619) 555-9517,grace.allen@test.com,Engineering,Software Development;Systems Engineering
+Zoe,Hill,203918,6/17/2023,(415) 555-3698,zoe.hill@test.com,Operations,Logistics Planning;Process Standardization
+Elijah,Harris,184617,7/11/2023,(408) 555-7531,elijah.harris@test.com,Sales,Lead Generation;Account Development
+Aurora,King,230678,8/5/2023,(213) 555-8524,aurora.king@test.com,Marketing,Email Marketing;Digital Advertising
+Carter,Adams,113398,9/29/2023,(714) 555-1478,carter.adams@test.com,Finance,Financial Analysis;Risk Assessment
+Aria,Johnson,191577,10/24/2023,(925) 555-3698,aria.johnson@test.com,Engineering,Hardware Design;Embedded Systems
+Luke,Walker,118605,11/18/2023,(562) 555-7410,luke.walker@test.com,Operations,Process Optimization;Supply Chain Analysis
+Ruby,Thomas,143820,12/12/2023,(650) 555-9632,ruby.thomas@test.com,Sales,Sales Operations;Customer Relationship Management
+Ethan,Brown,219040,1/5/2023,(916) 555-8524,ethan.brown@test.com,Marketing,Market Research;Product Management
+Hannah,Evans,171432,2/28/2023,(818) 555-4567,hannah.evans@test.com,Finance,Financial Forecasting;Budgeting
+Levi,Gonzalez,227072,3/24/2023,(619) 555-7410,levi.gonzalez@test.com,Engineering,Network Security;Database Management
+Nora,Baker,195789,4/18/2023,(415) 555-9632,nora.baker@test.com,Operations,Project Planning;Facilities Planning
+Jack,Wright,157791,5/12/2023,(408) 555-8524,jack.wright@test.com,Sales,Sales Strategy;Negotiation
+Aubrey,Clark,176029,6/5/2023,(213) 555-3698,aubrey.clark@test.com,Marketing,Brand Strategy;Content Creation
+Wyatt,Allen,125464,7/30/2023,(714) 555-7410,wyatt.allen@test.com,Finance,Financial Modeling;Investment Analysis
+Addison,Hill,126447,8/24/2023,(925) 555-8524,addison.hill@test.com,Engineering,Product Design;Quality Assurance
+Harper,Scott,147482,9/17/2023,(562) 555-9632,harper.scott@test.com,Operations,Process Improvement;Supply Chain Management
+Thomas,Lopez,215337,10/11/2023,(650) 555-3698,thomas.lopez@test.com,Sales,Client Relationship;Sales Planning
+Samantha,Green,85362,11/4/2023,(916) 555-7410,samantha.green@test.com,Marketing,Market Analysis;Campaign Management
+Henry,Adams,238372,12/28/2023,(818) 555-8524,henry.adams@test.com,Finance,Financial Planning;Investment Analysis
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/README.md b/examples/EntityFrameworkCore.Ydb.Samples/README.md
new file mode 100644
index 00000000..c582d104
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/README.md
@@ -0,0 +1,18 @@
+# Entity Framework Core Ydb Samples
+
+This project contains a number of samples for using Entity Framework Core in combination with YDB.
+
+Some samples are inspired by the [Entity Framework Core Tutorial](https://www.csharptutorial.net/entity-framework-core-tutorial).
+
+## Samples
+
+- **AddEntity.Sample** – Example for adding entities.
+- **Database.Operations.Tutorial** – Basic database operations.
+- **Schema.OneToOne** – One-to-one relationship.
+- **Schema.OneToMany** – One-to-many relationship.
+- **Schema.ManyToMany** – Many-to-many relationship.
+
+## Usage
+
+Each subfolder contains an independent sample.
+Please refer to the README or documentation inside each sample folder for instructions on how to run it.
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Schema.ManyToMany/HRContext.cs b/examples/EntityFrameworkCore.Ydb.Samples/Schema.ManyToMany/HRContext.cs
new file mode 100644
index 00000000..810242ac
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Schema.ManyToMany/HRContext.cs
@@ -0,0 +1,35 @@
+using EntityFrameworkCore.Ydb.Extensions;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Design;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+
+namespace Schema.ManyToMany;
+
+public class HRContext(DbContextOptions options) : DbContext(options)
+{
+ public DbSet Employees { get; set; }
+ public DbSet Departments { get; set; }
+}
+
+internal class HRContextContextFactory : IDesignTimeDbContextFactory
+{
+ public HRContext CreateDbContext(string[] args)
+ {
+ var optionsBuilder = new DbContextOptionsBuilder();
+
+ // IMPORTANT!
+ // Disables retries for the migrations context.
+ // Required because migration operations may use suppressed or explicit transactions,
+ // and enabling retries in this case leads to runtime errors with this provider.
+ //
+ // "System.NotSupportedException: User transaction is not supported with a TransactionSuppressed migrations or a retrying execution strategy."
+ //
+ // Bottom line: ALWAYS disable retries for design-time/migration contexts to avoid migration failures and errors.
+ return new HRContext(
+ optionsBuilder
+ .UseYdb("Host=localhost;Port=2136;Database=/local", builder => builder.DisableRetryOnFailure())
+ .ConfigureWarnings(warnings => warnings.Ignore(RelationalEventId.PendingModelChangesWarning))
+ .Options
+ );
+ }
+}
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Schema.ManyToMany/Models.cs b/examples/EntityFrameworkCore.Ydb.Samples/Schema.ManyToMany/Models.cs
new file mode 100644
index 00000000..7acb76a5
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Schema.ManyToMany/Models.cs
@@ -0,0 +1,51 @@
+namespace Schema.ManyToMany;
+
+public class Department
+{
+ public int Id { get; set; }
+ public required string Name { get; set; }
+
+ // Collection navigation containing children
+ public required ICollection Employees { get; set; }
+}
+
+public class Employee
+{
+ public int Id { get; set; }
+ public required string FirstName { get; set; }
+ public required string LastName { get; set; }
+ public required decimal Salary { get; set; }
+ public required DateTime JoinedDate { get; set; }
+ public int DepartmentId { get; set; }
+
+ // Reference navigation to Department
+ public Department Department { get; set; } = null!;
+
+ // Reference navigation to EmployeeProfile
+ public EmployeeProfile? Profile { get; set; }
+
+ // collection navigation to Employee
+ public List Skills { get; set; } = new();
+}
+
+public class EmployeeProfile
+{
+ public int Id { get; set; }
+ public required string Phone { get; set; }
+ public required string Email { get; set; }
+
+ // Required foreign key property
+ public int EmployeeId { get; set; }
+
+ // Required reference navigation to Employee
+ public Employee Employee { get; set; } = null!;
+}
+
+public class Skill
+{
+ public int Id { get; set; }
+ public required string Title { get; set; }
+
+ // collection navigation to Employee
+ public List Employees { get; set; } = new();
+}
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Schema.ManyToMany/Program.cs b/examples/EntityFrameworkCore.Ydb.Samples/Schema.ManyToMany/Program.cs
new file mode 100644
index 00000000..9cbe6ada
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Schema.ManyToMany/Program.cs
@@ -0,0 +1 @@
+Console.WriteLine();
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Schema.ManyToMany/README.md b/examples/EntityFrameworkCore.Ydb.Samples/Schema.ManyToMany/README.md
new file mode 100644
index 00000000..b12291c7
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Schema.ManyToMany/README.md
@@ -0,0 +1,28 @@
+# Entity Framework Core YDB Schema Many-to-Many Example
+
+This sample demonstrates how to model a [many-to-many relationship](https://www.csharptutorial.net/entity-framework-core-tutorial/ef-core-many-to-many-relationships/) in Entity Framework Core targeting YDB.
+
+The focus here is to show what database schema (DDL) will be generated by EF Core migrations for such a model.
+
+## How to View the Generated Schema
+
+1. Set up a local YDB instance:
+ [YDB local setup guide](https://ydb.tech/docs/en/reference/docker/start)
+
+2. Install the EF Core CLI tool (if needed):
+ ```bash
+ dotnet tool install --global dotnet-ef
+ dotnet add package Microsoft.EntityFrameworkCore.Design
+ ```
+
+3. Add a migration to generate the DDL (if not already present):
+ ```bash
+ dotnet ef migrations add InitialCreate
+ ```
+
+4. Generate the SQL script for the schema:
+ ```bash
+ dotnet ef migrations script
+ ```
+
+5. Inspect the generated SQL script to see how EF Core maps the many-to-many relationship in YDB.
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Schema.ManyToMany/Schema.ManyToMany.csproj b/examples/EntityFrameworkCore.Ydb.Samples/Schema.ManyToMany/Schema.ManyToMany.csproj
new file mode 100644
index 00000000..4449f9bb
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Schema.ManyToMany/Schema.ManyToMany.csproj
@@ -0,0 +1,21 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+ Schema.ManyToMany
+
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToMany/HRContext.cs b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToMany/HRContext.cs
new file mode 100644
index 00000000..85d99eaa
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToMany/HRContext.cs
@@ -0,0 +1,37 @@
+// using Microsoft.EntityFrameworkCore;
+
+using EntityFrameworkCore.Ydb.Extensions;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Design;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+
+namespace Schema.OneToMany;
+
+public class HRContext(DbContextOptions options) : DbContext(options)
+{
+ public DbSet Employees { get; set; }
+ public DbSet Departments { get; set; }
+}
+
+internal class HRContextContextFactory : IDesignTimeDbContextFactory
+{
+ public HRContext CreateDbContext(string[] args)
+ {
+ var optionsBuilder = new DbContextOptionsBuilder();
+
+ // IMPORTANT!
+ // Disables retries for the migrations context.
+ // Required because migration operations may use suppressed or explicit transactions,
+ // and enabling retries in this case leads to runtime errors with this provider.
+ //
+ // "System.NotSupportedException: User transaction is not supported with a TransactionSuppressed migrations or a retrying execution strategy."
+ //
+ // Bottom line: ALWAYS disable retries for design-time/migration contexts to avoid migration failures and errors.
+ return new HRContext(
+ optionsBuilder
+ .UseYdb("Host=localhost;Port=2136;Database=/local", builder => builder.DisableRetryOnFailure())
+ .ConfigureWarnings(warnings => warnings.Ignore(RelationalEventId.PendingModelChangesWarning))
+ .Options
+ );
+ }
+}
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToMany/Models.cs b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToMany/Models.cs
new file mode 100644
index 00000000..a05bcec5
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToMany/Models.cs
@@ -0,0 +1,25 @@
+namespace Schema.OneToMany;
+
+public class Department
+{
+ public int Id { get; set; }
+ public required string Name { get; set; }
+
+ // Collection navigation containing children
+ public required ICollection Employees { get; set; }
+}
+
+public class Employee
+{
+ public int Id { get; set; }
+ public required string FirstName { get; set; }
+ public required string LastName { get; set; }
+ public required decimal Salary { get; set; }
+ public required DateTime JoinedDate { get; set; }
+
+ // Required foreign key property
+ public int DepartmentId { get; set; }
+
+ // Required reference navigation to parent
+ public Department Department { get; set; } = null!;
+}
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToMany/Program.cs b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToMany/Program.cs
new file mode 100644
index 00000000..9cbe6ada
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToMany/Program.cs
@@ -0,0 +1 @@
+Console.WriteLine();
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToMany/README.md b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToMany/README.md
new file mode 100644
index 00000000..f1a9d02f
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToMany/README.md
@@ -0,0 +1,27 @@
+# Entity Framework Core YDB Schema One-to-Many Example
+
+This sample demonstrates how to model a [one-to-many relationship](https://www.csharptutorial.net/entity-framework-core-tutorial/ef-core-one-to-many-relationship/) in Entity Framework Core targeting YDB.
+
+The focus here is to show what database schema (DDL) will be generated by EF Core migrations for such a model.
+
+## How to View the Generated Schema
+
+1. Set up [YDB local](https://ydb.tech/docs/en/reference/docker/start).
+
+2. Install the EF Core CLI tool (if needed):
+ ```bash
+ dotnet tool install --global dotnet-ef
+ dotnet add package Microsoft.EntityFrameworkCore.Design
+ ```
+
+3. Add a migration to generate the DDL (if not already present):
+ ```bash
+ dotnet ef migrations add InitialCreate
+ ```
+
+4. Generate the SQL script for the schema:
+ ```bash
+ dotnet ef migrations script
+ ```
+
+5. Inspect the generated SQL script to see how EF Core maps the one-to-many relationship in YDB.
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToMany/Schema.OneToMany.csproj b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToMany/Schema.OneToMany.csproj
new file mode 100644
index 00000000..29520a74
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToMany/Schema.OneToMany.csproj
@@ -0,0 +1,21 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+ Schema.OneToMany
+
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToOne/HRContext.cs b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToOne/HRContext.cs
new file mode 100644
index 00000000..7f78fa3e
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToOne/HRContext.cs
@@ -0,0 +1,37 @@
+// using Microsoft.EntityFrameworkCore;
+
+using EntityFrameworkCore.Ydb.Extensions;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Design;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+
+namespace Schema.OneToOne;
+
+public class HRContext(DbContextOptions options) : DbContext(options)
+{
+ public DbSet Employees { get; set; }
+ public DbSet Departments { get; set; }
+}
+
+internal class HRContextContextFactory : IDesignTimeDbContextFactory
+{
+ public HRContext CreateDbContext(string[] args)
+ {
+ var optionsBuilder = new DbContextOptionsBuilder();
+
+ // IMPORTANT!
+ // Disables retries for the migrations context.
+ // Required because migration operations may use suppressed or explicit transactions,
+ // and enabling retries in this case leads to runtime errors with this provider.
+ //
+ // "System.NotSupportedException: User transaction is not supported with a TransactionSuppressed migrations or a retrying execution strategy."
+ //
+ // Bottom line: ALWAYS disable retries for design-time/migration contexts to avoid migration failures and errors.
+ return new HRContext(
+ optionsBuilder
+ .UseYdb("Host=localhost;Port=2136;Database=/local", builder => builder.DisableRetryOnFailure())
+ .ConfigureWarnings(warnings => warnings.Ignore(RelationalEventId.PendingModelChangesWarning))
+ .Options
+ );
+ }
+}
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToOne/Models.cs b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToOne/Models.cs
new file mode 100644
index 00000000..60037e96
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToOne/Models.cs
@@ -0,0 +1,39 @@
+namespace Schema.OneToOne;
+
+public class Department
+{
+ public int Id { get; set; }
+ public required string Name { get; set; }
+
+ // Collection navigation containing children
+ public required ICollection Employees { get; set; }
+}
+
+public class Employee
+{
+ public int Id { get; set; }
+ public required string FirstName { get; set; }
+ public required string LastName { get; set; }
+ public required decimal Salary { get; set; }
+ public required DateTime JoinedDate { get; set; }
+ public int DepartmentId { get; set; }
+
+ // Reference navigation to Department
+ public Department Department { get; set; } = null!;
+
+ // Reference navigation to EmployeeProfile
+ public EmployeeProfile? Profile { get; set; }
+}
+
+public class EmployeeProfile
+{
+ public int Id { get; set; }
+ public required string Phone { get; set; }
+ public required string Email { get; set; }
+
+ // Required foreign key property
+ public int EmployeeId { get; set; }
+
+ // Required reference navigation to Employee
+ public Employee Employee { get; set; } = null!;
+}
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToOne/Program.cs b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToOne/Program.cs
new file mode 100644
index 00000000..864ddc49
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToOne/Program.cs
@@ -0,0 +1 @@
+Console.WriteLine();
\ No newline at end of file
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToOne/README.md b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToOne/README.md
new file mode 100644
index 00000000..5609e498
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToOne/README.md
@@ -0,0 +1,27 @@
+# Entity Framework Core YDB Schema One-to-One Example
+
+This sample demonstrates how to model a [one-to-one relationship](https://www.csharptutorial.net/entity-framework-core-tutorial/ef-core-one-to-one/) in Entity Framework Core targeting YDB.
+
+The focus here is to show what database schema (DDL) will be generated by EF Core migrations for such a model.
+
+## How to View the Generated Schema
+
+1. Set up [YDB local](https://ydb.tech/docs/en/reference/docker/start).
+
+2. Install the EF Core CLI tool (if needed):
+ ```bash
+ dotnet tool install --global dotnet-ef
+ dotnet add package Microsoft.EntityFrameworkCore.Design
+ ```
+
+3. Add a migration to generate the DDL (if not already present):
+ ```bash
+ dotnet ef migrations add InitialCreate
+ ```
+
+4. Generate the SQL script for the schema:
+ ```bash
+ dotnet ef migrations script
+ ```
+
+5. Inspect the generated SQL script to see how EF Core maps the one-to-one relationship in YDB.
diff --git a/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToOne/Schema.OneToOne.csproj b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToOne/Schema.OneToOne.csproj
new file mode 100644
index 00000000..484e670b
--- /dev/null
+++ b/examples/EntityFrameworkCore.Ydb.Samples/Schema.OneToOne/Schema.OneToOne.csproj
@@ -0,0 +1,21 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+ Schema.OneToOne
+
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
diff --git a/examples/src/EntityFrameworkCore.Ydb.Yandex.Cloud/CmdOptions.cs b/examples/EntityFrameworkCore.Ydb.Yandex.Cloud/CmdOptions.cs
similarity index 100%
rename from examples/src/EntityFrameworkCore.Ydb.Yandex.Cloud/CmdOptions.cs
rename to examples/EntityFrameworkCore.Ydb.Yandex.Cloud/CmdOptions.cs
diff --git a/examples/src/EntityFrameworkCore.Ydb.Yandex.Cloud/EntityFrameworkCore.Ydb.Yandex.Cloud.csproj b/examples/EntityFrameworkCore.Ydb.Yandex.Cloud/EntityFrameworkCore.Ydb.Yandex.Cloud.csproj
similarity index 80%
rename from examples/src/EntityFrameworkCore.Ydb.Yandex.Cloud/EntityFrameworkCore.Ydb.Yandex.Cloud.csproj
rename to examples/EntityFrameworkCore.Ydb.Yandex.Cloud/EntityFrameworkCore.Ydb.Yandex.Cloud.csproj
index 7c01b52e..a6522c29 100644
--- a/examples/src/EntityFrameworkCore.Ydb.Yandex.Cloud/EntityFrameworkCore.Ydb.Yandex.Cloud.csproj
+++ b/examples/EntityFrameworkCore.Ydb.Yandex.Cloud/EntityFrameworkCore.Ydb.Yandex.Cloud.csproj
@@ -16,7 +16,6 @@
-
-
+
diff --git a/examples/src/EntityFrameworkCore.Ydb.Yandex.Cloud/Program.cs b/examples/EntityFrameworkCore.Ydb.Yandex.Cloud/Program.cs
similarity index 100%
rename from examples/src/EntityFrameworkCore.Ydb.Yandex.Cloud/Program.cs
rename to examples/EntityFrameworkCore.Ydb.Yandex.Cloud/Program.cs
diff --git a/examples/src/EntityFrameworkCore.Ydb.Yandex.Cloud/README.md b/examples/EntityFrameworkCore.Ydb.Yandex.Cloud/README.md
similarity index 100%
rename from examples/src/EntityFrameworkCore.Ydb.Yandex.Cloud/README.md
rename to examples/EntityFrameworkCore.Ydb.Yandex.Cloud/README.md
diff --git a/examples/README.md b/examples/README.md
index b1ff27e6..aa581d29 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -1,35 +1,13 @@
-# YDB .NET SDK Examples
+# YDB .NET Ecosystem Examples
-## Prerequisites
-.NET 6
+Sample projects for working with YDB in .NET.
-## Running examples
+## Projects
-1. Clone repository
- ```bash
- git clone https://github.com/ydb-platform/ydb-dotnet-sdk.git
- ```
-
-2. Build solution
- ```bash
- cd ydb-dotnet-sdk/examples/src
- dotnet build
- ```
-
-3. Run example
- ```bash
- cd
- dotnet run -e -d
- ```
-
-## Provided examples
-
-### BasicExample
-Demonstrates basic operations with YDB, including:
-* Driver initialization
-* Table client initialization
-* Table creation via SchemeQuery (DDL)
-* Data queries (OLTP) & transactions (read, modify)
-* Interactive transactions
-* ReadTable for streaming read of table contents
-* ScanQuery for streaming wide queries (OLAP)
+- **Ydb.Sdk.AdoNet.QuickStart** – Quickstart for using YDB with ADO.NET.
+- **Ydb.Sdk.AdoNet.Dapper.QuickStart** – Example of Dapper usage with YDB.
+- **Ydb.Sdk.AdoNet.Yandex.Cloud** – Connecting to YDB in Yandex Cloud via ADO.NET.
+- **EntityFrameworkCore.Ydb.QuickStart** – Quickstart for YDB + Entity Framework Core.
+- **EntityFrameworkCore.Ydb.Samples** – Extended Entity Framework Core samples.
+- **EntityFrameworkCore.Ydb.Yandex.Cloud** – Example of EF Core with YDB in Yandex Cloud.
+- **Ydb.Sdk.Topic.QuickStart** – Example for Topic API.
diff --git a/examples/src/DapperExample/Program.cs b/examples/Ydb.Sdk.AdoNet.Dapper.QuickStart/Program.cs
similarity index 99%
rename from examples/src/DapperExample/Program.cs
rename to examples/Ydb.Sdk.AdoNet.Dapper.QuickStart/Program.cs
index bbcde0da..4e050913 100644
--- a/examples/src/DapperExample/Program.cs
+++ b/examples/Ydb.Sdk.AdoNet.Dapper.QuickStart/Program.cs
@@ -6,6 +6,7 @@
// Init Users table
await using var connection = await new YdbDataSource().OpenConnectionAsync();
+await connection.ExecuteAsync("DROP TABLE IF EXISTS Users");
await connection.ExecuteAsync("""
CREATE TABLE IF NOT EXISTS Users(
Id Int32,
@@ -21,8 +22,6 @@ await connection.ExecuteAsync("INSERT INTO Users(Id, Name, Email) VALUES (@Id, @
Console.WriteLine(await connection.QuerySingleAsync("SELECT * FROM Users WHERE Id = @Id",
new { Id = 1 }));
-await connection.ExecuteAsync("DROP TABLE IF EXISTS Users");
-
internal class User
{
public int Id { get; init; }
diff --git a/examples/Ydb.Sdk.AdoNet.Dapper.QuickStart/README.md b/examples/Ydb.Sdk.AdoNet.Dapper.QuickStart/README.md
new file mode 100644
index 00000000..72600d4a
--- /dev/null
+++ b/examples/Ydb.Sdk.AdoNet.Dapper.QuickStart/README.md
@@ -0,0 +1,13 @@
+# YDB Sdk ADO.NET Dapper Quick Start
+
+A sample application demonstrating simple usage of Dapper with the YDB ADO.NET provider.
+Shows how to perform basic database queries and map results to C# objects using Dapper.
+
+## Running QuickStart
+
+1. Set up [YDB local](https://ydb.tech/docs/en/reference/docker/start).
+
+2. Run the app:
+ ```bash
+ dotnet run
+ ```
diff --git a/examples/src/DapperExample/DapperExample.csproj b/examples/Ydb.Sdk.AdoNet.Dapper.QuickStart/Ydb.Sdk.AdoNet.Dapper.QuickStart.csproj
similarity index 72%
rename from examples/src/DapperExample/DapperExample.csproj
rename to examples/Ydb.Sdk.AdoNet.Dapper.QuickStart/Ydb.Sdk.AdoNet.Dapper.QuickStart.csproj
index e1d9c706..868b1300 100644
--- a/examples/src/DapperExample/DapperExample.csproj
+++ b/examples/Ydb.Sdk.AdoNet.Dapper.QuickStart/Ydb.Sdk.AdoNet.Dapper.QuickStart.csproj
@@ -5,11 +5,11 @@
net8.0
enable
enable
- Dapper
+ Ydb.Sdk.AdoNet.Dapper.QuickStart
-
+
diff --git a/examples/src/AdoNet/CmdOptions.cs b/examples/Ydb.Sdk.AdoNet.QuickStart/CmdOptions.cs
similarity index 95%
rename from examples/src/AdoNet/CmdOptions.cs
rename to examples/Ydb.Sdk.AdoNet.QuickStart/CmdOptions.cs
index 00b2100f..f2b0b4b9 100644
--- a/examples/src/AdoNet/CmdOptions.cs
+++ b/examples/Ydb.Sdk.AdoNet.QuickStart/CmdOptions.cs
@@ -1,6 +1,6 @@
using CommandLine;
-namespace AdoNet;
+namespace Ydb.Sdk.AdoNet.QuickStart;
internal class CmdOptions
{
diff --git a/examples/src/AdoNet/Program.cs b/examples/Ydb.Sdk.AdoNet.QuickStart/Program.cs
similarity index 97%
rename from examples/src/AdoNet/Program.cs
rename to examples/Ydb.Sdk.AdoNet.QuickStart/Program.cs
index c0e3b533..bba59fd5 100644
--- a/examples/src/AdoNet/Program.cs
+++ b/examples/Ydb.Sdk.AdoNet.QuickStart/Program.cs
@@ -1,9 +1,9 @@
using System.Data;
-using AdoNet;
using CommandLine;
using Microsoft.Extensions.Logging;
using Polly;
using Ydb.Sdk.Ado;
+using Ydb.Sdk.AdoNet.QuickStart;
using var factory = LoggerFactory.Create(builder => builder.AddConsole());
@@ -82,8 +82,6 @@ CREATE TABLE episodes
PRIMARY KEY (series_id, season_id, episode_id)
);
""";
- _logger.LogInformation("Creating tables for examples, SQL script: {CommandText}", ydbCommand.CommandText);
-
await ydbCommand.ExecuteNonQueryAsync();
_logger.LogInformation("Created tables");
@@ -185,8 +183,6 @@ UPSERT INTO episodes (series_id, season_id, episode_id, title, air_date)
(2, 5, 7, "Initial Coin Offering", Date("2018-05-06")),
(2, 5, 8, "Fifty-One Percent", Date("2018-05-13"));
""";
- _logger.LogInformation("Loading data for examples, SQL script: {CommandText}", ydbCommand.CommandText);
-
await ydbCommand.ExecuteNonQueryAsync();
_logger.LogInformation("Loaded data");
@@ -225,8 +221,6 @@ ORDER BY -- Sorting the results.
ydbCommand.Parameters.Add(new YdbParameter("$season_id", DbType.UInt64, 1U));
ydbCommand.Parameters.Add(new YdbParameter("$limit_size", DbType.UInt64, 3U));
- _logger.LogInformation("Selecting data, SQL script: {CommandText}", ydbCommand.CommandText);
-
var ydbDataReader = await ydbCommand.ExecuteReaderAsync();
_logger.LogInformation("Selected rows:");
@@ -312,16 +306,13 @@ private async Task InteractiveTransaction()
UPSERT INTO episodes (series_id, season_id, episode_id, title, air_date)
VALUES (2, 5, 13, "Test Episode", Date("2018-08-27"))
""";
- _logger.LogInformation("Updating data, SQL script: {CommandText}", ydbCommand.CommandText);
await ydbCommand.ExecuteNonQueryAsync();
-
ydbCommand.CommandText = """
INSERT INTO episodes(series_id, season_id, episode_id, title, air_date)
VALUES
(2, 5, 21, "Test 21", Date("2018-08-27")),
(2, 5, 22, "Test 22", Date("2018-08-27"))
""";
- _logger.LogInformation("Inserting data, SQL script: {CommandText}", ydbCommand.CommandText);
await ydbCommand.ExecuteNonQueryAsync();
await ydbCommand.Transaction.CommitAsync();
_logger.LogInformation("Commit transaction");
@@ -405,7 +396,7 @@ private async Task ConnectionWithLoggerFactory()
{
Host = _cmdOptions.Host,
Port = _cmdOptions.Port,
- LoggerFactory = LoggerFactory.Create(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Debug))
+ LoggerFactory = LoggerFactory.Create(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Information))
};
await using var ydbConnection = new YdbConnection(connectionStringBuilder);
await ydbConnection.OpenAsync();
diff --git a/examples/Ydb.Sdk.AdoNet.QuickStart/README.md b/examples/Ydb.Sdk.AdoNet.QuickStart/README.md
new file mode 100644
index 00000000..377cb9ba
--- /dev/null
+++ b/examples/Ydb.Sdk.AdoNet.QuickStart/README.md
@@ -0,0 +1,14 @@
+# YDB Sdk ADO.NET Quick Start
+
+A sample application demonstrating how to use YDB with ADO.NET.
+Shows how to create tables, execute interactive transactions, and perform basic database operations using the standard
+ADO.NET API.
+
+## Running QuickStart
+
+1. Set up [YDB local](https://ydb.tech/docs/en/reference/docker/start).
+
+2. Run the app:
+ ```bash
+ dotnet run
+ ```
diff --git a/examples/src/AdoNet/AdoNet.csproj b/examples/Ydb.Sdk.AdoNet.QuickStart/Ydb.Sdk.AdoNet.QuickStart.csproj
similarity index 81%
rename from examples/src/AdoNet/AdoNet.csproj
rename to examples/Ydb.Sdk.AdoNet.QuickStart/Ydb.Sdk.AdoNet.QuickStart.csproj
index 2f0be3a9..54d438b6 100644
--- a/examples/src/AdoNet/AdoNet.csproj
+++ b/examples/Ydb.Sdk.AdoNet.QuickStart/Ydb.Sdk.AdoNet.QuickStart.csproj
@@ -5,10 +5,11 @@
net8.0
enable
enable
+ Ydb.Sdk.AdoNet.QuickStart
-
+
diff --git a/examples/Ydb.Sdk.AdoNet.Yandex.Cloud/CmdOptions.cs b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud/CmdOptions.cs
new file mode 100644
index 00000000..00bb0df5
--- /dev/null
+++ b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud/CmdOptions.cs
@@ -0,0 +1,12 @@
+using CommandLine;
+
+namespace Ydb.Sdk.AdoNet.Yandex.Cloud;
+
+internal class CmdOptions
+{
+ [Option("connectionString", Required = true, HelpText = "ConnectionString ADO.NET format")]
+ public string ConnectionString { get; set; } = null!;
+
+ [Option("saFilePath", Required = true, HelpText = "Sa Key")]
+ public string SaFilePath { get; set; } = null!;
+}
\ No newline at end of file
diff --git a/examples/src/YC/Program.cs b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud/Program.cs
similarity index 78%
rename from examples/src/YC/Program.cs
rename to examples/Ydb.Sdk.AdoNet.Yandex.Cloud/Program.cs
index 5686b9cf..a504a4d2 100644
--- a/examples/src/YC/Program.cs
+++ b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud/Program.cs
@@ -1,7 +1,7 @@
using CommandLine;
using Microsoft.Extensions.Logging;
-using YcCloud;
using Ydb.Sdk.Ado;
+using Ydb.Sdk.AdoNet.Yandex.Cloud;
using Ydb.Sdk.Yc;
await Parser.Default.ParseArguments(args).WithParsedAsync(async cmd =>
@@ -10,12 +10,8 @@ await Parser.Default.ParseArguments(args).WithParsedAsync(async cmd
var saProvider = new ServiceAccountProvider(saFilePath: cmd.SaFilePath, loggerFactory: loggerFactory);
- var builder = new YdbConnectionStringBuilder
+ var builder = new YdbConnectionStringBuilder(cmd.ConnectionString)
{
- UseTls = true,
- Host = cmd.Host,
- Port = 2135,
- Database = cmd.Database,
CredentialsProvider = saProvider,
LoggerFactory = loggerFactory,
ServerCertificates = YcCerts.GetYcServerCertificates()
@@ -24,6 +20,6 @@ await Parser.Default.ParseArguments(args).WithParsedAsync(async cmd
await using var ydbConnection = new YdbConnection(builder);
await ydbConnection.OpenAsync();
- Console.WriteLine(await new YdbCommand(ydbConnection) { CommandText = "SELECT 'Hello Dedicated YDB!'u" }
+ Console.WriteLine(await new YdbCommand(ydbConnection) { CommandText = "SELECT 'Hello YDB from Yandex Cloud!'u" }
.ExecuteScalarAsync());
});
\ No newline at end of file
diff --git a/examples/Ydb.Sdk.AdoNet.Yandex.Cloud/README.md b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud/README.md
new file mode 100644
index 00000000..78a69b38
--- /dev/null
+++ b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud/README.md
@@ -0,0 +1,9 @@
+# YDB Sdk ADO.NET to Yandex Cloud Example
+
+A sample application that checks connection settings and performs a simple select query on a YDB database hosted in Yandex Cloud.
+
+## Running
+
+```bash
+dotnet run --connectionString "UseTls=true;Host=;Port=2135;Database=" --saFilePath ""
+```
diff --git a/examples/src/YC/YC.csproj b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud/Ydb.Sdk.AdoNet.Yandex.Cloud.csproj
similarity index 83%
rename from examples/src/YC/YC.csproj
rename to examples/Ydb.Sdk.AdoNet.Yandex.Cloud/Ydb.Sdk.AdoNet.Yandex.Cloud.csproj
index 5e882a24..5702f8e1 100644
--- a/examples/src/YC/YC.csproj
+++ b/examples/Ydb.Sdk.AdoNet.Yandex.Cloud/Ydb.Sdk.AdoNet.Yandex.Cloud.csproj
@@ -5,7 +5,7 @@
net8.0
enable
enable
- YcCloud
+ Ydb.Sdk.AdoNet.Yandex.Cloud
@@ -16,6 +16,6 @@
-
+
diff --git a/examples/src/Common/DataUtils.cs b/examples/Ydb.Sdk.QueryService.QuickStart/DataUtils.cs
similarity index 99%
rename from examples/src/Common/DataUtils.cs
rename to examples/Ydb.Sdk.QueryService.QuickStart/DataUtils.cs
index 6cf9b191..b65a7967 100644
--- a/examples/src/Common/DataUtils.cs
+++ b/examples/Ydb.Sdk.QueryService.QuickStart/DataUtils.cs
@@ -1,6 +1,3 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
using Ydb.Sdk.Value;
namespace Ydb.Sdk.Examples;
diff --git a/examples/src/QueryExample/Program.cs b/examples/Ydb.Sdk.QueryService.QuickStart/Program.cs
similarity index 87%
rename from examples/src/QueryExample/Program.cs
rename to examples/Ydb.Sdk.QueryService.QuickStart/Program.cs
index 8e8d8b0e..7e036265 100644
--- a/examples/src/QueryExample/Program.cs
+++ b/examples/Ydb.Sdk.QueryService.QuickStart/Program.cs
@@ -39,10 +39,6 @@ private static async Task Run(CmdOptions cmdOptions)
await QueryExample.Run(
endpoint: cmdOptions.Endpoint,
database: cmdOptions.Database,
- credentialsProvider: await AuthUtils.MakeCredentialsFromEnv(
- fallbackAnonymous: cmdOptions.FallbackAnonymous,
- loggerFactory: loggerFactory),
- customServerCertificate: AuthUtils.GetCustomServerCertificate(),
path: cmdOptions.Path,
loggerFactory: loggerFactory
);
diff --git a/examples/src/QueryExample/QueryExample.cs b/examples/Ydb.Sdk.QueryService.QuickStart/QueryExample.cs
similarity index 96%
rename from examples/src/QueryExample/QueryExample.cs
rename to examples/Ydb.Sdk.QueryService.QuickStart/QueryExample.cs
index 1f66afa1..46e12400 100644
--- a/examples/src/QueryExample/QueryExample.cs
+++ b/examples/Ydb.Sdk.QueryService.QuickStart/QueryExample.cs
@@ -1,6 +1,4 @@
-using System.Security.Cryptography.X509Certificates;
using Microsoft.Extensions.Logging;
-using Ydb.Sdk.Auth;
using Ydb.Sdk.Services.Query;
using Ydb.Sdk.Value;
@@ -20,17 +18,10 @@ private QueryExample(QueryClient client, string database, string path)
public static async Task Run(
string endpoint,
string database,
- ICredentialsProvider? credentialsProvider,
- X509Certificate? customServerCertificate,
string path,
ILoggerFactory loggerFactory)
{
- var config = new DriverConfig(
- endpoint: endpoint,
- database: database,
- credentials: credentialsProvider,
- customServerCertificate: customServerCertificate
- );
+ var config = new DriverConfig(endpoint: endpoint, database: database);
await using var driver = await Driver.CreateInitialized(
config: config,
diff --git a/examples/src/QueryExample/QueryExample.csproj b/examples/Ydb.Sdk.QueryService.QuickStart/Ydb.Sdk.QueryService.QuickStart.csproj
similarity index 88%
rename from examples/src/QueryExample/QueryExample.csproj
rename to examples/Ydb.Sdk.QueryService.QuickStart/Ydb.Sdk.QueryService.QuickStart.csproj
index 6e487ba2..4e349d82 100644
--- a/examples/src/QueryExample/QueryExample.csproj
+++ b/examples/Ydb.Sdk.QueryService.QuickStart/Ydb.Sdk.QueryService.QuickStart.csproj
@@ -8,7 +8,7 @@
Ydb.Sdk.Examples.QueryExample
Ydb.Sdk.Examples
-
+
git
https://github.com/ydb-platform/ydb-dotnet-sdk
@@ -17,12 +17,11 @@
-
-
+
+
-
+
-
diff --git a/examples/src/Topic/Program.cs b/examples/Ydb.Sdk.Topic.QuickStart/Program.cs
similarity index 100%
rename from examples/src/Topic/Program.cs
rename to examples/Ydb.Sdk.Topic.QuickStart/Program.cs
diff --git a/examples/Ydb.Sdk.Topic.QuickStart/README.md b/examples/Ydb.Sdk.Topic.QuickStart/README.md
new file mode 100644
index 00000000..ae999750
--- /dev/null
+++ b/examples/Ydb.Sdk.Topic.QuickStart/README.md
@@ -0,0 +1,12 @@
+# YDB SDK Topic Quick Start
+
+This sample demonstrates how to produce and consume messages using the YDB Topic API in .NET.
+
+## Running QuickStart
+
+1. Set up a local YDB instance: [YDB local setup](https://ydb.tech/docs/en/reference/docker/start)
+
+2. Run the sample:
+ ```bash
+ dotnet run
+ ```
diff --git a/examples/src/Topic/Topic.csproj b/examples/Ydb.Sdk.Topic.QuickStart/Ydb.Sdk.Topic.QuickStart.csproj
similarity index 71%
rename from examples/src/Topic/Topic.csproj
rename to examples/Ydb.Sdk.Topic.QuickStart/Ydb.Sdk.Topic.QuickStart.csproj
index b6cf30e9..59de5261 100644
--- a/examples/src/Topic/Topic.csproj
+++ b/examples/Ydb.Sdk.Topic.QuickStart/Ydb.Sdk.Topic.QuickStart.csproj
@@ -5,13 +5,14 @@
net8.0
enable
enable
+ Ydb.Sdk.Topic.QuickStart
-
-
+
+
-
+
diff --git a/examples/src/YdbExamples.sln b/examples/YdbExamples.sln
similarity index 50%
rename from examples/src/YdbExamples.sln
rename to examples/YdbExamples.sln
index 3f99e3df..8966b920 100644
--- a/examples/src/YdbExamples.sln
+++ b/examples/YdbExamples.sln
@@ -3,38 +3,36 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31205.134
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common", "Common\Common.csproj", "{59F508A9-5EE0-4A6C-9580-89FC8C6CD4CE}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ydb.Sdk.QueryService.QuickStart", "Ydb.Sdk.QueryService.QuickStart\Ydb.Sdk.QueryService.QuickStart.csproj", "{0BA2CD4F-BF38-4C0D-878B-3D0C2C2970D9}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicExample", "BasicExample\BasicExample.csproj", "{9DAD5FF3-B7C2-4A9E-B4B2-A0FBD6097727}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ydb.Sdk.AdoNet.QuickStart", "Ydb.Sdk.AdoNet.QuickStart\Ydb.Sdk.AdoNet.QuickStart.csproj", "{5030F1BC-E974-46BB-9381-C4356E120D96}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QueryExample", "QueryExample\QueryExample.csproj", "{0BA2CD4F-BF38-4C0D-878B-3D0C2C2970D9}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ydb.Sdk.AdoNet.Dapper.QuickStart", "Ydb.Sdk.AdoNet.Dapper.QuickStart\Ydb.Sdk.AdoNet.Dapper.QuickStart.csproj", "{AC8F1B10-31EB-4A29-BF35-7F49B06E1FA8}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdoNet", "AdoNet\AdoNet.csproj", "{5030F1BC-E974-46BB-9381-C4356E120D96}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ydb.Sdk.AdoNet.Yandex.Cloud", "Ydb.Sdk.AdoNet.Yandex.Cloud\Ydb.Sdk.AdoNet.Yandex.Cloud.csproj", "{753E4F33-CB08-47B9-864F-4CC037B278C4}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DapperExample", "DapperExample\DapperExample.csproj", "{AC8F1B10-31EB-4A29-BF35-7F49B06E1FA8}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YC", "YC\YC.csproj", "{753E4F33-CB08-47B9-864F-4CC037B278C4}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Topic", "Topic\Topic.csproj", "{0FB9A1C2-4B0C-4AE4-9FA2-E0ED37802A6E}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ydb.Sdk.Topic.QuickStart", "Ydb.Sdk.Topic.QuickStart\Ydb.Sdk.Topic.QuickStart.csproj", "{0FB9A1C2-4B0C-4AE4-9FA2-E0ED37802A6E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFrameworkCore.Ydb.QuickStart", "EntityFrameworkCore.Ydb.QuickStart\EntityFrameworkCore.Ydb.QuickStart.csproj", "{0CE9DF93-1411-4E73-BA88-A66018FAB948}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFrameworkCore.Ydb.Yandex.Cloud", "EntityFrameworkCore.Ydb.Yandex.Cloud\EntityFrameworkCore.Ydb.Yandex.Cloud.csproj", "{8F7266C7-75BB-4753-9FB2-BDF4678AF73B}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddEntity.Sample", "EntityFrameworkCore.Ydb.Samples\AddEntity.Sample\AddEntity.Sample.csproj", "{CFEC4D14-902F-4E27-9F6C-8E150AE00009}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Schema.OneToMany", "EntityFrameworkCore.Ydb.Samples\Schema.OneToMany\Schema.OneToMany.csproj", "{5D8A1318-FD60-4BDD-9DB3-BF050CCC9755}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Schema.OneToOne", "EntityFrameworkCore.Ydb.Samples\Schema.OneToOne\Schema.OneToOne.csproj", "{DBCEC1B1-FD84-4F9B-84B9-7BDA749C6DF2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Schema.ManyToMany", "EntityFrameworkCore.Ydb.Samples\Schema.ManyToMany\Schema.ManyToMany.csproj", "{08439995-062A-497A-9130-0F6429B0219E}"
+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
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {59F508A9-5EE0-4A6C-9580-89FC8C6CD4CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {59F508A9-5EE0-4A6C-9580-89FC8C6CD4CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {59F508A9-5EE0-4A6C-9580-89FC8C6CD4CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {59F508A9-5EE0-4A6C-9580-89FC8C6CD4CE}.Release|Any CPU.Build.0 = Release|Any CPU
- {9DAD5FF3-B7C2-4A9E-B4B2-A0FBD6097727}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {9DAD5FF3-B7C2-4A9E-B4B2-A0FBD6097727}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {9DAD5FF3-B7C2-4A9E-B4B2-A0FBD6097727}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {9DAD5FF3-B7C2-4A9E-B4B2-A0FBD6097727}.Release|Any CPU.Build.0 = Release|Any CPU
{0BA2CD4F-BF38-4C0D-878B-3D0C2C2970D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0BA2CD4F-BF38-4C0D-878B-3D0C2C2970D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0BA2CD4F-BF38-4C0D-878B-3D0C2C2970D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -63,6 +61,26 @@ Global
{8F7266C7-75BB-4753-9FB2-BDF4678AF73B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8F7266C7-75BB-4753-9FB2-BDF4678AF73B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8F7266C7-75BB-4753-9FB2-BDF4678AF73B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CFEC4D14-902F-4E27-9F6C-8E150AE00009}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CFEC4D14-902F-4E27-9F6C-8E150AE00009}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CFEC4D14-902F-4E27-9F6C-8E150AE00009}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CFEC4D14-902F-4E27-9F6C-8E150AE00009}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5D8A1318-FD60-4BDD-9DB3-BF050CCC9755}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5D8A1318-FD60-4BDD-9DB3-BF050CCC9755}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5D8A1318-FD60-4BDD-9DB3-BF050CCC9755}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5D8A1318-FD60-4BDD-9DB3-BF050CCC9755}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DBCEC1B1-FD84-4F9B-84B9-7BDA749C6DF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DBCEC1B1-FD84-4F9B-84B9-7BDA749C6DF2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DBCEC1B1-FD84-4F9B-84B9-7BDA749C6DF2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DBCEC1B1-FD84-4F9B-84B9-7BDA749C6DF2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {08439995-062A-497A-9130-0F6429B0219E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {08439995-062A-497A-9130-0F6429B0219E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {08439995-062A-497A-9130-0F6429B0219E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {08439995-062A-497A-9130-0F6429B0219E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B2B0786F-7545-4717-8D04-26DF9C181607}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/examples/src/YdbExamples.sln.DotSettings b/examples/YdbExamples.sln.DotSettings
similarity index 100%
rename from examples/src/YdbExamples.sln.DotSettings
rename to examples/YdbExamples.sln.DotSettings
diff --git a/examples/src/BasicExample/BasicExample.cs b/examples/src/BasicExample/BasicExample.cs
deleted file mode 100644
index 494a2369..00000000
--- a/examples/src/BasicExample/BasicExample.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-using System.Security.Cryptography.X509Certificates;
-using Microsoft.Extensions.Logging;
-using Ydb.Sdk.Auth;
-using Ydb.Sdk.Services.Table;
-
-namespace Ydb.Sdk.Examples;
-
-internal partial class BasicExample : TableExampleBase
-{
- private BasicExample(TableClient client, string database, string path)
- : base(client, database, path)
- {
- }
-
- public static async Task Run(
- string endpoint,
- string database,
- ICredentialsProvider? credentialsProvider,
- X509Certificate? customServerCertificate,
- string path,
- ILoggerFactory loggerFactory)
- {
- var config = new DriverConfig(
- endpoint: endpoint,
- database: database,
- credentials: credentialsProvider,
- customServerCertificate: customServerCertificate
- );
-
- await using var driver = await Driver.CreateInitialized(
- config: config,
- loggerFactory: loggerFactory
- );
-
- using var tableClient = new TableClient(driver, new TableClientConfig());
-
- var example = new BasicExample(tableClient, database, path);
-
- await example.SchemeQuery();
- await example.FillData();
- await example.SimpleSelect(1);
- await example.SimpleUpsert(10, "Coming soon", DateTime.UtcNow);
- await example.SimpleSelect(10);
- await example.InteractiveTx();
- await example.ReadTable();
- await example.ScanQuery(DateTime.Parse("2007-01-01"));
- }
-
- private static ExecuteDataQuerySettings DefaultDataQuerySettings =>
- new()
- {
- // Indicates that client is no longer interested in the result of operation after the
- // specified duration starting from the moment when operation arrives at the server.
- // Status code TIMEOUT will be returned from server in case when operation result in
- // not available in the specified time period. This status code doesn't indicate the result
- // of operation, it might be completed or cancelled.
- OperationTimeout = TimeSpan.FromSeconds(1),
-
- // Transport timeout from the moment operation was sent to server. It is useful in case
- // of possible network issues, to that query doesn't hang forever.
- // It is recommended to set this value to a larger value than OperationTimeout to give
- // server some time to issue a response.
- TransportTimeout = TimeSpan.FromSeconds(5),
-
- // Keep query compilation result in query cache or not. Should be false for ad-hoc queries,
- // and true (default) for high-RPS queries.
- KeepInQueryCache = false
- };
-
- private ExecuteDataQuerySettings DefaultCachedDataQuerySettings
- {
- get
- {
- var settings = DefaultDataQuerySettings;
- settings.KeepInQueryCache = true;
- return settings;
- }
- }
-}
\ No newline at end of file
diff --git a/examples/src/BasicExample/BasicExample.csproj b/examples/src/BasicExample/BasicExample.csproj
deleted file mode 100644
index 912bc598..00000000
--- a/examples/src/BasicExample/BasicExample.csproj
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- Exe
- net6.0
- enable
- enable
- Ydb.Sdk.Examples.BasicExample
- Ydb.Sdk.Examples
-
-
-
- git
- https://github.com/ydb-platform/ydb-dotnet-sdk
- https://github.com/ydb-platform/ydb-dotnet-sdk
- YANDEX LLC
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/examples/src/BasicExample/DataQuery.cs b/examples/src/BasicExample/DataQuery.cs
deleted file mode 100644
index 4f5d1248..00000000
--- a/examples/src/BasicExample/DataQuery.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-using Ydb.Sdk.Services.Table;
-using Ydb.Sdk.Value;
-
-namespace Ydb.Sdk.Examples;
-
-internal partial class BasicExample
-{
- private async Task SimpleSelect(ulong id)
- {
- var response = await Client.SessionExec(async session =>
- {
- var query = @$"
- PRAGMA TablePathPrefix('{BasePath}');
-
- DECLARE $id AS Uint64;
-
- SELECT
- series_id,
- title,
- release_date
- FROM series
- WHERE series_id = $id;
- ";
-
- return await session.ExecuteDataQuery(
- query: query,
- txControl: TxControl.BeginSerializableRW().Commit(),
- parameters: new Dictionary
- {
- { "$id", YdbValue.MakeUint64(id) }
- },
- settings: DefaultCachedDataQuerySettings
- );
- });
-
- response.Status.EnsureSuccess();
-
- var queryResponse = (ExecuteDataQueryResponse)response;
- var resultSet = queryResponse.Result.ResultSets[0];
-
- Console.WriteLine($"> SimpleSelect, " +
- $"columns: {resultSet.Columns.Count}, " +
- $"rows: {resultSet.Rows.Count}, " +
- $"truncated: {resultSet.Truncated}");
-
- foreach (var row in resultSet.Rows)
- {
- Console.WriteLine($"> Series, " +
- $"series_id: {(ulong?)row["series_id"]}, " +
- $"title: {(string?)row["title"]}, " +
- $"release_date: {(DateTime?)row["release_date"]}");
- }
- }
-
- private async Task SimpleUpsert(ulong id, string title, DateTime date)
- {
- var response = await Client.SessionExec(async session =>
- {
- var query = @$"
- PRAGMA TablePathPrefix('{BasePath}');
-
- DECLARE $id AS Uint64;
- DECLARE $title AS Utf8;
- DECLARE $release_date AS Date;
-
- UPSERT INTO series (series_id, title, release_date) VALUES
- ($id, $title, $release_date);
- ";
-
- return await session.ExecuteDataQuery(
- query: query,
- txControl: TxControl.BeginSerializableRW().Commit(),
- parameters: new Dictionary
- {
- { "$id", YdbValue.MakeUint64(id) },
- { "$title", YdbValue.MakeUtf8(title) },
- { "$release_date", YdbValue.MakeDate(date) }
- },
- settings: DefaultCachedDataQuerySettings
- );
- });
-
- response.Status.EnsureSuccess();
- }
-}
\ No newline at end of file
diff --git a/examples/src/BasicExample/FillData.cs b/examples/src/BasicExample/FillData.cs
deleted file mode 100644
index 48e6d4c8..00000000
--- a/examples/src/BasicExample/FillData.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-using Ydb.Sdk.Services.Table;
-
-namespace Ydb.Sdk.Examples;
-
-internal partial class BasicExample
-{
- // Fill sample tables with initial data.
- private async Task FillData()
- {
- var response = await Client.SessionExec(async session =>
- {
- var query = @$"
- PRAGMA TablePathPrefix('{BasePath}');
-
- DECLARE $seriesData AS List>;
-
- DECLARE $seasonsData AS List>;
-
- DECLARE $episodesData AS List>;
-
- REPLACE INTO series
- SELECT * FROM AS_TABLE($seriesData);
-
- REPLACE INTO seasons
- SELECT * FROM AS_TABLE($seasonsData);
-
- REPLACE INTO episodes
- SELECT * FROM AS_TABLE($episodesData);
- ";
-
- return await session.ExecuteDataQuery(
- query: query,
- txControl: TxControl.BeginSerializableRW().Commit(),
- parameters: DataUtils.GetDataParams(),
- settings: DefaultDataQuerySettings
- );
- });
-
- response.Status.EnsureSuccess();
- }
-}
\ No newline at end of file
diff --git a/examples/src/BasicExample/InteractiveTx.cs b/examples/src/BasicExample/InteractiveTx.cs
deleted file mode 100644
index e49390bc..00000000
--- a/examples/src/BasicExample/InteractiveTx.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-using Ydb.Sdk.Services.Table;
-using Ydb.Sdk.Value;
-
-namespace Ydb.Sdk.Examples;
-
-internal partial class BasicExample
-{
- private async Task InteractiveTx()
- {
- var execResponse = await Client.SessionExec(async session =>
- {
- var query1 = @$"
- PRAGMA TablePathPrefix('{BasePath}');
-
- DECLARE $series_id AS Uint64;
- DECLARE $season_id AS Uint64;
-
- SELECT first_aired FROM seasons
- WHERE series_id = $series_id AND season_id = $season_id;
- ";
-
- // Execute first query (no transaction commit)
- var response = await session.ExecuteDataQuery(
- query: query1,
- txControl: TxControl.BeginSerializableRW(),
- parameters: new Dictionary
- {
- { "$series_id", YdbValue.MakeUint64(1) },
- { "$season_id", YdbValue.MakeUint64(3) }
- },
- settings: DefaultCachedDataQuerySettings
- );
-
- if (!response.Status.IsSuccess || response.Tx is null)
- {
- return response;
- }
-
- // Perform some client logic
- var firstAired = (DateTime?)response.Result.ResultSets[0].Rows[0]["first_aired"];
- var newAired = firstAired!.Value.AddDays(2);
-
- var query2 = @$"
- PRAGMA TablePathPrefix('{BasePath}');
-
- DECLARE $series_id AS Uint64;
- DECLARE $season_id AS Uint64;
- DECLARE $air_date AS Date;
-
- UPSERT INTO seasons (series_id, season_id, first_aired) VALUES
- ($series_id, $season_id, $air_date);
- ";
-
- // Execute second query and commit transaction.
- response = await session.ExecuteDataQuery(
- query: query2,
- TxControl.Tx(response.Tx).Commit(),
- parameters: new Dictionary
- {
- { "$series_id", YdbValue.MakeUint64(1) },
- { "$season_id", YdbValue.MakeUint64(3) },
- { "$air_date", YdbValue.MakeDate(newAired) }
- },
- settings: DefaultCachedDataQuerySettings
- );
-
- return response;
- });
-
- execResponse.Status.EnsureSuccess();
- }
-}
\ No newline at end of file
diff --git a/examples/src/BasicExample/Program.cs b/examples/src/BasicExample/Program.cs
deleted file mode 100644
index 2c5895a1..00000000
--- a/examples/src/BasicExample/Program.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using CommandLine;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Logging.Abstractions;
-
-namespace Ydb.Sdk.Examples;
-
-internal class CmdOptions
-{
- [Option('e', "endpoint", Required = true, HelpText = "Database endpoint")]
- public string Endpoint { get; set; } = "";
-
- [Option('d', "database", Required = true, HelpText = "Database name")]
- public string Database { get; set; } = "";
-
- [Option('p', "path", HelpText = "Base path for tables")]
- public string Path { get; set; } = "ydb-dotnet-basic";
-
- [Option("anonymous", Required = false, HelpText = "Fallback anonymous")]
- public bool FallbackAnonymous { get; set; } = false;
-}
-
-internal static class Program
-{
- private static ServiceProvider GetServiceProvider() => new ServiceCollection()
- .AddLogging(configure => configure.AddConsole().SetMinimumLevel(LogLevel.Information))
- .BuildServiceProvider();
-
- private static async Task Run(CmdOptions cmdOptions)
- {
- await using var serviceProvider = GetServiceProvider();
- var loggerFactory = serviceProvider.GetService();
-
- loggerFactory ??= NullLoggerFactory.Instance;
-
- await BasicExample.Run(
- endpoint: cmdOptions.Endpoint,
- database: cmdOptions.Database,
- credentialsProvider: await AuthUtils.MakeCredentialsFromEnv(
- fallbackAnonymous: cmdOptions.FallbackAnonymous,
- loggerFactory: loggerFactory),
- customServerCertificate: AuthUtils.GetCustomServerCertificate(),
- path: cmdOptions.Path,
- loggerFactory: loggerFactory
- );
- }
-
- private static async Task Main(string[] args)
- {
- AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
-
- await Parser.Default.ParseArguments(args).WithParsedAsync(Run);
- }
-}
\ No newline at end of file
diff --git a/examples/src/BasicExample/ReadTable.cs b/examples/src/BasicExample/ReadTable.cs
deleted file mode 100644
index 7433db5b..00000000
--- a/examples/src/BasicExample/ReadTable.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using Ydb.Sdk.Services.Table;
-
-namespace Ydb.Sdk.Examples;
-
-internal partial class BasicExample
-{
- private async Task ReadTable()
- {
- var readStream = await Client.ReadTable(
- FullTablePath("seasons"),
- new ReadTableSettings
- {
- Columns = new List { "series_id", "season_id", "first_aired" },
- RowLimit = 5,
- Ordered = true
- });
-
- while (await readStream.Next())
- {
- readStream.Response.EnsureSuccess();
- var resultSet = readStream.Response.Result.ResultSet;
-
- foreach (var row in resultSet.Rows)
- {
- Console.WriteLine($"> ReadTable seasons, " +
- $"series_id: {(ulong?)row["series_id"]}, " +
- $"season_id: {(ulong?)row["season_id"]}, " +
- $"first_aired: {(DateTime?)row["first_aired"]}");
- }
- }
- }
-}
\ No newline at end of file
diff --git a/examples/src/BasicExample/ScanQuery.cs b/examples/src/BasicExample/ScanQuery.cs
deleted file mode 100644
index 4260bf6f..00000000
--- a/examples/src/BasicExample/ScanQuery.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using Ydb.Sdk.Value;
-
-namespace Ydb.Sdk.Examples;
-
-internal partial class BasicExample
-{
- private async Task ScanQuery(DateTime airFrom)
- {
- var query = @$"
- PRAGMA TablePathPrefix('{BasePath}');
-
- DECLARE $air_from AS Date;
-
- SELECT series_id, season_id, COUNT(*) AS episodes_count
- FROM episodes
- WHERE air_date >= $air_from
- GROUP BY series_id, season_id
- ORDER BY series_id, season_id;
- ";
-
- var scanStream = await Client.ExecuteScanQuery(
- query,
- new Dictionary
- {
- { "$air_from", YdbValue.MakeDate(airFrom) }
- });
-
- while (await scanStream.Next())
- {
- scanStream.Response.EnsureSuccess();
-
- var resultSet = scanStream.Response.Result.ResultSetPart;
- if (resultSet != null)
- {
- foreach (var row in resultSet.Rows)
- {
- Console.WriteLine($"> ScanQuery, " +
- $"series_id: {(ulong?)row["series_id"]}, " +
- $"season_id: {(ulong?)row["season_id"]}, " +
- $"episodes_count: {(ulong)row["episodes_count"]}");
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/examples/src/BasicExample/SchemeQuery.cs b/examples/src/BasicExample/SchemeQuery.cs
deleted file mode 100644
index 24bbaa23..00000000
--- a/examples/src/BasicExample/SchemeQuery.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-namespace Ydb.Sdk.Examples;
-
-internal partial class BasicExample
-{
- // Execute Scheme (DDL) query to create sample tables.
- private async Task SchemeQuery()
- {
- var response = await Client.SessionExec(async session =>
- await session.ExecuteSchemeQuery(@$"
- PRAGMA TablePathPrefix('{BasePath}');
-
- CREATE TABLE series (
- series_id Uint64,
- title Utf8,
- series_info Utf8,
- release_date Date,
- PRIMARY KEY (series_id)
- );
-
- CREATE TABLE seasons (
- series_id Uint64,
- season_id Uint64,
- title Utf8,
- first_aired Date,
- last_aired Date,
- PRIMARY KEY (series_id, season_id)
- );
-
- CREATE TABLE episodes (
- series_id Uint64,
- season_id Uint64,
- episode_id Uint64,
- title Utf8,
- air_date Date,
- PRIMARY KEY (series_id, season_id, episode_id)
- );
- "));
-
- response.Status.EnsureSuccess();
- }
-}
\ No newline at end of file
diff --git a/examples/src/Common/AuthUtils.cs b/examples/src/Common/AuthUtils.cs
deleted file mode 100644
index fd976e2d..00000000
--- a/examples/src/Common/AuthUtils.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using System;
-using System.Security.Cryptography.X509Certificates;
-using System.Threading.Tasks;
-using Microsoft.Extensions.Logging;
-using Ydb.Sdk.Auth;
-using Ydb.Sdk.Yc;
-
-namespace Ydb.Sdk.Examples;
-
-public static class AuthUtils
-{
- public static async Task MakeCredentialsFromEnv(
- bool fallbackAnonymous = false,
- ILoggerFactory? loggerFactory = null)
- {
- var saFileValue = Environment.GetEnvironmentVariable("YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS");
- if (!string.IsNullOrEmpty(saFileValue))
- {
- var saProvider = new ServiceAccountProvider(
- saFilePath: saFileValue,
- loggerFactory: loggerFactory);
- await saProvider.Initialize();
- return saProvider;
- }
-
- var anonymousValue = Environment.GetEnvironmentVariable("YDB_ANONYMOUS_CREDENTIALS");
- if (anonymousValue != null && IsTrueValue(anonymousValue))
- {
- return null;
- }
-
- var metadataValue = Environment.GetEnvironmentVariable("YDB_METADATA_CREDENTIALS");
- if (metadataValue != null && IsTrueValue(metadataValue))
- {
- var metadataProvider = new MetadataProvider(
- loggerFactory: loggerFactory);
- await metadataProvider.Initialize();
- return metadataProvider;
- }
-
- var tokenValue = Environment.GetEnvironmentVariable("YDB_ACCESS_TOKEN_CREDENTIALS");
- if (!string.IsNullOrEmpty(tokenValue))
- {
- return new TokenProvider(tokenValue);
- }
-
- if (fallbackAnonymous)
- {
- return null;
- }
-
- throw new InvalidOperationException("Failed to parse credentials from environmet, no valid options found.");
- }
-
- public static X509Certificate GetCustomServerCertificate() => YcCerts.GetDefaultServerCertificate();
-
- private static bool IsTrueValue(string value) =>
- value == "1" ||
- value.ToLower() == "yes" ||
- value.ToLower() == "true";
-}
\ No newline at end of file
diff --git a/examples/src/Common/Common.csproj b/examples/src/Common/Common.csproj
deleted file mode 100644
index a7cdb16c..00000000
--- a/examples/src/Common/Common.csproj
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
- net6.0
- Ydb.Sdk.Examples.Common
- Ydb.Sdk.Examples
- enable
-
-
-
- git
- https://github.com/ydb-platform/ydb-dotnet-sdk
- https://github.com/ydb-platform/ydb-dotnet-sdk
- YANDEX LLC
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/examples/src/Common/TableExampleBase.cs b/examples/src/Common/TableExampleBase.cs
deleted file mode 100644
index 168f8f51..00000000
--- a/examples/src/Common/TableExampleBase.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using Ydb.Sdk.Services.Table;
-
-namespace Ydb.Sdk.Examples;
-
-public class TableExampleBase
-{
- protected TableClient Client { get; }
- protected string BasePath { get; }
-
- protected TableExampleBase(TableClient client, string database, string path)
- {
- Client = client;
- BasePath = string.Join('/', database, path);
- }
-
- protected string FullTablePath(string table) => string.Join('/', BasePath, table);
-}
\ No newline at end of file
diff --git a/examples/src/YC/CmdOptions.cs b/examples/src/YC/CmdOptions.cs
deleted file mode 100644
index 0c6f3b11..00000000
--- a/examples/src/YC/CmdOptions.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using CommandLine;
-
-namespace YcCloud;
-
-internal class CmdOptions
-{
- [Option('h', "host", Required = true, HelpText = "Database host")]
- public string Host { get; set; } = null!;
-
- [Option('d', "database", Required = true, HelpText = "Database name")]
- public string Database { get; set; } = null!;
-
- [Option("saFilePath", Required = true, HelpText = "Sa Key")]
- public string SaFilePath { get; set; } = null!;
-}
\ No newline at end of file
diff --git a/src/Ydb.Sdk/README.md b/src/Ydb.Sdk/README.md
index b979a78e..6c40bfd7 100644
--- a/src/Ydb.Sdk/README.md
+++ b/src/Ydb.Sdk/README.md
@@ -59,7 +59,7 @@ while (await ydbDataReader.ReadAsync())
## More examples
-- [AdoNet simple guide](./../../examples/src/AdoNet)
-- [AdoNet connect to Yandex Cloud](./../../examples/src/YC)
-- [Dapper example](./../../examples/src/DapperExample)
-- [Topic client](./../../examples/src/Topic)
+- [AdoNet simple guide](./../../examples/Ydb.Sdk.AdoNet.QuickStart)
+- [AdoNet connect to Yandex Cloud](./../../examples/Ydb.Sdk.AdoNet.Yandex.Cloud)
+- [Dapper example](./../../examples/Ydb.Sdk.AdoNet.Dapper.QuickStart)
+- [Topic client](./../../examples/Ydb.Sdk.Topic.QuickStart)