-
Notifications
You must be signed in to change notification settings - Fork 816
/
NpgsqlTypeMapper.cs
executable file
·106 lines (95 loc) · 4.53 KB
/
NpgsqlTypeMapper.cs
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
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.Entity.Utilities;
using Npgsql;
using Npgsql.BackendMessages;
using Npgsql.TypeHandlers;
using Npgsql.TypeHandlers.NumericHandlers;
using NpgsqlTypes;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Storage.Internal
{
// TODO: Provider-specific types?
// TODO: BIT(1) vs. BIT(N)
// TODO: Enums? Ranges? Composite?
// TODO: Arrays? But this would conflict with navigation...
public class NpgsqlTypeMapper : RelationalTypeMapper
{
readonly Dictionary<string, RelationalTypeMapping> _simpleNameMappings;
readonly Dictionary<Type, RelationalTypeMapping> _simpleMappings;
public NpgsqlTypeMapper()
{
// Reflect over Npgsql's type mappings and generate EF7 type mappings from them
// Note that enums aren't supported yet, see https://github.com/aspnet/EntityFramework/issues/3620
// First, PostgreSQL type name (string) -> RelationalTypeMapping
_simpleNameMappings = TypeHandlerRegistry.HandlerTypes.Values
// Base types
.Where(tam => tam.Mapping.NpgsqlDbType.HasValue)
.Select(tam => new {
Name = tam.Mapping.PgName,
Mapping = (RelationalTypeMapping)new NpgsqlTypeMapping(tam.Mapping.PgName, GetTypeHandlerTypeArgument(tam.HandlerType), tam.Mapping.NpgsqlDbType.Value)
})
// Enums
//.Concat(TypeHandlerRegistry.GlobalEnumMappings.Select(kv => new {
// Name = kv.Key,
// Mapping = (RelationalTypeMapping)new NpgsqlTypeMapping(kv.Key, ((IEnumHandler)kv.Value).EnumType)
//}))
// Composites
.Concat(TypeHandlerRegistry.GlobalCompositeMappings.Select(kv => new {
Name = kv.Key,
Mapping = (RelationalTypeMapping)new NpgsqlTypeMapping(kv.Key, ((ICompositeHandler)kv.Value).CompositeType)
}))
// Output
.ToDictionary(x => x.Name, x => x.Mapping);
// Second, CLR type -> RelationalTypeMapping
_simpleMappings = TypeHandlerRegistry.HandlerTypes.Values
// Base types
.Select(tam => tam.Mapping)
.Where(m => m.NpgsqlDbType.HasValue)
.SelectMany(m => m.Types, (m, t) => new {
Type = t,
Mapping = (RelationalTypeMapping)new NpgsqlTypeMapping(m.PgName, t, m.NpgsqlDbType.Value)
})
// Enums
//.Concat(TypeHandlerRegistry.GlobalEnumMappings.Select(kv => new {
// Type = ((IEnumHandler)kv.Value).EnumType,
// Mapping = (RelationalTypeMapping)new NpgsqlTypeMapping(kv.Key, ((IEnumHandler)kv.Value).EnumType)
//}))
// Composites
.Concat(TypeHandlerRegistry.GlobalCompositeMappings.Select(kv => new {
Type = ((ICompositeHandler)kv.Value).CompositeType,
Mapping = (RelationalTypeMapping)new NpgsqlTypeMapping(kv.Key, ((ICompositeHandler)kv.Value).CompositeType)
}))
// Output
.ToDictionary(x => x.Type, x => x.Mapping);
}
protected override string GetColumnType(IProperty property) => property.Npgsql().ColumnType;
protected override IReadOnlyDictionary<Type, RelationalTypeMapping> SimpleMappings
=> _simpleMappings;
protected override IReadOnlyDictionary<string, RelationalTypeMapping> SimpleNameMappings
=> _simpleNameMappings;
static Type GetTypeHandlerTypeArgument(Type handler)
{
while (!handler.IsGenericType || handler.GetGenericTypeDefinition() != typeof(TypeHandler<>))
{
handler = handler.BaseType;
if (handler == null)
{
throw new Exception("Npgsql type handler doesn't inherit from TypeHandler<>?");
}
}
return handler.GetGenericArguments()[0];
}
}
}