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

loresoft / EntityFrameworkCore.Generator / 27730465225

18 Jun 2026 01:21AM UTC coverage: 74.693% (+19.8%) from 54.885%
27730465225

push

github

pwelter34
update tests

922 of 1609 branches covered (57.3%)

Branch coverage included in aggregate %.

7 of 7 new or added lines in 2 files covered. (100.0%)

230 existing lines in 23 files now uncovered.

4007 of 4990 relevant lines covered (80.3%)

1258.69 hits per line

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

89.97
/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
namespace EntityFrameworkCore.Generator.Templates;
9

10
public class MappingClassTemplate : CodeTemplateBase
11
{
12
    private readonly Entity _entity;
13

14
    public MappingClassTemplate(Entity entity, GeneratorOptions options) : base(options)
159✔
15
    {
16
        _entity = entity;
159✔
17
    }
159✔
18

19

20
    public override string WriteCode()
21
    {
22
        CodeBuilder.Clear();
159✔
23

24
        if (Options.Data.Mapping.Header.HasValue())
159!
UNCOV
25
            CodeBuilder.AppendLine(Options.Data.Mapping.Header).AppendLine();
×
26

27
        CodeBuilder.AppendLine("using System;");
159✔
28
        CodeBuilder.AppendLine("using System.Collections.Generic;");
159✔
29
        CodeBuilder.AppendLine();
159✔
30
        CodeBuilder.AppendLine("using Microsoft.EntityFrameworkCore;");
159✔
31
        CodeBuilder.AppendLine("using Microsoft.EntityFrameworkCore.Metadata.Builders;");
159✔
32
        CodeBuilder.AppendLine();
159✔
33

34
        CodeBuilder.Append($"namespace {_entity.MappingNamespace}");
159✔
35

36
        if (Options.Project.FileScopedNamespace)
159✔
37
        {
38
            CodeBuilder.AppendLine(";");
137✔
39
            CodeBuilder.AppendLine();
137✔
40
            GenerateClass();
137✔
41
        }
42
        else
43
        {
44
            CodeBuilder.AppendLine();
22✔
45
            CodeBuilder.AppendLine("{");
22✔
46

47
            using (CodeBuilder.Indent())
22✔
48
            {
49
                GenerateClass();
22✔
50
            }
22✔
51

52
            CodeBuilder.AppendLine("}");
22✔
53
        }
54

55
        return CodeBuilder.ToString();
159✔
56
    }
57

58

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

65
        if (Options.Data.Mapping.Document)
159✔
66
        {
67
            CodeBuilder.AppendLine("/// <summary>");
137✔
68
            CodeBuilder.AppendLine($"/// Allows configuration for an entity type <see cref=\"{safeName}\" />");
137✔
69
            CodeBuilder.AppendLine("/// </summary>");
137✔
70
        }
71

72
        CodeBuilder.AppendLine($"public partial class {mappingClass}");
159✔
73

74
        using (CodeBuilder.Indent())
159✔
75
            CodeBuilder.AppendLine($": IEntityTypeConfiguration<{safeName}>");
159✔
76

77
        CodeBuilder.AppendLine("{");
159✔
78

79
        using (CodeBuilder.Indent())
159✔
80
        {
81
            GenerateConfigure();
159✔
82
            GenerateConstants();
159✔
83
        }
159✔
84

85
        CodeBuilder.AppendLine("}");
159✔
86

87
    }
159✔
88

89
    private void GenerateConstants()
90
    {
91
        var entityClass = _entity.EntityClass.ToSafeName();
159✔
92
        var safeName = $"{_entity.EntityNamespace}.{entityClass}";
159✔
93

94
        CodeBuilder.AppendLine("#region Generated Constants");
159✔
95

96
        CodeBuilder.AppendLine("public readonly struct Table");
159✔
97
        CodeBuilder.AppendLine("{");
159✔
98

99
        using (CodeBuilder.Indent())
159✔
100
        {
101

102
            if (_entity.TableSchema.HasValue())
159✔
103
            {
104
                if (Options.Data.Mapping.Document)
125✔
105
                    CodeBuilder.AppendLine($"/// <summary>Table Schema name constant for entity <see cref=\"{safeName}\" /></summary>");
103✔
106

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

110
            if (Options.Data.Mapping.Document)
159✔
111
                CodeBuilder.AppendLine($"/// <summary>Table Name constant for entity <see cref=\"{safeName}\" /></summary>");
137✔
112

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

116
        CodeBuilder.AppendLine("}");
159✔
117

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

122
        using (CodeBuilder.Indent())
159✔
123
        {
124
            foreach (var property in _entity.Properties)
2,876✔
125
            {
126
                if (Options.Data.Mapping.Document)
1,279✔
127
                    CodeBuilder.AppendLine($"/// <summary>Column Name constant for property <see cref=\"{safeName}.{property.PropertyName}\" /></summary>");
1,069✔
128

129
                CodeBuilder.AppendLine($"public const string {property.PropertyName.ToSafeName()} = {property.ColumnName.ToLiteral()};");
1,279✔
130
            }
131
        }
132

133
        CodeBuilder.AppendLine("}");
159✔
134
        CodeBuilder.AppendLine("#endregion");
159✔
135
    }
159✔
136

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

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

150
        CodeBuilder.AppendLine($"public void Configure(EntityTypeBuilder<{entityFullName}> builder)");
159✔
151
        CodeBuilder.AppendLine("{");
159✔
152

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

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

162
            CodeBuilder.AppendLine("#endregion");
159✔
163
        }
159✔
164

165
        CodeBuilder.AppendLine("}");
159✔
166
        CodeBuilder.AppendLine();
159✔
167
    }
159✔
168

169

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

179
    }
159✔
180

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

188
        CodeBuilder.IncrementIndent();
77✔
189

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

194
        CodeBuilder.Append(relationship.PrimaryPropertyName);
77✔
195
        CodeBuilder.Append(")");
77✔
196

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

209
        var keys = relationship.Properties;
77✔
210
        bool wroteLine = false;
77✔
211

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

225
                CodeBuilder.Append($"d.{p.PropertyName}");
6✔
226
                wroteLine = true;
6✔
227
            }
228
            CodeBuilder.Append("}");
3✔
229
        }
230
        CodeBuilder.Append(")");
77✔
231

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

237
        if (nonPrimaryPrincipalKey)
77!
238
        {
UNCOV
239
            CodeBuilder.AppendLine();
×
240

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

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

264
        CodeBuilder.DecrementIndent();
77✔
265

266
        CodeBuilder.AppendLine(";");
77✔
267
    }
77✔
268

269

270
    private void GeneratePropertyMapping()
271
    {
272
        CodeBuilder.AppendLine("// properties");
159✔
273
        foreach (var property in _entity.Properties)
2,876✔
274
        {
275
            GeneratePropertyMapping(property);
1,279✔
276
            CodeBuilder.AppendLine();
1,279✔
277
        }
278
    }
159✔
279

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

285
        CodeBuilder.Append($"builder.Property(t => t.{property.PropertyName})");
1,279✔
286

287
        CodeBuilder.IncrementIndent();
1,279✔
288
        if (property.IsRequired)
1,279✔
289
        {
290
            CodeBuilder.AppendLine();
668✔
291
            CodeBuilder.Append(".IsRequired()");
668✔
292
        }
293

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

305
        if (property.IsConcurrencyToken == true)
1,279✔
306
        {
307
            CodeBuilder.AppendLine();
26✔
308
            CodeBuilder.Append(".IsConcurrencyToken()");
26✔
309
        }
310

311
        CodeBuilder.AppendLine();
1,279✔
312
        CodeBuilder.Append($".HasColumnName({property.ColumnName.ToLiteral()})");
1,279✔
313

314
        if (!string.IsNullOrEmpty(property.NativeType))
1,279!
315
        {
316
            CodeBuilder.AppendLine();
1,279✔
317
            CodeBuilder.Append($".HasColumnType({property.NativeType.ToLiteral()})");
1,279✔
318
        }
319

320
        if ((isString || isByteArray) && property.Size > 0)
1,279✔
321
        {
322
            CodeBuilder.AppendLine();
382✔
323
            CodeBuilder.Append($".HasMaxLength({property.Size.Value.ToString(CultureInfo.InvariantCulture)})");
382✔
324
        }
325

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

338
        if (property.IsIdentity == true)
1,279✔
339
        {
340
            CodeBuilder.AppendLine();
65✔
341
            CodeBuilder.Append(".ValueGeneratedOnAdd()");
65✔
342
        }
343
        else if (property.IsComputed == true || property.IsRowVersion == true)
1,214✔
344
        {
345
            CodeBuilder.AppendLine();
44✔
346
            CodeBuilder.Append(".ValueGeneratedOnAddOrUpdate()");
44✔
347
        }
348

349
        CodeBuilder.DecrementIndent();
1,279✔
350

351
        CodeBuilder.AppendLine(";");
1,279✔
352
    }
1,279✔
353

354

355
    private void GenerateKeyMapping()
356
    {
357
        CodeBuilder.AppendLine("// key");
159✔
358

359
        var keys = _entity.Properties.Where(p => p.IsPrimaryKey == true).ToList();
159✔
360
        if (keys.Count == 0)
159✔
361
        {
362
            CodeBuilder.AppendLine("builder.HasNoKey();");
13✔
363
            CodeBuilder.AppendLine();
13✔
364

365
            return;
13✔
366
        }
367

368
        CodeBuilder.Append("builder.HasKey(t => ");
146✔
369

370
        if (keys.Count == 1)
146✔
371
        {
372
            var propertyName = keys[0].PropertyName.ToSafeName();
128✔
373
            CodeBuilder.AppendLine($"t.{propertyName});");
128✔
374
            CodeBuilder.AppendLine();
128✔
375

376
            return;
128✔
377
        }
378

379
        bool wroteLine = false;
18✔
380

381
        CodeBuilder.Append("new { ");
18✔
382
        foreach (var p in keys)
108✔
383
        {
384
            if (wroteLine)
36✔
385
                CodeBuilder.Append(", ");
18✔
386

387
            CodeBuilder.Append("t.");
36✔
388
            CodeBuilder.Append(p.PropertyName);
36✔
389
            wroteLine = true;
36✔
390
        }
391

392
        CodeBuilder.AppendLine(" });");
18✔
393
        CodeBuilder.AppendLine();
18✔
394
    }
18✔
395

396
    private void GenerateTableMapping()
397
    {
398
        CodeBuilder.AppendLine("// table");
159✔
399

400
        var method = _entity.IsView ? "ToView" : "ToTable";
159✔
401

402
        CodeBuilder.AppendLine(_entity.TableSchema.HasValue()
159✔
403
            ? $"builder.{method}(\"{_entity.TableName}\", \"{_entity.TableSchema}\");"
159✔
404
            : $"builder.{method}(\"{_entity.TableName}\");");
159✔
405

406
        CodeBuilder.AppendLine();
159✔
407

408
        if (_entity.TemporalTableName.IsNullOrEmpty())
159✔
409
            return;
158✔
410

411
        CodeBuilder.AppendLine("builder");
1✔
412
        CodeBuilder.IncrementIndent();
1✔
413
        CodeBuilder.AppendLine(".ToTable(tableBuilder => tableBuilder");
1✔
414
        CodeBuilder.IncrementIndent();
1✔
415
        CodeBuilder.AppendLine(".IsTemporal(temporalBuilder =>");
1✔
416
        CodeBuilder.AppendLine("{");
1✔
417
        CodeBuilder.IncrementIndent();
1✔
418
        CodeBuilder.AppendLine("temporalBuilder");
1✔
419
        CodeBuilder.IncrementIndent();
1✔
420

421
        CodeBuilder.AppendLine(_entity.TemporalTableSchema.HasValue()
1!
422
            ? $".UseHistoryTable(\"{_entity.TemporalTableName}\", \"{_entity.TemporalTableSchema}\");"
1✔
423
            : $".UseHistoryTable(\"{_entity.TemporalTableName}\");");
1✔
424

425
        CodeBuilder.DecrementIndent();
1✔
426
        CodeBuilder.AppendLine("temporalBuilder");
1✔
427
        CodeBuilder.IncrementIndent();
1✔
428
        CodeBuilder.AppendLine($".HasPeriodStart(\"{_entity.TemporalStartProperty}\")");
1✔
429
        CodeBuilder.AppendLine($".HasColumnName(\"{_entity.TemporalStartColumn}\");");
1✔
430

431
        CodeBuilder.DecrementIndent();
1✔
432
        CodeBuilder.AppendLine("temporalBuilder");
1✔
433
        CodeBuilder.IncrementIndent();
1✔
434
        CodeBuilder.AppendLine($".HasPeriodEnd(\"{_entity.TemporalEndProperty}\")");
1✔
435
        CodeBuilder.AppendLine($".HasColumnName(\"{_entity.TemporalEndColumn}\");");
1✔
436

437
        CodeBuilder.DecrementIndent();
1✔
438
        CodeBuilder.DecrementIndent();
1✔
439
        CodeBuilder.AppendLine("})");
1✔
440

441
        CodeBuilder.DecrementIndent();
1✔
442
        CodeBuilder.AppendLine(");");
1✔
443

444
        CodeBuilder.DecrementIndent();
1✔
445

446
        CodeBuilder.AppendLine();
1✔
447
    }
1✔
448
}
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