Skip to content

Commit ffb46e7

Browse files
tmp
1 parent b90a726 commit ffb46e7

21 files changed

Lines changed: 660 additions & 15 deletions

.env

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ POSTGRES_CONNECTION_STRING="host=localhost;database=tests;username=postgres;pass
55
POSTGRES_USER="postgres"
66
POSTGRES_PASSWORD="pass"
77
TESTS_DB="tests"
8-
SQLITE_CONNECTION_STRING="Data Source=tests.db;Mode=ReadWriteCreate"
8+
SQLITE_CONNECTION_STRING="Data Source=tests.db;Mode=ReadWriteCreate"
9+
POSTGRES_SCHEMA_FILES=postgres/schema.sql
10+
MYSQL_SCHEMA_FILES=mysql/schema.sql

benchmark/.env

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
POSTGRES_SCHEMA_FILES=postgres/schema.sql
2+
MYSQL_SCHEMA_FILES=mysql/schema.sql
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<ProjectReference Include="..\postgres\SqlcImpl\SqlcImpl.csproj" />
12+
<ProjectReference Include="..\postgres\EFCoreImpl\EFCoreImpl.csproj" />
13+
</ItemGroup>
14+
</Project>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using PostgresEFCoreImpl;
2+
using PostgresSqlcImpl;
3+
using System.Diagnostics;
4+
5+
public class PostgresRunner
6+
{
7+
public PostgresRunner()
8+
{
9+
SqlcImpl = new QuerySql();
10+
EFCoreImpl = new Queries(new SalesDbContext());
11+
}
12+
13+
public QuerySql SqlcImpl { get; }
14+
15+
public Queries EFCoreImpl { get; }
16+
17+
public void TimeSqlcImpl()
18+
{
19+
var stopwatch = new Stopwatch();
20+
stopwatch.Start();
21+
// SqlcImpl.GetCustomerOrders(new GetCustomerOrdersArgs(1, 0, 10));
22+
stopwatch.Stop();
23+
Console.WriteLine($"SqlcImpl: {stopwatch.ElapsedMilliseconds}ms");
24+
}
25+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using PostgresSqlcImpl;
2+
3+
public class Program
4+
{
5+
public static void Main(string[] args)
6+
{
7+
var postgresRunner = new PostgresRunner();
8+
postgresRunner.Run();
9+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<RootNamespace>PostgresEFCoreImpl</RootNamespace>
6+
<OutputType>Library</OutputType>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
11+
<ItemGroup>
12+
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
13+
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.0" />
14+
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0" />
15+
</ItemGroup>
16+
17+
</Project>
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel.DataAnnotations;
4+
using System.ComponentModel.DataAnnotations.Schema;
5+
6+
namespace PostgresEFCoreImpl;
7+
8+
[Table("customers", Schema = "sales")]
9+
public class Customer
10+
{
11+
[Key]
12+
[Column("customer_id")]
13+
public int CustomerId { get; set; }
14+
15+
[Required]
16+
[Column("name")]
17+
[MaxLength(100)]
18+
public string Name { get; set; } = string.Empty;
19+
20+
[Required]
21+
[Column("email")]
22+
[MaxLength(255)]
23+
public string Email { get; set; } = string.Empty;
24+
25+
[Required]
26+
[Column("phone")]
27+
[MaxLength(50)]
28+
public string Phone { get; set; } = string.Empty;
29+
30+
[Column("address")]
31+
[MaxLength(255)]
32+
public string? Address { get; set; }
33+
34+
[Required]
35+
[Column("registered_at")]
36+
public DateTime RegisteredAt { get; set; }
37+
38+
public ICollection<Order> Orders { get; set; } = new List<Order>();
39+
}
40+
41+
[Table("products", Schema = "sales")]
42+
public class Product
43+
{
44+
[Key]
45+
[Column("product_id")]
46+
public int ProductId { get; set; }
47+
48+
[Required]
49+
[Column("name")]
50+
[MaxLength(200)]
51+
public string Name { get; set; } = string.Empty;
52+
53+
[Required]
54+
[Column("category")]
55+
[MaxLength(100)]
56+
public string Category { get; set; } = string.Empty;
57+
58+
[Required]
59+
[Column("unit_price", TypeName = "decimal(10,2)")]
60+
public decimal UnitPrice { get; set; }
61+
62+
[Required]
63+
[Column("stock_quantity")]
64+
public int StockQuantity { get; set; }
65+
66+
[Column("description")]
67+
public string? Description { get; set; }
68+
69+
[Required]
70+
[Column("added_at")]
71+
public DateTime AddedAt { get; set; }
72+
73+
public ICollection<OrderItem> OrderItems { get; set; } = new List<OrderItem>();
74+
}
75+
76+
[Table("orders", Schema = "sales")]
77+
public class Order
78+
{
79+
[Key]
80+
[Column("order_id")]
81+
public Guid OrderId { get; set; }
82+
83+
[Required]
84+
[Column("customer_id")]
85+
public int CustomerId { get; set; }
86+
87+
[Required]
88+
[Column("ordered_at")]
89+
public DateTime OrderedAt { get; set; }
90+
91+
[Required]
92+
[Column("order_state")]
93+
[MaxLength(10)]
94+
public string OrderState { get; set; } = string.Empty;
95+
96+
[Required]
97+
[Column("total_amount", TypeName = "decimal(10,2)")]
98+
public decimal TotalAmount { get; set; }
99+
100+
[ForeignKey(nameof(CustomerId))]
101+
public Customer Customer { get; set; } = null!;
102+
103+
public ICollection<OrderItem> OrderItems { get; set; } = new List<OrderItem>();
104+
}
105+
106+
[Table("order_items", Schema = "sales")]
107+
public class OrderItem
108+
{
109+
[Key]
110+
[Column("order_item_id")]
111+
public Guid OrderItemId { get; set; }
112+
113+
[Required]
114+
[Column("order_id")]
115+
public Guid OrderId { get; set; }
116+
117+
[Required]
118+
[Column("product_id")]
119+
public int ProductId { get; set; }
120+
121+
[Required]
122+
[Column("quantity")]
123+
public int Quantity { get; set; }
124+
125+
[Required]
126+
[Column("unit_price", TypeName = "decimal(10,2)")]
127+
public decimal UnitPrice { get; set; }
128+
129+
[ForeignKey(nameof(OrderId))]
130+
public Order Order { get; set; } = null!;
131+
132+
[ForeignKey(nameof(ProductId))]
133+
public Product Product { get; set; } = null!;
134+
}
135+
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Threading.Tasks;
5+
using Microsoft.EntityFrameworkCore;
6+
7+
namespace PostgresEFCoreImpl;
8+
9+
public class Queries
10+
{
11+
private readonly SalesDbContext _dbContext;
12+
13+
public Queries(SalesDbContext dbContext)
14+
{
15+
_dbContext = dbContext;
16+
}
17+
18+
public DbContext DbContext => _dbContext;
19+
20+
// Result type for GetCustomerOrders matching SqlC output
21+
public record GetCustomerOrdersRow(
22+
Guid OrderId,
23+
DateTime OrderedAt,
24+
string OrderState,
25+
decimal TotalAmount,
26+
Guid OrderItemId,
27+
int Quantity,
28+
decimal UnitPrice,
29+
int ProductId,
30+
string ProductName,
31+
string ProductCategory
32+
);
33+
34+
public record GetCustomerOrdersArgs(int CustomerId, int Offset, int Limit);
35+
36+
/// <summary>
37+
/// Get customer orders with all order items and product details, ordered by date descending with pagination
38+
/// </summary>
39+
public async Task<List<GetCustomerOrdersRow>> GetCustomerOrders(GetCustomerOrdersArgs args)
40+
{
41+
var results = await _dbContext.Orders
42+
.Where(o => o.CustomerId == args.CustomerId)
43+
.OrderByDescending(o => o.OrderedAt)
44+
.Skip(args.Offset)
45+
.Take(args.Limit)
46+
.SelectMany(o => o.OrderItems.Select(i => new
47+
{
48+
Order = o,
49+
OrderItem = i,
50+
Product = i.Product
51+
}))
52+
.Select(x => new GetCustomerOrdersRow(
53+
x.Order.OrderId,
54+
x.Order.OrderedAt,
55+
x.Order.OrderState,
56+
x.Order.TotalAmount,
57+
x.OrderItem.OrderItemId,
58+
x.OrderItem.Quantity,
59+
x.OrderItem.UnitPrice,
60+
x.Product.ProductId,
61+
x.Product.Name,
62+
x.Product.Category
63+
))
64+
.ToListAsync();
65+
66+
return results;
67+
}
68+
69+
public record AddProductsArgs(string Name, string Category, decimal UnitPrice, int StockQuantity, string? Description);
70+
71+
/// <summary>
72+
/// Bulk insert products
73+
/// </summary>
74+
public async Task AddProducts(List<AddProductsArgs> args)
75+
{
76+
var products = args.Select(a => new Product
77+
{
78+
Name = a.Name,
79+
Category = a.Category,
80+
UnitPrice = a.UnitPrice,
81+
StockQuantity = a.StockQuantity,
82+
Description = a.Description,
83+
AddedAt = DateTime.UtcNow
84+
}).ToList();
85+
86+
await _dbContext.Products.AddRangeAsync(products);
87+
await _dbContext.SaveChangesAsync();
88+
}
89+
90+
public record AddOrdersArgs(int CustomerId, string OrderState, decimal TotalAmount);
91+
92+
/// <summary>
93+
/// Bulk insert orders
94+
/// </summary>
95+
public async Task AddOrders(List<AddOrdersArgs> args)
96+
{
97+
var orders = args.Select(a => new Order
98+
{
99+
OrderId = Guid.NewGuid(),
100+
CustomerId = a.CustomerId,
101+
OrderState = a.OrderState,
102+
TotalAmount = a.TotalAmount,
103+
OrderedAt = DateTime.UtcNow
104+
}).ToList();
105+
106+
await _dbContext.Orders.AddRangeAsync(orders);
107+
await _dbContext.SaveChangesAsync();
108+
}
109+
110+
public record AddOrderItemsArgs(Guid OrderId, int ProductId, int Quantity, decimal UnitPrice);
111+
112+
/// <summary>
113+
/// Bulk insert order items
114+
/// </summary>
115+
public async Task AddOrderItems(List<AddOrderItemsArgs> args)
116+
{
117+
var orderItems = args.Select(a => new OrderItem
118+
{
119+
OrderItemId = Guid.NewGuid(),
120+
OrderId = a.OrderId,
121+
ProductId = a.ProductId,
122+
Quantity = a.Quantity,
123+
UnitPrice = a.UnitPrice
124+
}).ToList();
125+
126+
await _dbContext.OrderItems.AddRangeAsync(orderItems);
127+
await _dbContext.SaveChangesAsync();
128+
}
129+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using Microsoft.EntityFrameworkCore;
2+
3+
namespace PostgresEFCoreImpl;
4+
5+
public class SalesDbContext : DbContext
6+
{
7+
public DbSet<Customer> Customers { get; set; } = null!;
8+
public DbSet<Product> Products { get; set; } = null!;
9+
public DbSet<Order> Orders { get; set; } = null!;
10+
public DbSet<OrderItem> OrderItems { get; set; } = null!;
11+
12+
protected override void OnModelCreating(ModelBuilder modelBuilder)
13+
{
14+
base.OnModelCreating(modelBuilder);
15+
}
16+
}
17+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// auto-generated by sqlc - do not edit
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
6+
namespace PostgresSqlcImpl;
7+
public readonly record struct SalesCustomer(int CustomerId, string Name, string Email, string Phone, string? Address, DateTime RegisteredAt);
8+
public readonly record struct SalesProduct(int ProductId, string Name, string Category, decimal UnitPrice, int StockQuantity, string? Description, DateTime AddedAt);
9+
public readonly record struct SalesOrder(Guid OrderId, int CustomerId, DateTime OrderedAt, string OrderState, decimal TotalAmount);
10+
public readonly record struct SalesOrderItem(Guid OrderItemId, Guid OrderId, int ProductId, int Quantity, decimal UnitPrice);

0 commit comments

Comments
 (0)