diff --git a/src/EFCore.Jet/Migrations/Internal/JetHistoryRepository.cs b/src/EFCore.Jet/Migrations/Internal/JetHistoryRepository.cs index 37f69aa..f73f4cf 100644 --- a/src/EFCore.Jet/Migrations/Internal/JetHistoryRepository.cs +++ b/src/EFCore.Jet/Migrations/Internal/JetHistoryRepository.cs @@ -71,11 +71,11 @@ namespace EntityFrameworkCore.Jet.Migrations.Internal .Append(", ") .Append(SqlGenerationHelper.DelimitIdentifier(ProductVersionColumnName)) .AppendLine(")") - .Append("VALUES ('") + .Append("VALUES (") .Append(stringTypeMapping.GenerateSqlLiteral(row.MigrationId)) - .Append("', '") + .Append(", ") .Append(stringTypeMapping.GenerateSqlLiteral(row.ProductVersion)) - .AppendLine("');") + .AppendLine(");") .ToString(); } @@ -93,9 +93,9 @@ namespace EntityFrameworkCore.Jet.Migrations.Internal .AppendLine(SqlGenerationHelper.DelimitIdentifier(TableName)) .Append("WHERE ") .Append(SqlGenerationHelper.DelimitIdentifier(MigrationIdColumnName)) - .Append(" = '") + .Append(" = ") .Append(stringTypeMapping.GenerateSqlLiteral(migrationId)) - .AppendLine("';") + .AppendLine(";") .ToString(); } diff --git a/src/EFCore.Jet/Storage/Internal/JetByteArrayTypeMapping.cs b/src/EFCore.Jet/Storage/Internal/JetByteArrayTypeMapping.cs index f788135..7afddfc 100644 --- a/src/EFCore.Jet/Storage/Internal/JetByteArrayTypeMapping.cs +++ b/src/EFCore.Jet/Storage/Internal/JetByteArrayTypeMapping.cs @@ -6,6 +6,7 @@ using System.Data.Common; using System.Globalization; using System.Text; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.Storage; namespace EntityFrameworkCore.Jet.Storage.Internal @@ -16,21 +17,35 @@ namespace EntityFrameworkCore.Jet.Storage.Internal /// public class JetByteArrayTypeMapping : ByteArrayTypeMapping { - private readonly int _maxSpecificSize; /// - /// Initializes a new instance of the class. + /// This API supports the Entity Framework Core infrastructure and is not intended to be used + /// directly from your code. This API may change or be removed in future releases. /// - /// The name of the database type. - /// The to be used. - /// The size of data the property is configured to store, or null if no size is configured. public JetByteArrayTypeMapping( - [NotNull] string storeType, - DbType? dbType = System.Data.DbType.Binary, - int? size = null) - : base(storeType, dbType, size) + [CanBeNull] string storeType = null, + int? size = null, + bool fixedLength = false, + [CanBeNull] ValueComparer comparer = null, + StoreTypePostfix? storeTypePostfix = null) + : base( + new RelationalTypeMappingParameters( + new CoreTypeMappingParameters(typeof(byte[]), null, comparer), + storeType ?? (fixedLength ? "binary" : "varbinary"), + storeTypePostfix ?? StoreTypePostfix.Size, + System.Data.DbType.Binary, + size: size, + fixedLength: fixedLength)) + { + } + + /// + /// This API supports the Entity Framework Core infrastructure and is not intended to be used + /// directly from your code. This API may change or be removed in future releases. + /// + protected JetByteArrayTypeMapping(RelationalTypeMappingParameters parameters) + : base(parameters) { - _maxSpecificSize = CalculateSize(size); } private static int CalculateSize(int? size) @@ -41,10 +56,7 @@ namespace EntityFrameworkCore.Jet.Storage.Internal /// directly from your code. This API may change or be removed in future releases. /// public override RelationalTypeMapping Clone(string storeType, int? size) - => new JetByteArrayTypeMapping( - storeType, - DbType, - size); + => new JetByteArrayTypeMapping(storeType, size, IsFixedLength, Comparer, StoreTypePostfix); /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used @@ -59,9 +71,10 @@ namespace EntityFrameworkCore.Jet.Storage.Internal var value = parameter.Value; var length = (value as string)?.Length ?? (value as byte[])?.Length; + int maxSpecificSize = CalculateSize(Size); - parameter.Size = value == null || value == DBNull.Value || length != null && length <= _maxSpecificSize - ? _maxSpecificSize + parameter.Size = value == null || value == DBNull.Value || length != null && length <= maxSpecificSize + ? maxSpecificSize : -1; } diff --git a/src/EFCore.Jet/Storage/Internal/JetTypeMappingSource.cs b/src/EFCore.Jet/Storage/Internal/JetTypeMappingSource.cs index ff3a250..1698d6d 100644 --- a/src/EFCore.Jet/Storage/Internal/JetTypeMappingSource.cs +++ b/src/EFCore.Jet/Storage/Internal/JetTypeMappingSource.cs @@ -17,7 +17,7 @@ namespace EntityFrameworkCore.Jet.Storage.Internal public class JetTypeMappingSource : RelationalTypeMappingSource { private readonly JetStringTypeMapping _unboundedUnicodeString - = new JetStringTypeMapping("text"); + = new JetStringTypeMapping("text", unicode: true); private readonly JetStringTypeMapping _unboundedAnsiString = new JetStringTypeMapping("text"); @@ -26,7 +26,7 @@ namespace EntityFrameworkCore.Jet.Storage.Internal = new JetByteArrayTypeMapping("image"); private readonly JetByteArrayTypeMapping _rowversion - = new JetByteArrayTypeMapping("varbinary(8)", dbType: DbType.Binary, size: 8); + = new JetByteArrayTypeMapping("varbinary(8)", size: 8); private readonly IntTypeMapping _int = new IntTypeMapping("int", DbType.Int32); @@ -41,10 +41,10 @@ namespace EntityFrameworkCore.Jet.Storage.Internal //private readonly JetBoolTypeMapping _bool = new JetBoolTypeMapping("bit"); private readonly JetStringTypeMapping _fixedLengthUnicodeString - = new JetStringTypeMapping("char"); + = new JetStringTypeMapping("char", unicode: true); private readonly JetStringTypeMapping _variableLengthUnicodeString - = new JetStringTypeMapping("varchar"); + = new JetStringTypeMapping("varchar", unicode: true); // Jet does not support ANSI strings /* @@ -78,7 +78,7 @@ namespace EntityFrameworkCore.Jet.Storage.Internal private readonly TimeSpanTypeMapping _time = new JetTimeSpanTypeMapping("datetime"); - private readonly JetStringTypeMapping _xml = new JetStringTypeMapping("text"); + private readonly JetStringTypeMapping _xml = new JetStringTypeMapping("text", unicode: true); private readonly Dictionary _storeTypeMappings; private readonly Dictionary _clrTypeMappings; @@ -207,7 +207,8 @@ namespace EntityFrameworkCore.Jet.Storage.Internal var storeTypeName = mappingInfo.StoreTypeName; var storeTypeNameBase = mappingInfo.StoreTypeNameBase; - clrType = clrType.UnwrapNullableType().UnwrapEnumType(); + // Fixes: #22 + //clrType = clrType.UnwrapNullableType().UnwrapEnumType(); if (storeTypeName != null) @@ -252,7 +253,7 @@ namespace EntityFrameworkCore.Jet.Storage.Internal return size == null ? isAnsi ? _unboundedAnsiString : _unboundedUnicodeString - : new JetStringTypeMapping(storeType: isFixedLength ? "char" : "varchar", size: size); + : new JetStringTypeMapping(storeType: isFixedLength ? "char" : "varchar", size: size, unicode: true); } if (clrType == typeof(byte[])) diff --git a/test/EFCore.Jet.FunctionalTests/TestUtilities/JetTestStore.cs b/test/EFCore.Jet.FunctionalTests/TestUtilities/JetTestStore.cs index 63282a2..e9f89a8 100644 --- a/test/EFCore.Jet.FunctionalTests/TestUtilities/JetTestStore.cs +++ b/test/EFCore.Jet.FunctionalTests/TestUtilities/JetTestStore.cs @@ -75,7 +75,7 @@ namespace EntityFramework.Jet.FunctionalTests name = "scratch-" + Interlocked.Increment(ref _scratchCount); } while (File.Exists(name + ".accdb")); - + JetConnection.CreateEmptyDatabase(JetConnection.GetConnectionString(name + ".accdb")); return new JetTestStore(name, deleteDatabase: true); } @@ -214,28 +214,39 @@ namespace EntityFramework.Jet.FunctionalTests public int ExecuteNonQuery(string sql, params object[] parameters) { + var connectionState = Connection.State; + if (connectionState != ConnectionState.Open) + Connection.Open(); + int result; using (var command = CreateCommand(Connection, sql, parameters)) { - return command.ExecuteNonQuery(); + result = command.ExecuteNonQuery(); } + if (connectionState != ConnectionState.Open) + Connection.Close(); + return result; } public IEnumerable Query(string sql, params object[] parameters) { + var connectionState = Connection.State; + if (connectionState != ConnectionState.Open) + Connection.Open(); + + var results = Enumerable.Empty(); using (var command = CreateCommand(Connection, sql, parameters)) { using (var dataReader = command.ExecuteReader()) { - var results = Enumerable.Empty(); - while (dataReader.Read()) { results = results.Concat(new[] { dataReader.GetFieldValue(0) }); } - - return results; } } + if (connectionState != ConnectionState.Open) + Connection.Close(); + return results; } public bool Exists() @@ -262,7 +273,7 @@ namespace EntityFramework.Jet.FunctionalTests Transaction?.Dispose(); Connection?.Dispose(); if (_deleteDatabase) - ((JetConnection)Connection)?.DropDatabase(false); + JetConnection.DropDatabase(ConnectionString); base.Dispose(); } diff --git a/test/EFCore.Jet.Tests/JetTypeMapperTest.cs b/test/EFCore.Jet.Tests/JetTypeMapperTest.cs index 05e537d..6c97bdc 100644 --- a/test/EFCore.Jet.Tests/JetTypeMapperTest.cs +++ b/test/EFCore.Jet.Tests/JetTypeMapperTest.cs @@ -65,7 +65,7 @@ namespace EntityFrameworkCore.Jet.Tests public void Does_simple_Jet_mappings_to_DbTypes() { Assert.Equal(DbType.Int32, GetTypeMapping(typeof(int)).DbType); - Assert.Equal(DbType.String, GetTypeMapping(typeof(string)).DbType); + Assert.Null(GetTypeMapping(typeof(string)).DbType); Assert.Equal(DbType.Binary, GetTypeMapping(typeof(byte[])).DbType); Assert.Equal(DbType.Guid, GetTypeMapping(typeof(Guid)).DbType); Assert.Equal(DbType.Byte, GetTypeMapping(typeof(byte)).DbType); @@ -73,7 +73,7 @@ namespace EntityFrameworkCore.Jet.Tests Assert.Equal(DbType.Boolean, GetTypeMapping(typeof(bool)).DbType); Assert.Equal(DbType.Int16, GetTypeMapping(typeof(short)).DbType); Assert.Equal(DbType.Int64, GetTypeMapping(typeof(long)).DbType); - Assert.Equal(DbType.Single, GetTypeMapping(typeof(float)).DbType); + Assert.Null(GetTypeMapping(typeof(float)).DbType); Assert.Equal(DbType.DateTime, GetTypeMapping(typeof(DateTime)).DbType); } @@ -81,7 +81,7 @@ namespace EntityFrameworkCore.Jet.Tests public void Does_simple_Jet_mappings_for_nullable_CLR_types_to_DbTypes() { Assert.Equal(DbType.Int32, GetTypeMapping(typeof(int?)).DbType); - Assert.Equal(DbType.String, GetTypeMapping(typeof(string)).DbType); + Assert.Null(GetTypeMapping(typeof(string)).DbType); Assert.Equal(DbType.Binary, GetTypeMapping(typeof(byte[])).DbType); Assert.Equal(DbType.Guid, GetTypeMapping(typeof(Guid?)).DbType); Assert.Equal(DbType.Byte, GetTypeMapping(typeof(byte?)).DbType); @@ -89,7 +89,7 @@ namespace EntityFrameworkCore.Jet.Tests Assert.Equal(DbType.Boolean, GetTypeMapping(typeof(bool?)).DbType); Assert.Equal(DbType.Int16, GetTypeMapping(typeof(short?)).DbType); Assert.Equal(DbType.Int64, GetTypeMapping(typeof(long?)).DbType); - Assert.Equal(DbType.Single, GetTypeMapping(typeof(float?)).DbType); + Assert.Null(GetTypeMapping(typeof(float?)).DbType); Assert.Equal(DbType.DateTime, GetTypeMapping(typeof(DateTime?)).DbType); } @@ -129,7 +129,7 @@ namespace EntityFrameworkCore.Jet.Tests { var typeMapping = GetTypeMapping(typeof(string)); - Assert.Equal(DbType.String, typeMapping.DbType); + Assert.Null(typeMapping.DbType); Assert.Equal("text", typeMapping.StoreType); Assert.Equal(null, typeMapping.Size); Assert.True(typeMapping.IsUnicode); @@ -142,7 +142,7 @@ namespace EntityFrameworkCore.Jet.Tests { var typeMapping = GetTypeMapping(typeof(string), null, 3); - //Assert.Null(typeMapping.DbType); + Assert.Null(typeMapping.DbType); Assert.Equal("varchar(3)", typeMapping.StoreType); Assert.Equal(3, typeMapping.Size); Assert.True(typeMapping.IsUnicode); @@ -154,7 +154,7 @@ namespace EntityFrameworkCore.Jet.Tests { var typeMapping = GetTypeMapping(typeof(string), isNullable: false); - Assert.Equal(DbType.String, typeMapping.DbType); + Assert.Null(typeMapping.DbType); Assert.Equal("text", typeMapping.StoreType); Assert.Equal(null, typeMapping.Size); Assert.True(typeMapping.IsUnicode); @@ -189,7 +189,7 @@ namespace EntityFrameworkCore.Jet.Tests var typeMapping = GetMapping(property); - Assert.Equal(DbType.String, typeMapping.DbType); + Assert.Null(typeMapping.DbType); Assert.Equal("varchar(255)", typeMapping.StoreType); Assert.Equal(255, typeMapping.Size); Assert.True(typeMapping.IsUnicode); @@ -207,7 +207,7 @@ namespace EntityFrameworkCore.Jet.Tests var typeMapping = GetMapping(fkProperty); - Assert.Equal(DbType.String, typeMapping.DbType); + Assert.Null(typeMapping.DbType); Assert.Equal("varchar(255)", typeMapping.StoreType); Assert.Equal(255, typeMapping.Size); Assert.True(typeMapping.IsUnicode); @@ -226,7 +226,7 @@ namespace EntityFrameworkCore.Jet.Tests var typeMapping = GetMapping(fkProperty); - Assert.Equal(DbType.String, typeMapping.DbType); + Assert.Null(typeMapping.DbType); Assert.Equal("varchar(255)", typeMapping.StoreType); Assert.Equal(255, typeMapping.Size); Assert.True(typeMapping.IsUnicode); @@ -242,7 +242,7 @@ namespace EntityFrameworkCore.Jet.Tests var typeMapping = GetMapping(property); - Assert.Equal(DbType.String, typeMapping.DbType); + Assert.Null(typeMapping.DbType); Assert.Equal("varchar(255)", typeMapping.StoreType); Assert.Equal(255, typeMapping.Size); Assert.True(typeMapping.IsUnicode); @@ -419,7 +419,8 @@ namespace EntityFrameworkCore.Jet.Tests { Assert.Equal("NULL", GetMappingForValue(null).StoreType); Assert.Equal("NULL", GetMappingForValue(DBNull.Value).StoreType); - Assert.Equal("NULL", RelationalTypeMapperExtensions.GetMappingForValue(null, "Itz").StoreType); + // Now no TypeMapper no party + //Assert.Equal("NULL", RelationalTypeMapperExtensions.GetMappingForValue(null, "Itz").StoreType); } private enum LongEnum : long