|
1 | 1 | using System; |
2 | | -using System.Collections.Concurrent; |
3 | 2 | using System.Collections.Generic; |
4 | 3 | using System.Data; |
5 | | -using System.Numerics; |
6 | 4 | using System.Text.Json; |
7 | 5 | using EfCore.Ydb.Storage.Internal.Mapping; |
8 | 6 | using Microsoft.EntityFrameworkCore.Storage; |
9 | 7 | using Type = System.Type; |
10 | 8 |
|
11 | 9 | namespace EfCore.Ydb.Storage.Internal; |
12 | 10 |
|
13 | | -public sealed class YdbTypeMappingSource : RelationalTypeMappingSource |
| 11 | +public sealed class YdbTypeMappingSource( |
| 12 | + TypeMappingSourceDependencies dependencies, |
| 13 | + RelationalTypeMappingSourceDependencies relationalDependencies |
| 14 | +) : RelationalTypeMappingSource(dependencies, relationalDependencies) |
14 | 15 | { |
15 | | - private ConcurrentDictionary<string, RelationalTypeMapping[]> StoreTypeMapping { get; } |
16 | | - private ConcurrentDictionary<Type, RelationalTypeMapping> ClrTypeMapping { get; } |
17 | | - |
18 | 16 | #region Mappings |
19 | 17 |
|
20 | | - private readonly YdbBoolTypeMapping _bool = YdbBoolTypeMapping.Default; |
| 18 | + private static readonly YdbBoolTypeMapping Bool = YdbBoolTypeMapping.Default; |
| 19 | + |
| 20 | + private static readonly SByteTypeMapping Int8 = new("Int8", DbType.SByte); |
| 21 | + private static readonly ShortTypeMapping Int16 = new("Int16", DbType.Int16); |
| 22 | + private static readonly IntTypeMapping Int32 = new("Int32", DbType.Int32); |
| 23 | + private static readonly LongTypeMapping Int64 = new("Int64", DbType.Int64); |
21 | 24 |
|
22 | | - private readonly SByteTypeMapping _int8 = new("Int8", DbType.SByte); |
23 | | - private readonly ShortTypeMapping _int16 = new("Int16", DbType.Int16); |
24 | | - private readonly IntTypeMapping _int32 = new("Int32", DbType.Int32); |
25 | | - private readonly LongTypeMapping _int64 = new("Int64", DbType.Int64); |
| 25 | + private static readonly ByteTypeMapping Uint8 = new("Uint8", DbType.Byte); |
| 26 | + private static readonly UShortTypeMapping Uint16 = new("Uint16", DbType.UInt16); |
| 27 | + private static readonly UIntTypeMapping Uint32 = new("Uint32", DbType.UInt32); |
| 28 | + private static readonly ULongTypeMapping Uint64 = new("Uint64", DbType.UInt64); |
26 | 29 |
|
27 | | - private readonly ByteTypeMapping _uint8 = new("Uint8", DbType.Byte); |
28 | | - private readonly UShortTypeMapping _uint16 = new("Uint16", DbType.UInt16); |
29 | | - private readonly UIntTypeMapping _uint32 = new("Uint32", DbType.UInt32); |
30 | | - private readonly ULongTypeMapping _uint64 = new("Uint64", DbType.UInt64); |
| 30 | + private static readonly FloatTypeMapping Float = new("Float", DbType.Single); |
| 31 | + private static readonly DoubleTypeMapping Double = new("Double", DbType.Double); |
31 | 32 |
|
32 | | - private readonly FloatTypeMapping _float = new("Float", DbType.Single); |
33 | | - private readonly DoubleTypeMapping _double = new("Double", DbType.Double); |
34 | | - private readonly YdbDecimalTypeMapping _biginteger = new(typeof(BigInteger)); |
35 | | - private readonly YdbDecimalTypeMapping _decimal = new(typeof(decimal)); |
36 | | - private readonly YdbDecimalTypeMapping _decimalAsDouble = new(typeof(double)); |
37 | | - private readonly YdbDecimalTypeMapping _decimalAsFloat = new(typeof(float)); |
| 33 | + private static readonly YdbDecimalTypeMapping Decimal = new(typeof(decimal)); |
38 | 34 |
|
39 | | - private readonly StringTypeMapping _text = new("Text", DbType.String); |
40 | | - private readonly YdbStringTypeMapping _ydbString = YdbStringTypeMapping.Default; |
41 | | - private readonly YdbBytesTypeMapping _bytes = YdbBytesTypeMapping.Default; |
42 | | - private readonly YdbJsonTypeMapping _json = new("Json", typeof(JsonElement), DbType.String); |
| 35 | + private static readonly StringTypeMapping Text = new("Text", DbType.String); |
| 36 | + private static readonly YdbBytesTypeMapping Bytes = YdbBytesTypeMapping.Default; |
| 37 | + private static readonly YdbJsonTypeMapping Json = new("Json", typeof(JsonElement), DbType.String); |
43 | 38 |
|
44 | | - private readonly DateOnlyTypeMapping _date = new("Date"); |
45 | | - private readonly DateTimeTypeMapping _dateTime = new("Datetime"); |
46 | | - private readonly DateTimeTypeMapping _timestamp = new("Timestamp"); |
47 | | - private readonly TimeSpanTypeMapping _interval = new("Interval"); |
| 39 | + private static readonly DateOnlyTypeMapping Date = new("Date"); |
| 40 | + private static readonly DateTimeTypeMapping DateTime = new("Datetime"); |
| 41 | + private static readonly DateTimeTypeMapping Timestamp = new("Timestamp"); |
| 42 | + private static readonly TimeSpanTypeMapping Interval = new("Interval"); |
48 | 43 |
|
49 | 44 | #endregion |
50 | 45 |
|
51 | | - public YdbTypeMappingSource( |
52 | | - TypeMappingSourceDependencies dependencies, |
53 | | - RelationalTypeMappingSourceDependencies relationalDependencies |
54 | | - ) : base(dependencies, relationalDependencies) |
55 | | - { |
56 | | - var storeTypeMappings = new Dictionary<string, RelationalTypeMapping[]>(StringComparer.OrdinalIgnoreCase) |
| 46 | + private static readonly Dictionary<string, RelationalTypeMapping[]> StoreTypeMapping = |
| 47 | + new(StringComparer.OrdinalIgnoreCase) |
57 | 48 | { |
58 | | - { "Bool", [_bool] }, |
| 49 | + { "Bool", [Bool] }, |
59 | 50 |
|
60 | | - { "Int8", [_int8] }, |
61 | | - { "Int16", [_int16] }, |
62 | | - { "Int32", [_int32] }, |
63 | | - { "Int64", [_int64] }, |
| 51 | + { "Int8", [Int8] }, |
| 52 | + { "Int16", [Int16] }, |
| 53 | + { "Int32", [Int32] }, |
| 54 | + { "Int64", [Int64] }, |
64 | 55 |
|
65 | | - { "Uint8", [_uint8] }, |
66 | | - { "Uint16", [_uint16] }, |
67 | | - { "Uint32", [_uint32] }, |
68 | | - { "Uint64", [_uint64] }, |
| 56 | + { "Uint8", [Uint8] }, |
| 57 | + { "Uint16", [Uint16] }, |
| 58 | + { "Uint32", [Uint32] }, |
| 59 | + { "Uint64", [Uint64] }, |
69 | 60 |
|
70 | | - { "Float", [_float] }, |
71 | | - { "Double", [_double] }, |
| 61 | + { "Float", [Float] }, |
| 62 | + { "Double", [Double] }, |
72 | 63 |
|
73 | | - { "Decimal", [_decimal, _decimalAsDouble, _decimalAsFloat, _biginteger] }, |
| 64 | + { "Date", [Date] }, |
| 65 | + { "DateTime", [DateTime] }, |
| 66 | + { "Timestamp", [Timestamp] }, |
| 67 | + { "Interval", [Interval] }, |
74 | 68 |
|
75 | | - { "Text", [_text] }, |
76 | | - { "String", [_ydbString] }, |
77 | | - { "Json", [_json] }, |
| 69 | + { "Text", [Text] }, |
| 70 | + { "Bytes", [Bytes] }, |
78 | 71 |
|
79 | | - { "Bytes", [_bytes] }, |
| 72 | + { "Decimal", [Decimal] }, |
80 | 73 |
|
81 | | - { "Date", [_date] }, |
82 | | - { "DateTime", [_dateTime] }, |
83 | | - { "Timestamp", [_timestamp] }, |
84 | | - { "Interval", [_interval] } |
| 74 | + { "Json", [Json] } |
85 | 75 | }; |
86 | | - var clrTypeMappings = new Dictionary<Type, RelationalTypeMapping> |
87 | | - { |
88 | | - { typeof(bool), _bool }, |
89 | 76 |
|
90 | | - { typeof(sbyte), _int8 }, |
91 | | - { typeof(short), _int16 }, |
92 | | - { typeof(int), _int32 }, |
93 | | - { typeof(long), _int64 }, |
| 77 | + private static readonly Dictionary<Type, RelationalTypeMapping> ClrTypeMapping = new() |
| 78 | + { |
| 79 | + { typeof(bool), Bool }, |
94 | 80 |
|
95 | | - { typeof(byte), _uint8 }, |
96 | | - { typeof(ushort), _uint16 }, |
97 | | - { typeof(uint), _uint32 }, |
98 | | - { typeof(ulong), _uint64 }, |
| 81 | + { typeof(sbyte), Int8 }, |
| 82 | + { typeof(short), Int16 }, |
| 83 | + { typeof(int), Int32 }, |
| 84 | + { typeof(long), Int64 }, |
99 | 85 |
|
100 | | - { typeof(float), _float }, |
101 | | - { typeof(double), _double }, |
102 | | - { typeof(decimal), _decimal }, |
| 86 | + { typeof(byte), Uint8 }, |
| 87 | + { typeof(ushort), Uint16 }, |
| 88 | + { typeof(uint), Uint32 }, |
| 89 | + { typeof(ulong), Uint64 }, |
103 | 90 |
|
104 | | - { typeof(string), _text }, |
105 | | - { typeof(byte[]), _bytes }, |
106 | | - { typeof(JsonElement), _json }, |
| 91 | + { typeof(float), Float }, |
| 92 | + { typeof(double), Double }, |
| 93 | + { typeof(decimal), Decimal }, |
107 | 94 |
|
108 | | - { typeof(DateOnly), _date }, |
109 | | - { typeof(DateTime), _timestamp }, |
110 | | - { typeof(TimeSpan), _interval } |
111 | | - }; |
| 95 | + { typeof(string), Text }, |
| 96 | + { typeof(byte[]), Bytes }, |
| 97 | + { typeof(JsonElement), Json }, |
112 | 98 |
|
113 | | - StoreTypeMapping = new ConcurrentDictionary<string, RelationalTypeMapping[]>(storeTypeMappings); |
114 | | - ClrTypeMapping = new ConcurrentDictionary<Type, RelationalTypeMapping>(clrTypeMappings); |
115 | | - } |
| 99 | + { typeof(DateOnly), Date }, |
| 100 | + { typeof(DateTime), Timestamp }, |
| 101 | + { typeof(TimeSpan), Interval } |
| 102 | + }; |
116 | 103 |
|
117 | 104 | protected override RelationalTypeMapping? FindMapping(in RelationalTypeMappingInfo mappingInfo) |
118 | | - => FindBaseMapping(mappingInfo) |
119 | | - ?? base.FindMapping(mappingInfo); |
| 105 | + => base.FindMapping(mappingInfo) ?? FindBaseMapping(mappingInfo)?.Clone(mappingInfo); |
120 | 106 |
|
121 | | - private RelationalTypeMapping? FindBaseMapping(in RelationalTypeMappingInfo mappingInfo) |
| 107 | + private static RelationalTypeMapping? FindBaseMapping(in RelationalTypeMappingInfo mappingInfo) |
122 | 108 | { |
123 | 109 | var clrType = mappingInfo.ClrType; |
124 | 110 | var storeTypeName = mappingInfo.StoreTypeName; |
125 | 111 |
|
126 | | - // Special case. |
127 | | - // If property has [YdbString] attribute then we use STRING type instead of TEXT |
128 | | - if (mappingInfo.StoreTypeName == "string") |
129 | | - { |
130 | | - return _ydbString; |
131 | | - } |
132 | | - |
133 | 112 | if (storeTypeName is null) |
134 | 113 | { |
135 | 114 | return clrType is null ? null : ClrTypeMapping.GetValueOrDefault(clrType); |
|
0 commit comments