Skip to content
This repository was archived by the owner on Feb 1, 2025. It is now read-only.

Commit f0ca92a

Browse files
authored
Fix for #157. Improved DataType handling. (#159)
* Improved types detection. * Improved tests.
1 parent dddd88c commit f0ca92a

File tree

8 files changed

+136
-28
lines changed

8 files changed

+136
-28
lines changed

Source/LinqToDB.EntityFrameworkCore/EFCoreMetadataReader.cs

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
2+
using System.Collections;
23
using System.Collections.Concurrent;
34
using System.Collections.Generic;
5+
using System.Data;
46
using System.Linq;
57
using System.Linq.Expressions;
68
using System.Reflection;
@@ -135,6 +137,41 @@ static bool CompareProperty(IProperty property, MemberInfo memberInfo)
135137
{
136138
return CompareProperty(property.GetIdentifyingMemberInfo(), memberInfo);
137139
}
140+
141+
static DataType DbTypeToDataType(DbType dbType)
142+
{
143+
return dbType switch
144+
{
145+
DbType.AnsiString => DataType.VarChar,
146+
DbType.AnsiStringFixedLength => DataType.VarChar,
147+
DbType.Binary => DataType.Binary,
148+
DbType.Boolean => DataType.Boolean,
149+
DbType.Byte => DataType.Byte,
150+
DbType.Currency => DataType.Money,
151+
DbType.Date => DataType.Date,
152+
DbType.DateTime => DataType.DateTime,
153+
DbType.DateTime2 => DataType.DateTime2,
154+
DbType.DateTimeOffset => DataType.DateTimeOffset,
155+
DbType.Decimal => DataType.Decimal,
156+
DbType.Double => DataType.Double,
157+
DbType.Guid => DataType.Guid,
158+
DbType.Int16 => DataType.Int16,
159+
DbType.Int32 => DataType.Int32,
160+
DbType.Int64 => DataType.Int64,
161+
DbType.Object => DataType.Undefined,
162+
DbType.SByte => DataType.SByte,
163+
DbType.Single => DataType.Single,
164+
DbType.String => DataType.NVarChar,
165+
DbType.StringFixedLength => DataType.NVarChar,
166+
DbType.Time => DataType.Time,
167+
DbType.UInt16 => DataType.UInt16,
168+
DbType.UInt32 => DataType.UInt32,
169+
DbType.UInt64 => DataType.UInt64,
170+
DbType.VarNumeric => DataType.VarNumeric,
171+
DbType.Xml => DataType.Xml,
172+
_ => DataType.Undefined
173+
};
174+
}
138175

139176
public T[] GetAttributes<T>(Type type, MemberInfo memberInfo, bool inherit = true) where T : Attribute
140177
{
@@ -191,16 +228,34 @@ public T[] GetAttributes<T>(Type type, MemberInfo memberInfo, bool inherit = tru
191228
return false;
192229
});
193230

194-
return new T[]{(T)(Attribute) new ColumnAttribute
231+
var dataType = DataType.Undefined;
232+
233+
if (prop.GetTypeMapping() is RelationalTypeMapping typeMapping)
195234
{
196-
Name = prop.GetColumnName(storeObjectId!.Value),
197-
Length = prop.GetMaxLength() ?? 0,
198-
CanBeNull = prop.IsNullable,
199-
DbType = prop.GetColumnType(),
200-
IsPrimaryKey = isPrimaryKey,
201-
PrimaryKeyOrder = primaryKeyOrder,
202-
IsIdentity = isIdentity,
203-
}};
235+
if (typeMapping.DbType != null)
236+
{
237+
dataType = DbTypeToDataType(typeMapping.DbType.Value);
238+
}
239+
else
240+
{
241+
dataType = SqlDataType.GetDataType(typeMapping.ClrType).Type.DataType;
242+
}
243+
}
244+
245+
return new T[]
246+
{
247+
(T)(Attribute)new ColumnAttribute
248+
{
249+
Name = prop.GetColumnName(storeObjectId!.Value),
250+
Length = prop.GetMaxLength() ?? 0,
251+
CanBeNull = prop.IsNullable,
252+
DbType = prop.GetColumnType(),
253+
DataType = dataType,
254+
IsPrimaryKey = isPrimaryKey,
255+
PrimaryKeyOrder = primaryKeyOrder,
256+
IsIdentity = isIdentity,
257+
}
258+
};
204259
}
205260
}
206261

Tests/LinqToDB.EntityFrameworkCore.BaseTests/Models/ForMapping/ForMappingContextBase.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ protected ForMappingContextBase(DbContextOptions options) : base(options)
1111
public DbSet<WithIdentity> WithIdentity { get; set; } = null!;
1212
public DbSet<NoIdentity> NoIdentity { get; set; } = null!;
1313
public DbSet<UIntTable> UIntTable { get; set; } = null!;
14+
public DbSet<StringTypes> StringTypes { get; set; } = null!;
1415
}
1516
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System.ComponentModel.DataAnnotations;
2+
3+
namespace LinqToDB.EntityFrameworkCore.BaseTests.Models.ForMapping
4+
{
5+
public class StringTypes
6+
{
7+
[Key]
8+
public int Id { get; set; }
9+
10+
public string? AnsiString { get; set; }
11+
12+
public string? UnicodeString { get; set; }
13+
}
14+
}

Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/ForMappingTests.cs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using FluentAssertions;
5-
using LinqToDB.Data;
6-
using LinqToDB.EntityFrameworkCore.BaseTests;
1+
using LinqToDB.EntityFrameworkCore.BaseTests;
72
using LinqToDB.EntityFrameworkCore.BaseTests.Models.ForMapping;
83
using LinqToDB.EntityFrameworkCore.PomeloMySql.Tests.Models.ForMapping;
94
using Microsoft.EntityFrameworkCore;
@@ -12,6 +7,8 @@ namespace LinqToDB.EntityFrameworkCore.PomeloMySql.Tests
127
{
138
public class ForMappingTests : ForMappingTestsBase
149
{
10+
private bool _isDbCreated;
11+
1512
public override ForMappingContextBase CreateContext()
1613
{
1714
var optionsBuilder = new DbContextOptionsBuilder<ForMappingContext>();
@@ -21,8 +18,13 @@ public override ForMappingContextBase CreateContext()
2118
var options = optionsBuilder.Options;
2219
var ctx = new ForMappingContext(options);
2320

24-
//ctx.Database.EnsureDeleted();
25-
ctx.Database.EnsureCreated();
21+
if (!_isDbCreated)
22+
{
23+
ctx.Database.EnsureDeleted();
24+
ctx.Database.EnsureCreated();
25+
26+
_isDbCreated = true;
27+
}
2628

2729
return ctx;
2830
}

Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/ForMappingTests.cs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using FluentAssertions;
5-
using LinqToDB.Data;
6-
using LinqToDB.EntityFrameworkCore.BaseTests;
1+
using LinqToDB.EntityFrameworkCore.BaseTests;
72
using LinqToDB.EntityFrameworkCore.BaseTests.Models.ForMapping;
83
using LinqToDB.EntityFrameworkCore.PostgreSQL.Tests.Models.ForMapping;
94
using Microsoft.EntityFrameworkCore;
@@ -14,6 +9,8 @@ namespace LinqToDB.EntityFrameworkCore.PostgreSQL.Tests
149
[TestFixture]
1510
public class ForMappingTests : ForMappingTestsBase
1611
{
12+
private bool _isDbCreated;
13+
1714
public override ForMappingContextBase CreateContext()
1815
{
1916
var optionsBuilder = new DbContextOptionsBuilder<ForMappingContext>();
@@ -23,8 +20,13 @@ public override ForMappingContextBase CreateContext()
2320
var options = optionsBuilder.Options;
2421
var ctx = new ForMappingContext(options);
2522

26-
ctx.Database.EnsureDeleted();
27-
ctx.Database.EnsureCreated();
23+
if (!_isDbCreated)
24+
{
25+
ctx.Database.EnsureDeleted();
26+
ctx.Database.EnsureCreated();
27+
28+
_isDbCreated = true;
29+
}
2830

2931
return ctx;
3032
}

Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/ForMappingTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public override ForMappingContextBase CreateContext()
1818
var options = optionsBuilder.Options;
1919
var ctx = new ForMappingContext(options);
2020

21+
ctx.Database.OpenConnection();
2122
ctx.Database.EnsureCreated();
2223

2324
return ctx;

Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ForMappingTests.cs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using LinqToDB.EntityFrameworkCore.BaseTests;
1+
using System.Linq;
2+
using FluentAssertions;
3+
using LinqToDB.EntityFrameworkCore.BaseTests;
24
using LinqToDB.EntityFrameworkCore.BaseTests.Models.ForMapping;
35
using LinqToDB.EntityFrameworkCore.SqlServer.Tests.Models.ForMapping;
46
using Microsoft.EntityFrameworkCore;
@@ -9,6 +11,8 @@ namespace LinqToDB.EntityFrameworkCore.SqlServer.Tests
911
[TestFixture]
1012
public class ForMappingTests : ForMappingTestsBase
1113
{
14+
private bool _isDbCreated;
15+
1216
public override ForMappingContextBase CreateContext()
1317
{
1418
var optionsBuilder = new DbContextOptionsBuilder<ForMappingContext>();
@@ -18,10 +22,32 @@ public override ForMappingContextBase CreateContext()
1822
var options = optionsBuilder.Options;
1923
var ctx = new ForMappingContext(options);
2024

21-
//ctx.Database.EnsureDeleted();
22-
ctx.Database.EnsureCreated();
25+
if (!_isDbCreated)
26+
{
27+
ctx.Database.EnsureDeleted();
28+
ctx.Database.EnsureCreated();
29+
30+
_isDbCreated = true;
31+
}
2332

2433
return ctx;
2534
}
35+
36+
[Test]
37+
public void TestStringMappings()
38+
{
39+
using (var db = CreateContext())
40+
{
41+
var ms = LinqToDBForEFTools.GetMappingSchema(db.Model, db);
42+
var ed = ms.GetEntityDescriptor(typeof(StringTypes));
43+
44+
ed.Columns.First(c => c.MemberName == nameof(StringTypes.AnsiString)).DataType.Should()
45+
.Be(DataType.VarChar);
46+
47+
ed.Columns.First(c => c.MemberName == nameof(StringTypes.UnicodeString)).DataType.Should()
48+
.Be(DataType.NVarChar);
49+
}
50+
51+
}
2652
}
2753
}

Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/ForMapping/ForMappingContext.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
2525
{
2626
b.HasKey(e => e.Id);
2727
});
28+
29+
modelBuilder.Entity<StringTypes>(b =>
30+
{
31+
b.Property(e => e.AnsiString).HasMaxLength(50).IsUnicode(false);
32+
b.Property(e => e.UnicodeString).HasMaxLength(50).IsUnicode();
33+
}
34+
);
2835
}
2936
}
3037
}

0 commit comments

Comments
 (0)