Skip to content

Commit 267c408

Browse files
committed
Add strongly-typed IDs and orders for use in EF Core
1 parent 5e136e9 commit 267c408

13 files changed

+668
-1
lines changed

StronglyTypedIdEfCore/StronglyTypedIdEfCore/Data/ApplicationDbContext.cs

+2
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,7 @@ public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
1313
: base(options)
1414
{
1515
}
16+
17+
public DbSet<Order> Orders { get; set; }
1618
}
1719
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System;
2+
using System.Collections.Concurrent;
3+
using System.Collections.Generic;
4+
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
5+
6+
namespace StronglyTypedId.Shop.Data
7+
{
8+
public class CustomValueConverterSelector : ValueConverterSelector
9+
{
10+
private readonly ConcurrentDictionary<(Type ModelClrType, Type ProviderClrType), ValueConverterInfo> _converters
11+
= new ConcurrentDictionary<(Type ModelClrType, Type ProviderClrType), ValueConverterInfo>();
12+
13+
public CustomValueConverterSelector(ValueConverterSelectorDependencies dependencies) : base(dependencies)
14+
{
15+
}
16+
17+
public override IEnumerable<ValueConverterInfo> Select(Type modelClrType, Type providerClrType = null)
18+
{
19+
foreach (var converter in base.Select(modelClrType, providerClrType))
20+
{
21+
yield return converter;
22+
}
23+
24+
// Extract the "real" type T from Nullable<T> if required
25+
var underlyingModelType = UnwrapNullableType(modelClrType);
26+
var underlyingProviderType = UnwrapNullableType(providerClrType);
27+
28+
// 'null' means 'get any value converters for the modelClrType'
29+
if (underlyingProviderType is null || underlyingProviderType == typeof(Guid))
30+
{
31+
// Try and get a nested class with the expected name.
32+
var converterType = underlyingModelType.GetNestedType("EfCoreValueConverter");
33+
34+
if (converterType != null)
35+
{
36+
yield return _converters.GetOrAdd(
37+
(underlyingModelType, typeof(Guid)),
38+
k =>
39+
{
40+
// Create an instance of the converter whenever it's requested.
41+
Func<ValueConverterInfo, ValueConverter> factory =
42+
info => (ValueConverter) Activator.CreateInstance(converterType, info.MappingHints);
43+
44+
// Build the info for our strongly-typed ID => Guid converter
45+
return new ValueConverterInfo(modelClrType, typeof(Guid), factory);
46+
}
47+
);
48+
}
49+
}
50+
}
51+
52+
private static Type UnwrapNullableType(Type providerClrType)
53+
{
54+
if (providerClrType is null)
55+
{
56+
return null;
57+
}
58+
59+
return Nullable.GetUnderlyingType(providerClrType) ?? providerClrType;
60+
}
61+
}
62+
}

StronglyTypedIdEfCore/StronglyTypedIdEfCore/Data/Migrations/20190420212339_OrderSchema.Designer.cs

+270
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using System;
2+
using Microsoft.EntityFrameworkCore.Migrations;
3+
4+
namespace StronglyTypedIdEfCore.Data.Migrations
5+
{
6+
public partial class OrderSchema : Migration
7+
{
8+
protected override void Up(MigrationBuilder migrationBuilder)
9+
{
10+
migrationBuilder.CreateTable(
11+
name: "Orders",
12+
columns: table => new
13+
{
14+
OrderId = table.Column<Guid>(nullable: false),
15+
Name = table.Column<string>(nullable: true)
16+
},
17+
constraints: table =>
18+
{
19+
table.PrimaryKey("PK_Orders", x => x.OrderId);
20+
});
21+
22+
migrationBuilder.CreateTable(
23+
name: "OrderLine",
24+
columns: table => new
25+
{
26+
OrderLineId = table.Column<Guid>(nullable: false),
27+
OrderId = table.Column<Guid>(nullable: false),
28+
ProductName = table.Column<string>(nullable: true)
29+
},
30+
constraints: table =>
31+
{
32+
table.PrimaryKey("PK_OrderLine", x => x.OrderLineId);
33+
table.ForeignKey(
34+
name: "FK_OrderLine_Orders_OrderId",
35+
column: x => x.OrderId,
36+
principalTable: "Orders",
37+
principalColumn: "OrderId",
38+
onDelete: ReferentialAction.Cascade);
39+
});
40+
41+
migrationBuilder.CreateIndex(
42+
name: "IX_OrderLine_OrderId",
43+
table: "OrderLine",
44+
column: "OrderId");
45+
}
46+
47+
protected override void Down(MigrationBuilder migrationBuilder)
48+
{
49+
migrationBuilder.DropTable(
50+
name: "OrderLine");
51+
52+
migrationBuilder.DropTable(
53+
name: "Orders");
54+
}
55+
}
56+
}

0 commit comments

Comments
 (0)