Skip to content

Commit d9546ce

Browse files
authored
Refactor MetadataProvider to improve table metadata retrieval logic (#81)
* Refactor MetadataProvider to improve table metadata retrieval logic * Improve error handling for keyless entities in MetadataProvider
1 parent 0cdcce7 commit d9546ce

1 file changed

Lines changed: 52 additions & 50 deletions

File tree

Lines changed: 52 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,52 @@
1-
using Microsoft.EntityFrameworkCore;
2-
using Microsoft.EntityFrameworkCore.Infrastructure;
3-
4-
using PhenX.EntityFrameworkCore.BulkInsert.Abstractions;
5-
6-
namespace PhenX.EntityFrameworkCore.BulkInsert.Metadata;
7-
8-
internal sealed class MetadataProvider
9-
{
10-
private Dictionary<Type, Dictionary<Type, TableMetadata>> _tablesPerContext = new();
11-
12-
public TableMetadata GetTableInfo<T>(DbContext context)
13-
{
14-
var tables = GetTables(context);
15-
16-
if (!tables.TryGetValue(typeof(T), out var table))
17-
{
18-
throw new InvalidOperationException($"Cannot find metadata for type '{typeof(T)}'.");
19-
}
20-
21-
return table;
22-
}
23-
24-
private Dictionary<Type, TableMetadata> GetTables(DbContext context)
25-
{
26-
lock (_tablesPerContext)
27-
{
28-
var type = context.GetType();
29-
if (_tablesPerContext.TryGetValue(context.GetType(), out var tables))
30-
{
31-
return tables;
32-
}
33-
34-
var provider = context.GetService<IBulkInsertProvider>();
35-
36-
tables = context.Model.GetEntityTypes()
37-
// Filter out entities without an associated table
38-
// See also https://learn.microsoft.com/en-us/ef/core/modeling/keyless-entity-types
39-
.Where(x => x.GetTableName() is not null)
40-
.GroupBy(x => x.ClrType)
41-
.ToDictionary(
42-
x => x.Key,
43-
x => new TableMetadata(x.First(), provider.SqlDialect));
44-
45-
_tablesPerContext[type] = tables;
46-
47-
return tables;
48-
}
49-
}
50-
}
1+
using Microsoft.EntityFrameworkCore;
2+
using Microsoft.EntityFrameworkCore.Infrastructure;
3+
4+
using PhenX.EntityFrameworkCore.BulkInsert.Abstractions;
5+
6+
namespace PhenX.EntityFrameworkCore.BulkInsert.Metadata;
7+
8+
internal sealed class MetadataProvider
9+
{
10+
private readonly Dictionary<Type, Dictionary<Type, TableMetadata>> _tablesPerContext = new();
11+
12+
public TableMetadata GetTableInfo<T>(DbContext context)
13+
{
14+
lock (_tablesPerContext)
15+
{
16+
var type = context.GetType();
17+
18+
if (!_tablesPerContext.TryGetValue(type, out var tables))
19+
{
20+
tables = new Dictionary<Type, TableMetadata>();
21+
_tablesPerContext[type] = tables;
22+
}
23+
24+
var modelType = typeof(T);
25+
26+
if (tables.TryGetValue(modelType, out var table))
27+
{
28+
return table;
29+
}
30+
31+
var entityType = context.Model.FindEntityType(modelType);
32+
if (entityType == null)
33+
{
34+
throw new InvalidOperationException($"The type '{modelType.FullName}' is not part of the model for the current context.");
35+
}
36+
37+
// Filter out entities without an associated table
38+
// See also https://learn.microsoft.com/en-us/ef/core/modeling/keyless-entity-types
39+
if (entityType.GetTableName() is null)
40+
{
41+
throw new InvalidOperationException($"The type '{modelType.FullName}' is not mapped to a table in the database or is keyless.");
42+
}
43+
44+
var provider = context.GetService<IBulkInsertProvider>();
45+
46+
var tableMetadata = new TableMetadata(entityType, provider.SqlDialect);
47+
tables[modelType] = tableMetadata;
48+
49+
return tableMetadata;
50+
}
51+
}
52+
}

0 commit comments

Comments
 (0)