• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

loresoft / EntityFrameworkCore.Generator / 15303740763

28 May 2025 03:07PM UTC coverage: 54.841% (-0.2%) from 55.036%
15303740763

push

github

pwelter34
add file header support

642 of 1331 branches covered (48.23%)

Branch coverage included in aggregate %.

14 of 33 new or added lines in 14 files covered. (42.42%)

3 existing lines in 3 files now uncovered.

1873 of 3255 relevant lines covered (57.54%)

61.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

73.58
/src/EntityFrameworkCore.Generator.Core/Templates/MappingClassTemplate.cs
1
using System.Data;
2
using System.Globalization;
3

4
using EntityFrameworkCore.Generator.Extensions;
5
using EntityFrameworkCore.Generator.Metadata.Generation;
6
using EntityFrameworkCore.Generator.Options;
7

8
using Microsoft.EntityFrameworkCore;
9
using Microsoft.EntityFrameworkCore.Metadata;
10

11
namespace EntityFrameworkCore.Generator.Templates;
12

13
public class MappingClassTemplate : CodeTemplateBase
14
{
15
    private readonly Entity _entity;
16

17
    public MappingClassTemplate(Entity entity, GeneratorOptions options) : base(options)
22✔
18
    {
19
        _entity = entity;
22✔
20
    }
22✔
21

22

23
    public override string WriteCode()
24
    {
25
        CodeBuilder.Clear();
22✔
26

27
        if (Options.Data.Mapping.Header.HasValue())
22!
NEW
28
            CodeBuilder.AppendLine(Options.Data.Mapping.Header).AppendLine();
×
29

30
        CodeBuilder.AppendLine("using System;");
22✔
31
        CodeBuilder.AppendLine("using System.Collections.Generic;");
22✔
32
        CodeBuilder.AppendLine();
22✔
33
        CodeBuilder.AppendLine("using Microsoft.EntityFrameworkCore;");
22✔
34
        CodeBuilder.AppendLine();
22✔
35

36
        CodeBuilder.Append($"namespace {_entity.MappingNamespace}");
22✔
37

38
        if (Options.Project.FileScopedNamespace)
22!
39
        {
40
            CodeBuilder.AppendLine(";");
×
41
            CodeBuilder.AppendLine();
×
42
            GenerateClass();
×
43
        }
44
        else
45
        {
46
            CodeBuilder.AppendLine();
22✔
47
            CodeBuilder.AppendLine("{");
22✔
48

49
            using (CodeBuilder.Indent())
22✔
50
            {
51
                GenerateClass();
22✔
52
            }
22✔
53

54
            CodeBuilder.AppendLine("}");
22✔
55
        }
56

57
        return CodeBuilder.ToString();
22✔
58
    }
59

60

61
    private void GenerateClass()
62
    {
63
        var mappingClass = _entity.MappingClass.ToSafeName();
22✔
64
        var entityClass = _entity.EntityClass.ToSafeName();
22✔
65
        var safeName = $"{_entity.EntityNamespace}.{entityClass}";
22✔
66

67
        if (Options.Data.Mapping.Document)
22!
68
        {
69
            CodeBuilder.AppendLine("/// <summary>");
×
70
            CodeBuilder.AppendLine($"/// Allows configuration for an entity type <see cref=\"{safeName}\" />");
×
71
            CodeBuilder.AppendLine("/// </summary>");
×
72
        }
73

74
        CodeBuilder.AppendLine($"public partial class {mappingClass}");
22✔
75

76
        using (CodeBuilder.Indent())
22✔
77
            CodeBuilder.AppendLine($": IEntityTypeConfiguration<{safeName}>");
22✔
78

79
        CodeBuilder.AppendLine("{");
22✔
80

81
        using (CodeBuilder.Indent())
22✔
82
        {
83
            GenerateConfigure();
22✔
84
            GenerateConstants();
22✔
85
        }
22✔
86

87
        CodeBuilder.AppendLine("}");
22✔
88

89
    }
22✔
90

91
    private void GenerateConstants()
92
    {
93
        var entityClass = _entity.EntityClass.ToSafeName();
22✔
94
        var safeName = $"{_entity.EntityNamespace}.{entityClass}";
22✔
95

96
        CodeBuilder.AppendLine("#region Generated Constants");
22✔
97

98
        CodeBuilder.AppendLine("public readonly struct Table");
22✔
99
        CodeBuilder.AppendLine("{");
22✔
100

101
        using (CodeBuilder.Indent())
22✔
102
        {
103

104
            if (Options.Data.Mapping.Document)
22!
105
                CodeBuilder.AppendLine($"/// <summary>Table Schema name constant for entity <see cref=\"{safeName}\" /></summary>");
×
106

107
            CodeBuilder.AppendLine($"public const string Schema = \"{_entity.TableSchema}\";");
22✔
108

109
            if (Options.Data.Mapping.Document)
22!
110
                CodeBuilder.AppendLine($"/// <summary>Table Name constant for entity <see cref=\"{safeName}\" /></summary>");
×
111

112
            CodeBuilder.AppendLine($"public const string Name = \"{_entity.TableName}\";");
22✔
113
        }
22✔
114

115
        CodeBuilder.AppendLine("}");
22✔
116

117
        CodeBuilder.AppendLine();
22✔
118
        CodeBuilder.AppendLine("public readonly struct Columns");
22✔
119
        CodeBuilder.AppendLine("{");
22✔
120

121
        using (CodeBuilder.Indent())
22✔
122
        {
123
            foreach (var property in _entity.Properties)
464✔
124
            {
125
                if (Options.Data.Mapping.Document)
210!
126
                    CodeBuilder.AppendLine($"/// <summary>Column Name constant for property <see cref=\"{safeName}.{property.PropertyName}\" /></summary>");
×
127

128
                CodeBuilder.AppendLine($"public const string {property.PropertyName.ToSafeName()} = {property.ColumnName.ToLiteral()};");
210✔
129
            }
130
        }
131

132
        CodeBuilder.AppendLine("}");
22✔
133
        CodeBuilder.AppendLine("#endregion");
22✔
134
    }
22✔
135

136
    private void GenerateConfigure()
137
    {
138
        var entityClass = _entity.EntityClass.ToSafeName();
22✔
139
        var entityFullName = $"{_entity.EntityNamespace}.{entityClass}";
22✔
140

141
        if (Options.Data.Mapping.Document)
22!
142
        {
143
            CodeBuilder.AppendLine("/// <summary>");
×
144
            CodeBuilder.AppendLine($"/// Configures the entity of type <see cref=\"{entityFullName}\" />");
×
145
            CodeBuilder.AppendLine("/// </summary>");
×
146
            CodeBuilder.AppendLine("/// <param name=\"builder\">The builder to be used to configure the entity type.</param>");
×
147
        }
148

149
        CodeBuilder.AppendLine($"public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder<{entityFullName}> builder)");
22✔
150
        CodeBuilder.AppendLine("{");
22✔
151

152
        using (CodeBuilder.Indent())
22✔
153
        {
154
            CodeBuilder.AppendLine("#region Generated Configure");
22✔
155

156
            GenerateTableMapping();
22✔
157
            GenerateKeyMapping();
22✔
158
            GeneratePropertyMapping();
22✔
159
            GenerateRelationshipMapping();
22✔
160

161
            CodeBuilder.AppendLine("#endregion");
22✔
162
        }
22✔
163

164
        CodeBuilder.AppendLine("}");
22✔
165
        CodeBuilder.AppendLine();
22✔
166
    }
22✔
167

168

169
    private void GenerateRelationshipMapping()
170
    {
171
        CodeBuilder.AppendLine("// relationships");
22✔
172
        foreach (var relationship in _entity.Relationships.Where(e => e.IsMapped))
100✔
173
        {
174
            GenerateRelationshipMapping(relationship);
14✔
175
            CodeBuilder.AppendLine();
14✔
176
        }
177

178
    }
22✔
179

180
    private void GenerateRelationshipMapping(Relationship relationship)
181
    {
182
        CodeBuilder.Append("builder.HasOne(t => t.");
14✔
183
        CodeBuilder.Append(relationship.PropertyName);
14✔
184
        CodeBuilder.Append(")");
14✔
185
        CodeBuilder.AppendLine();
14✔
186

187
        CodeBuilder.IncrementIndent();
14✔
188

189
        CodeBuilder.Append(relationship.PrimaryCardinality == Cardinality.Many
14✔
190
            ? ".WithMany(t => t."
14✔
191
            : ".WithOne(t => t.");
14✔
192

193
        CodeBuilder.Append(relationship.PrimaryPropertyName);
14✔
194
        CodeBuilder.Append(")");
14✔
195

196
        CodeBuilder.AppendLine();
14✔
197
        CodeBuilder.Append(".HasForeignKey");
14✔
198
        if (relationship.IsOneToOne)
14✔
199
        {
200
            CodeBuilder.Append("<");
2✔
201
            CodeBuilder.Append(_entity.EntityNamespace);
2✔
202
            CodeBuilder.Append(".");
2✔
203
            CodeBuilder.Append(_entity.EntityClass.ToSafeName());
2✔
204
            CodeBuilder.Append(">");
2✔
205
        }
206
        CodeBuilder.Append("(d => ");
14✔
207

208
        var keys = relationship.Properties;
14✔
209
        bool wroteLine = false;
14✔
210

211
        if (keys.Count == 1)
14!
212
        {
213
            var propertyName = keys[0].PropertyName.ToSafeName();
14✔
214
            CodeBuilder.Append($"d.{propertyName}");
14✔
215
        }
216
        else
217
        {
218
            CodeBuilder.Append("new { ");
×
219
            foreach (var p in keys)
×
220
            {
221
                if (wroteLine)
×
222
                    CodeBuilder.Append(", ");
×
223

224
                CodeBuilder.Append($"d.{p.PropertyName}");
×
225
                wroteLine = true;
×
226
            }
227
            CodeBuilder.Append("}");
×
228
        }
229
        CodeBuilder.Append(")");
14✔
230

231
        var primaryKeys = relationship.PrimaryProperties;
14✔
232
        var nonPrimaryPrincipalKey = !primaryKeys
14✔
233
            .Select(pp => relationship.PrimaryEntity.Properties.ByProperty(pp.PropertyName))
14✔
234
            .All(p => p?.IsPrimaryKey ?? true);
28!
235

236
        if (nonPrimaryPrincipalKey)
14!
237
        {
238
            CodeBuilder.AppendLine();
×
239

240
            CodeBuilder.Append(".HasPrincipalKey(t => ");
×
241
            if (primaryKeys.Count > 1)
×
242
            {
243
                CodeBuilder.Append("new { ");
×
244
                CodeBuilder.Append(string.Join(", ", primaryKeys.Select(pp => $"t.{pp.PropertyName.ToSafeName()}")));
×
245
                CodeBuilder.Append(" }");
×
246
            }
247
            else
248
            {
249
                var propertyName = primaryKeys.First().PropertyName.ToSafeName();
×
250
                CodeBuilder.Append($"t.{propertyName}");
×
251
            }
252
            CodeBuilder.Append(")");
×
253
        }
254

255
        if (!string.IsNullOrEmpty(relationship.RelationshipName))
14✔
256
        {
257
            CodeBuilder.AppendLine();
14✔
258
            CodeBuilder.Append(".HasConstraintName(\"");
14✔
259
            CodeBuilder.Append(relationship.RelationshipName);
14✔
260
            CodeBuilder.Append("\")");
14✔
261
        }
262

263
        CodeBuilder.DecrementIndent();
14✔
264

265
        CodeBuilder.AppendLine(";");
14✔
266
    }
14✔
267

268

269
    private void GeneratePropertyMapping()
270
    {
271
        CodeBuilder.AppendLine("// properties");
22✔
272
        foreach (var property in _entity.Properties)
464✔
273
        {
274
            GeneratePropertyMapping(property);
210✔
275
            CodeBuilder.AppendLine();
210✔
276
        }
277
    }
22✔
278

279
    private void GeneratePropertyMapping(Property property)
280
    {
281
        bool isString = property.SystemType == typeof(string);
210✔
282
        bool isByteArray = property.SystemType == typeof(byte[]);
210✔
283

284
        CodeBuilder.Append($"builder.Property(t => t.{property.PropertyName})");
210✔
285

286
        CodeBuilder.IncrementIndent();
210✔
287
        if (property.IsRequired)
210✔
288
        {
289
            CodeBuilder.AppendLine();
120✔
290
            CodeBuilder.Append(".IsRequired()");
120✔
291
        }
292

293
        if (property.IsRowVersion == true)
210✔
294
        {
295
            if (property.DataType == DbType.Binary && property.SystemType != typeof(byte[]))
16!
296
            {
297
                CodeBuilder.AppendLine();
×
298
                CodeBuilder.Append(".HasConversion<byte[]>()");
×
299
            }
300
            CodeBuilder.AppendLine();
16✔
301
            CodeBuilder.Append(".IsRowVersion()");
16✔
302
        }
303

304
        if (property.IsConcurrencyToken == true)
210✔
305
        {
306
            CodeBuilder.AppendLine();
16✔
307
            CodeBuilder.Append(".IsConcurrencyToken()");
16✔
308
        }
309

310
        CodeBuilder.AppendLine();
210✔
311
        CodeBuilder.Append($".HasColumnName({property.ColumnName.ToLiteral()})");
210✔
312

313
        if (!string.IsNullOrEmpty(property.StoreType))
210✔
314
        {
315
            CodeBuilder.AppendLine();
210✔
316
            CodeBuilder.Append($".HasColumnType({property.StoreType.ToLiteral()})");
210✔
317
        }
318

319
        if ((isString || isByteArray) && property.Size > 0)
210✔
320
        {
321
            CodeBuilder.AppendLine();
90✔
322
            CodeBuilder.Append($".HasMaxLength({property.Size.Value.ToString(CultureInfo.InvariantCulture)})");
90✔
323
        }
324

325
        // only use for simple types
326
        if (property.DefaultValue is bool or int or long or byte or double or float or short)
210✔
327
        {
328
            CodeBuilder.AppendLine();
18✔
329
            CodeBuilder.Append($".HasDefaultValue({property.DefaultValue?.ToString()?.ToLowerInvariant()})");
18!
330
        }
331
        else if (!string.IsNullOrEmpty(property.Default))
192✔
332
        {
333
            CodeBuilder.AppendLine();
32✔
334
            CodeBuilder.Append($".HasDefaultValueSql({property.Default.ToLiteral()})");
32✔
335
        }
336

337
        switch (property.ValueGenerated)
210!
338
        {
339
            case ValueGenerated.OnAdd:
340
                CodeBuilder.AppendLine();
6✔
341
                CodeBuilder.Append(".ValueGeneratedOnAdd()");
6✔
342
                break;
6✔
343
            case ValueGenerated.OnAddOrUpdate:
344
                CodeBuilder.AppendLine();
16✔
345
                CodeBuilder.Append(".ValueGeneratedOnAddOrUpdate()");
16✔
346
                break;
16✔
347
            case ValueGenerated.OnUpdate:
348
                CodeBuilder.AppendLine();
×
349
                CodeBuilder.Append(".ValueGeneratedOnUpdate()");
×
350
                break;
351
        }
352
        CodeBuilder.DecrementIndent();
210✔
353

354
        CodeBuilder.AppendLine(";");
210✔
355
    }
210✔
356

357

358
    private void GenerateKeyMapping()
359
    {
360
        CodeBuilder.AppendLine("// key");
22✔
361

362
        var keys = _entity.Properties.Where(p => p.IsPrimaryKey == true).ToList();
232✔
363
        if (keys.Count == 0)
22!
364
        {
365
            CodeBuilder.AppendLine("builder.HasNoKey();");
×
366
            CodeBuilder.AppendLine();
×
367

368
            return;
×
369
        }
370

371
        CodeBuilder.Append("builder.HasKey(t => ");
22✔
372

373
        if (keys.Count == 1)
22✔
374
        {
375
            var propertyName = keys[0].PropertyName.ToSafeName();
20✔
376
            CodeBuilder.AppendLine($"t.{propertyName});");
20✔
377
            CodeBuilder.AppendLine();
20✔
378

379
            return;
20✔
380
        }
381

382
        bool wroteLine = false;
2✔
383

384
        CodeBuilder.Append("new { ");
2✔
385
        foreach (var p in keys)
12✔
386
        {
387
            if (wroteLine)
4✔
388
                CodeBuilder.Append(", ");
2✔
389

390
            CodeBuilder.Append("t.");
4✔
391
            CodeBuilder.Append(p.PropertyName);
4✔
392
            wroteLine = true;
4✔
393
        }
394

395
        CodeBuilder.AppendLine(" });");
2✔
396
        CodeBuilder.AppendLine();
2✔
397
    }
2✔
398

399
    private void GenerateTableMapping()
400
    {
401
        CodeBuilder.AppendLine("// table");
22✔
402

403
        var method = _entity.IsView
22!
404
            ? nameof(RelationalEntityTypeBuilderExtensions.ToView)
22✔
405
            : nameof(RelationalEntityTypeBuilderExtensions.ToTable);
22✔
406

407
        CodeBuilder.AppendLine(_entity.TableSchema.HasValue()
22!
408
            ? $"builder.{method}(\"{_entity.TableName}\", \"{_entity.TableSchema}\");"
22✔
409
            : $"builder.{method}(\"{_entity.TableName}\");");
22✔
410

411
        CodeBuilder.AppendLine();
22✔
412

413
        if (_entity.TemporalTableName.IsNullOrEmpty())
22!
414
            return;
22✔
415

416
        CodeBuilder.AppendLine("builder");
×
417
        CodeBuilder.IncrementIndent();
×
418
        CodeBuilder.AppendLine(".ToTable(tableBuilder => tableBuilder");
×
419
        CodeBuilder.IncrementIndent();
×
420
        CodeBuilder.AppendLine(".IsTemporal(temporalBuilder =>");
×
421
        CodeBuilder.AppendLine("{");
×
422
        CodeBuilder.IncrementIndent();
×
423
        CodeBuilder.AppendLine("temporalBuilder");
×
424
        CodeBuilder.IncrementIndent();
×
425

426
        CodeBuilder.AppendLine(_entity.TemporalTableSchema.HasValue()
×
427
            ? $".UseHistoryTable(\"{_entity.TemporalTableName}\", \"{_entity.TemporalTableSchema}\");"
×
428
            : $".UseHistoryTable(\"{_entity.TemporalTableName}\");");
×
429

430
        CodeBuilder.DecrementIndent();
×
431
        CodeBuilder.AppendLine("temporalBuilder");
×
432
        CodeBuilder.IncrementIndent();
×
433
        CodeBuilder.AppendLine($".HasPeriodStart(\"{_entity.TemporalStartProperty}\")");
×
434
        CodeBuilder.AppendLine($".HasColumnName(\"{_entity.TemporalStartColumn}\");");
×
435

436
        CodeBuilder.DecrementIndent();
×
437
        CodeBuilder.AppendLine("temporalBuilder");
×
438
        CodeBuilder.IncrementIndent();
×
439
        CodeBuilder.AppendLine($".HasPeriodEnd(\"{_entity.TemporalEndProperty}\")");
×
440
        CodeBuilder.AppendLine($".HasColumnName(\"{_entity.TemporalEndColumn}\");");
×
441

442
        CodeBuilder.DecrementIndent();
×
443
        CodeBuilder.DecrementIndent();
×
444
        CodeBuilder.AppendLine("})");
×
445

446
        CodeBuilder.DecrementIndent();
×
447
        CodeBuilder.AppendLine(");");
×
448

449
        CodeBuilder.DecrementIndent();
×
450

451
        CodeBuilder.AppendLine();
×
452
    }
×
453
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc