diff --git a/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetObjectToStringTranslator.cs b/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetObjectToStringTranslator.cs index 43d17d4..961cc9e 100644 --- a/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetObjectToStringTranslator.cs +++ b/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetObjectToStringTranslator.cs @@ -19,40 +19,72 @@ namespace EntityFrameworkCore.Jet.Query.ExpressionTranslators.Internal { private readonly JetSqlExpressionFactory _sqlExpressionFactory; - private static readonly Type[] _typeMapping = - { - typeof(int), - typeof(long), - typeof(DateTime), - typeof(Guid), - typeof(bool), - typeof(byte), - typeof(byte[]), - typeof(double), - typeof(DateTimeOffset), - typeof(char), - typeof(short), - typeof(float), - typeof(decimal), - typeof(TimeSpan), - typeof(uint), - typeof(ushort), - typeof(ulong), - typeof(sbyte), - }; + private const int DefaultLength = 100; + + private static readonly Dictionary TypeMapping + = new() + { + { typeof(sbyte), "varchar(4)" }, + { typeof(byte), "varchar(3)" }, + { typeof(short), "varchar(6)" }, + { typeof(ushort), "varchar(5)" }, + { typeof(int), "varchar(11)" }, + { typeof(uint), "varchar(10)" }, + { typeof(long), "varchar(20)" }, + { typeof(ulong), "varchar(20)" }, + { typeof(float), $"varchar({DefaultLength})" }, + { typeof(double), $"varchar({DefaultLength})" }, + { typeof(decimal), $"varchar({DefaultLength})" }, + { typeof(char), "varchar(1)" }, + { typeof(DateTime), $"varchar({DefaultLength})" }, + { typeof(DateTimeOffset), $"varchar({DefaultLength})" }, + { typeof(TimeSpan), $"varchar({DefaultLength})" }, + { typeof(Guid), "varchar(36)" }, + { typeof(byte[]), $"varchar({DefaultLength})" } + }; public JetObjectToStringTranslator(SqlExpressionFactory sqlExpressionFactory) => _sqlExpressionFactory = (JetSqlExpressionFactory)sqlExpressionFactory; - public SqlExpression? Translate(SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) + public virtual SqlExpression? Translate( + SqlExpression? instance, + MethodInfo method, + IReadOnlyList arguments, + IDiagnosticsLogger logger) { - return method.Name == nameof(ToString) - && arguments.Count == 0 - && instance != null - && _typeMapping.Contains( - instance.Type - .UnwrapNullableType() - .UnwrapEnumType()) + if (instance == null || method.Name != nameof(ToString) || arguments.Count != 0) + { + return null; + } + + if (instance.Type == typeof(bool)) + { + if (instance is ColumnExpression columnExpression && columnExpression.IsNullable) + { + return _sqlExpressionFactory.Case( + new[] + { + new CaseWhenClause( + _sqlExpressionFactory.Equal(instance, _sqlExpressionFactory.Constant(false)), + _sqlExpressionFactory.Constant(false.ToString())), + new CaseWhenClause( + _sqlExpressionFactory.Equal(instance, _sqlExpressionFactory.Constant(true)), + _sqlExpressionFactory.Constant(true.ToString())) + }, + _sqlExpressionFactory.Constant(null)); + } + + return _sqlExpressionFactory.Case( + new[] + { + new CaseWhenClause( + _sqlExpressionFactory.Equal(instance, _sqlExpressionFactory.Constant(false)), + _sqlExpressionFactory.Constant(false.ToString())) + }, + _sqlExpressionFactory.Constant(true.ToString())); + } + + return TypeMapping.TryGetValue(instance.Type, out var storeType) ? _sqlExpressionFactory.Convert(instance, typeof(string)) : null; }