-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
134 lines (116 loc) · 3.84 KB
/
Program.cs
File metadata and controls
134 lines (116 loc) · 3.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
using Microsoft.EntityFrameworkCore;
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseSqlite("Data Source=:memory:")
.Options;
using var db = new AppDbContext(options);
db.Database.OpenConnection();
db.Database.EnsureCreated();
var parentId = Guid.NewGuid();
db.Parents.Add(new Parent
{
Id = parentId,
Name = "P1",
Coords = new Outer
{
First = new Inner { A = "1", B = "2" },
Second = new Inner { A = "3", B = "4" }
},
Children = [new Child { Id = Guid.NewGuid(), ParentId = parentId, Data = new Inner { A = "x", B = "y" } }]
});
db.SaveChanges();
// Combining a collection-navigation struct projection with a nested-struct
// projection in the same Select works in preview.1 but throws in preview.2.
try
{
var result = await db.Parents
.AsNoTracking()
.Where(p => p.Id == parentId)
.Select(p => new ParentVm(
p.Name,
p.Children.Select(c => new ChildVm(new InnerVm(c.Data))).ToList(),
new OuterVm(p.Coords)
))
.FirstOrDefaultAsync();
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"OK — {result}");
Console.ResetColor();
}
catch (InvalidOperationException ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"BUG: {ex.Message}");
Console.ResetColor();
Environment.ExitCode = 1;
}
// ── Domain ──────────────────────────────────────────────────────────
public readonly record struct Inner
{
public string? A { get; init; }
public string? B { get; init; }
}
public readonly record struct Outer
{
public Inner First { get; init; } // nested struct ComplexProperty
public Inner Second { get; init; } // nested struct ComplexProperty
}
public class Child
{
public Guid Id { get; set; }
public Guid ParentId { get; set; }
public Inner Data { get; set; } // struct ComplexProperty on collection element
public Parent? Parent { get; set; }
}
public class Parent
{
public Guid Id { get; set; }
public string Name { get; set; } = default!;
public Outer Coords { get; set; } // struct with nested struct ComplexProperties
public List<Child> Children { get; set; } = [];
}
// ── View models ─────────────────────────────────────────────────────
public record InnerVm(string? A, string? B)
{
public InnerVm(Inner i) : this(i.A, i.B) { }
}
public record OuterVm(InnerVm First, InnerVm Second)
{
public OuterVm(Outer o) : this(new InnerVm(o.First), new InnerVm(o.Second)) { }
}
public record ChildVm(InnerVm Data);
public record ParentVm(string Name, List<ChildVm> Children, OuterVm Coords);
// ── DbContext ───────────────────────────────────────────────────────
public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
{
public DbSet<Parent> Parents => Set<Parent>();
public DbSet<Child> Children => Set<Child>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Parent>(e =>
{
e.HasKey(x => x.Id);
e.ComplexProperty(x => x.Coords, c =>
{
c.ComplexProperty(x => x.First, f =>
{
f.Property(x => x.A).HasColumnName("first_a");
f.Property(x => x.B).HasColumnName("first_b");
});
c.ComplexProperty(x => x.Second, s =>
{
s.Property(x => x.A).HasColumnName("second_a");
s.Property(x => x.B).HasColumnName("second_b");
});
});
e.HasMany(x => x.Children).WithOne(x => x.Parent).HasForeignKey(x => x.ParentId);
});
modelBuilder.Entity<Child>(e =>
{
e.HasKey(x => x.Id);
e.ComplexProperty(x => x.Data, d =>
{
d.Property(x => x.A).HasColumnName("data_a");
d.Property(x => x.B).HasColumnName("data_b");
});
});
}
}