diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/FirebirdSql.EntityFrameworkCore.Firebird.csproj b/src/FirebirdSql.EntityFrameworkCore.Firebird/FirebirdSql.EntityFrameworkCore.Firebird.csproj
index 4baf2bd0c..eaf71ce5e 100644
--- a/src/FirebirdSql.EntityFrameworkCore.Firebird/FirebirdSql.EntityFrameworkCore.Firebird.csproj
+++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/FirebirdSql.EntityFrameworkCore.Firebird.csproj
@@ -31,11 +31,13 @@
+
+
-
+
-
+
diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Infrastructure/FbDbContextOptionsBuilder.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Infrastructure/FbDbContextOptionsBuilder.cs
index 04e09712b..639560e35 100644
--- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Infrastructure/FbDbContextOptionsBuilder.cs
+++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Infrastructure/FbDbContextOptionsBuilder.cs
@@ -32,4 +32,10 @@ public virtual FbDbContextOptionsBuilder WithExplicitParameterTypes(bool explici
public virtual FbDbContextOptionsBuilder WithExplicitStringLiteralTypes(bool explicitStringLiteralTypes = true)
=> WithOption(e => e.WithExplicitStringLiteralTypes(explicitStringLiteralTypes));
+
+ public virtual FbDbContextOptionsBuilder WithUseCaseInsensitive(bool useCaseInsensitive = false)
+ => WithOption(e => e.WithUseCaseInsensitive(useCaseInsensitive));
+
+ public virtual FbDbContextOptionsBuilder WithIsUnicode(bool isUnicode = false)
+ => WithOption(e => e.WithIsUnicode(isUnicode));
}
diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Infrastructure/Internal/FbOptionsExtension.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Infrastructure/Internal/FbOptionsExtension.cs
index e03e20674..b0ea3e6c9 100644
--- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Infrastructure/Internal/FbOptionsExtension.cs
+++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Infrastructure/Internal/FbOptionsExtension.cs
@@ -28,7 +28,8 @@ public class FbOptionsExtension : RelationalOptionsExtension
DbContextOptionsExtensionInfo _info;
bool? _explicitParameterTypes;
bool? _explicitStringLiteralTypes;
-
+ bool? _useCaseInsensitive;
+ bool? _isUnicode;
public FbOptionsExtension()
{ }
@@ -37,6 +38,8 @@ public FbOptionsExtension(FbOptionsExtension copyFrom)
{
_explicitParameterTypes = copyFrom._explicitParameterTypes;
_explicitStringLiteralTypes = copyFrom._explicitStringLiteralTypes;
+ _useCaseInsensitive = copyFrom._useCaseInsensitive;
+ _isUnicode = copyFrom._isUnicode;
}
protected override RelationalOptionsExtension Clone()
@@ -48,6 +51,8 @@ public override void ApplyServices(IServiceCollection services)
public override DbContextOptionsExtensionInfo Info => _info ??= new ExtensionInfo(this);
public virtual bool? ExplicitParameterTypes => _explicitParameterTypes;
public virtual bool? ExplicitStringLiteralTypes => _explicitStringLiteralTypes;
+ public virtual bool? UseCaseInsensitive => _useCaseInsensitive;
+ public virtual bool? IsUnicode => _isUnicode;
public virtual FbOptionsExtension WithExplicitParameterTypes(bool explicitParameterTypes)
{
@@ -63,6 +68,20 @@ public virtual FbOptionsExtension WithExplicitStringLiteralTypes(bool explicitSt
return clone;
}
+ public virtual FbOptionsExtension WithUseCaseInsensitive(bool useCaseInsensitive)
+ {
+ var clone = (FbOptionsExtension)Clone();
+ clone._useCaseInsensitive = useCaseInsensitive;
+ return clone;
+ }
+
+ public virtual FbOptionsExtension WithIsUnicode(bool isUnicode)
+ {
+ var clone = (FbOptionsExtension)Clone();
+ clone._isUnicode = isUnicode;
+ return clone;
+ }
+
sealed class ExtensionInfo : RelationalExtensionInfo
{
int? _serviceProviderHash;
@@ -78,7 +97,6 @@ public override int GetServiceProviderHashCode()
return _serviceProviderHash ??= HashCode.Combine(base.GetServiceProviderHashCode(), Extension._explicitParameterTypes, Extension._explicitStringLiteralTypes);
}
- public override void PopulateDebugInfo(IDictionary debugInfo)
- { }
+ public override void PopulateDebugInfo(IDictionary debugInfo) => debugInfo["FirebirdSQL"] = "1.0";
}
}
diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Infrastructure/Internal/IFbOptions.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Infrastructure/Internal/IFbOptions.cs
index 7cd1447ea..62fddcad0 100644
--- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Infrastructure/Internal/IFbOptions.cs
+++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Infrastructure/Internal/IFbOptions.cs
@@ -23,4 +23,6 @@ public interface IFbOptions : ISingletonOptions
{
bool ExplicitParameterTypes { get; }
bool ExplicitStringLiteralTypes { get; }
+ bool UseCaseInsensitive { get; }
+ bool IsUnicode { get; }
}
diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Internal/FbOptions.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Internal/FbOptions.cs
index f87591877..926ed8b85 100644
--- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Internal/FbOptions.cs
+++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Internal/FbOptions.cs
@@ -31,6 +31,8 @@ public virtual void Initialize(IDbContextOptions options)
ExplicitParameterTypes = fbOptions.ExplicitParameterTypes ?? true;
ExplicitStringLiteralTypes = fbOptions.ExplicitStringLiteralTypes ?? true;
+ UseCaseInsensitive = fbOptions.UseCaseInsensitive ?? true;
+ IsUnicode = fbOptions.IsUnicode ?? true;
}
public virtual void Validate(IDbContextOptions options)
@@ -45,8 +47,18 @@ public virtual void Validate(IDbContextOptions options)
{
throw new InvalidOperationException($"A call was made to '{nameof(FbDbContextOptionsBuilder.WithExplicitStringLiteralTypes)}' that changed an option that must be constant within a service provider, but Entity Framework is not building its own internal service provider. Either allow EF to build the service provider by removing the call to '{nameof(DbContextOptionsBuilder.UseInternalServiceProvider)}', or ensure that the configuration for '{nameof(FbDbContextOptionsBuilder.WithExplicitStringLiteralTypes)}' does not change for all uses of a given service provider passed to '{nameof(DbContextOptionsBuilder.UseInternalServiceProvider)}'.");
}
+ if (UseCaseInsensitive != (fbOptions.UseCaseInsensitive ?? true))
+ {
+ throw new InvalidOperationException($"A call was made to '{nameof(FbDbContextOptionsBuilder.WithUseCaseInsensitive)}' that changed an option that must be constant within a service provider, but Entity Framework is not building its own internal service provider. Either allow EF to build the service provider by removing the call to '{nameof(DbContextOptionsBuilder.UseInternalServiceProvider)}', or ensure that the configuration for '{nameof(FbDbContextOptionsBuilder.WithExplicitStringLiteralTypes)}' does not change for all uses of a given service provider passed to '{nameof(DbContextOptionsBuilder.UseInternalServiceProvider)}'.");
+ }
+ if (IsUnicode != (fbOptions.IsUnicode ?? true))
+ {
+ throw new InvalidOperationException($"A call was made to '{nameof(FbDbContextOptionsBuilder.WithIsUnicode)}' that changed an option that must be constant within a service provider, but Entity Framework is not building its own internal service provider. Either allow EF to build the service provider by removing the call to '{nameof(DbContextOptionsBuilder.UseInternalServiceProvider)}', or ensure that the configuration for '{nameof(FbDbContextOptionsBuilder.WithExplicitStringLiteralTypes)}' does not change for all uses of a given service provider passed to '{nameof(DbContextOptionsBuilder.UseInternalServiceProvider)}'.");
+ }
}
public virtual bool ExplicitParameterTypes { get; private set; }
public virtual bool ExplicitStringLiteralTypes { get; private set; }
+ public virtual bool UseCaseInsensitive { get; private set; }
+ public virtual bool IsUnicode { get; private set; }
}
diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs
index 2e899cea6..19ea8ef4f 100644
--- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs
+++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs
@@ -39,6 +39,32 @@ public FbQuerySqlGenerator(QuerySqlGeneratorDependencies dependencies, IFbOption
_fbOptions = fbOptions;
}
+ protected override Expression VisitBinary(BinaryExpression binaryExpression)
+ {
+ // Garante parênteses em volta de operações lógicas para manter a precedência do Front-end
+ Sql.Append("(");
+ Visit(binaryExpression.Left);
+
+ var op = binaryExpression.NodeType switch
+ {
+ ExpressionType.AndAlso => " AND ",
+ ExpressionType.OrElse => " OR ",
+ ExpressionType.Equal => " = ",
+ ExpressionType.NotEqual => " <> ",
+ ExpressionType.LessThan => " < ",
+ ExpressionType.GreaterThan => " > ",
+ ExpressionType.LessThanOrEqual => " <= ",
+ ExpressionType.GreaterThanOrEqual => " >= ",
+ _ => base.VisitBinary(binaryExpression) == null ? "" : "" // Fallback padrão
+ };
+
+ Sql.Append(op);
+ Visit(binaryExpression.Right);
+ Sql.Append(")");
+
+ return binaryExpression;
+ }
+
protected override Expression VisitSqlUnary(SqlUnaryExpression sqlUnaryExpression)
{
if (sqlUnaryExpression.OperatorType == ExpressionType.Not && sqlUnaryExpression.TypeMapping.ClrType != typeof(bool))
@@ -143,22 +169,60 @@ protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpres
Sql.Append(")");
return sqlBinaryExpression;
}
+ //else if (sqlBinaryExpression.OperatorType == ExpressionType.AndAlso)
+ //{
+ // if (sqlBinaryExpression.Left.Type == typeof(bool))
+ // {
+ // var left = Sql.Append("UPPER(");
+ // Visit(sqlBinaryExpression.Left);
+ // Sql.Append(")");
+
+ // Sql.Append(GetOperatorType(sqlBinaryExpression.OperatorType));
+
+ // Sql.Append("UPPER(");
+ // Visit(sqlBinaryExpression.Right);
+ // Sql.Append(")");
+
+ // return sqlBinaryExpression;
+ // }
+ // return base.VisitSqlBinary(sqlBinaryExpression);
+ //}
else
{
return base.VisitSqlBinary(sqlBinaryExpression);
}
+ }
- void BooleanToIntegralAndVisit(SqlExpression expression)
+ protected override Expression VisitColumn(ColumnExpression columnExpression)
+ {
+ if (columnExpression.Type == typeof(string))
{
- Sql.Append("IIF(");
- Visit(expression);
- Sql.Append(", 1, 0)");
+ var isUpper = _fbOptions.UseCaseInsensitive;
+
+ if (isUpper)
+ {
+ Sql.Append("UPPER(");
+ }
+ base.VisitColumn(columnExpression);
+ if (isUpper)
+ {
+ Sql.Append(")");
+ }
+ return columnExpression;
}
+ return base.VisitColumn(columnExpression);
}
protected override Expression VisitSqlParameter(SqlParameterExpression sqlParameterExpression)
{
+ var isUpper = _fbOptions.UseCaseInsensitive && sqlParameterExpression.Type == typeof(string);
+
var shouldExplicitParameterTypes = _fbOptions.ExplicitParameterTypes;
+ if (isUpper)
+ {
+ Sql.Append("UPPER(");
+ }
+
if (shouldExplicitParameterTypes)
{
Sql.Append("CAST(");
@@ -169,8 +233,10 @@ protected override Expression VisitSqlParameter(SqlParameterExpression sqlParame
Sql.Append(" AS ");
if (sqlParameterExpression.Type == typeof(string))
{
- var isUnicode = FbTypeMappingSource.IsUnicode(sqlParameterExpression.TypeMapping);
- Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringParameterQueryType(isUnicode));
+ var isUnicode = FbTypeMappingSource.IsUnicode(sqlParameterExpression.TypeMapping, _fbOptions) && _fbOptions.IsUnicode;
+ var storeTypeNameBase = sqlParameterExpression.TypeMapping.StoreTypeNameBase;
+ var size = sqlParameterExpression.TypeMapping.Size ?? 0;
+ Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringParameterQueryType(isUnicode, storeTypeNameBase, size));
}
else
{
@@ -178,6 +244,10 @@ protected override Expression VisitSqlParameter(SqlParameterExpression sqlParame
}
Sql.Append(")");
}
+ if (isUpper)
+ {
+ Sql.Append(")");
+ }
return sqlParameterExpression;
}
@@ -191,9 +261,12 @@ protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstant
base.VisitSqlConstant(sqlConstantExpression);
if (shouldExplicitStringLiteralTypes)
{
- var isUnicode = FbTypeMappingSource.IsUnicode(sqlConstantExpression.TypeMapping);
+ var isUnicode = FbTypeMappingSource.IsUnicode(sqlConstantExpression.TypeMapping, _fbOptions) && _fbOptions.IsUnicode;
+ var storeTypeNameBase = sqlConstantExpression.TypeMapping.StoreTypeNameBase;
+ var size = sqlConstantExpression.TypeMapping.Size ?? 0;
+
Sql.Append(" AS ");
- Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringLiteralQueryType(sqlConstantExpression.Value as string, isUnicode));
+ Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringLiteralQueryType(sqlConstantExpression.Value as string, isUnicode, storeTypeNameBase, size));
Sql.Append(")");
}
return sqlConstantExpression;
@@ -383,6 +456,88 @@ protected override Expression VisitExtension(Expression extensionExpression)
};
}
+ protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression)
+ {
+ var methodName = methodCallExpression.Method.Name;
+
+ // 1. CONTAINS (Já implementado com CONTAINING)
+ if (methodName == "Contains" && methodCallExpression.Method.DeclaringType == typeof(string))
+ {
+ Visit(methodCallExpression.Object);
+ Sql.Append(" CONTAINING ");
+ Visit(methodCallExpression.Arguments[0]);
+ return methodCallExpression;
+ }
+
+ // 2. LIKE -> LIKE '%valor%'
+ if (methodName == "Like" && methodCallExpression.Method.DeclaringType == typeof(string))
+ {
+ // Para Like ser insensitive, forçamos UPPER em ambos os lados.
+ // SQL: UPPER(Campo) LIKE UPPER('%' || 'valor' || '%')
+ Sql.Append("UPPER(");
+ Visit(methodCallExpression.Object ?? methodCallExpression.Arguments[0]);
+ Sql.Append(") LIKE UPPER('%' || ");
+ Visit(methodCallExpression.Arguments.Last());
+ Sql.Append(" || '%')");
+ return methodCallExpression;
+ }
+
+ // 3. STARTSWITH -> LIKE 'valor%'
+ if (methodName == "StartsWith" && methodCallExpression.Method.DeclaringType == typeof(string))
+ {
+ // 'STARTING WITH' é mais performático que LIKE para inícios de string.
+ // SQL: UPPER(Campo) STARTING WITH UPPER('valor')
+ Sql.Append("UPPER(");
+ Visit(methodCallExpression.Object);
+ Sql.Append(") STARTING WITH UPPER(");
+ Visit(methodCallExpression.Arguments[0]);
+ Sql.Append(")");
+ return methodCallExpression;
+ }
+
+ // 4. ENDSWITH -> LIKE '%valor'
+ if (methodName == "EndsWith" && methodCallExpression.Method.DeclaringType == typeof(string))
+ {
+ // SQL: UPPER(Campo) LIKE UPPER('%' || 'valor')
+ Sql.Append("UPPER(");
+ Visit(methodCallExpression.Object);
+ Sql.Append(") LIKE UPPER('%' || ");
+ Visit(methodCallExpression.Arguments[0]);
+ Sql.Append(")");
+ return methodCallExpression;
+ }
+
+ // 5. SelectIN (Assume que o primeiro argumento é a lista e o segundo o valor, ou vice-versa)
+ // Geralmente mapeado de algo como "lista.Contains(item)"
+ if (methodName == "SelectIN" || (methodName == "Contains" && methodCallExpression.Method.DeclaringType != typeof(string)))
+ {
+ // Estrutura: VALOR IN (item1, item2, ...)
+ var column = methodCallExpression.Arguments.Count > 1 ? methodCallExpression.Arguments[1] : methodCallExpression.Arguments[0];
+ var list = methodCallExpression.Arguments.Count > 1 ? methodCallExpression.Arguments[0] : methodCallExpression.Object;
+
+ Visit(column);
+ Sql.Append(" IN (");
+ Visit(list); // O EF Core geralmente expande constantes de lista automaticamente
+ Sql.Append(")");
+ return methodCallExpression;
+ }
+
+ // 6. NotSelectIN
+ if (methodName == "NotSelectIN")
+ {
+ var column = methodCallExpression.Arguments[1];
+ var list = methodCallExpression.Arguments[0];
+
+ Visit(column);
+ Sql.Append(" NOT IN (");
+ Visit(list);
+ Sql.Append(")");
+ return methodCallExpression;
+ }
+
+ return base.VisitMethodCall(methodCallExpression);
+ }
+
protected virtual Expression VisitSpacedFunction(FbSpacedFunctionExpression spacedFunctionExpression)
{
Sql.Append(spacedFunctionExpression.Name);
@@ -413,4 +568,27 @@ void GenerateList(IReadOnlyList items, Action generationAction, Action<
generationAction(items[i]);
}
}
+
+ void BooleanToIntegralAndVisit(SqlExpression expression)
+ {
+ Sql.Append("IIF(");
+ Visit(expression);
+ Sql.Append(", 1, 0)");
+ }
+
+ string GetOperatorType(ExpressionType nodeType)
+ {
+ return nodeType switch
+ {
+ ExpressionType.AndAlso => " AND ",
+ ExpressionType.OrElse => " OR ",
+ ExpressionType.Equal => " = ",
+ ExpressionType.NotEqual => " <> ",
+ ExpressionType.LessThan => " < ",
+ ExpressionType.GreaterThan => " > ",
+ ExpressionType.LessThanOrEqual => " <= ",
+ ExpressionType.GreaterThanOrEqual => " >= ",
+ _ => ""
+ };
+ }
}
diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs
index 78bbff57d..ead4bb4d3 100644
--- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs
+++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs
@@ -27,17 +27,38 @@ public FbSqlGenerationHelper(RelationalSqlGenerationHelperDependencies dependenc
: base(dependencies)
{ }
- public virtual string StringLiteralQueryType(string s, bool isUnicode = true)
+ public virtual string StringLiteralQueryType(string s, bool isUnicode = true, string storeTypeNameBase = "", int size = 0)
{
- var length = MinimumStringQueryTypeLength(s);
+ var maxSize = MinimumStringQueryTypeLength(s);
+ string typeName;
+ if (storeTypeNameBase.Equals("BLOB SUB_TYPE TEXT", StringComparison.OrdinalIgnoreCase))
+ {
+ typeName = "VARCHAR";
+ }
+ else
+ {
+ typeName = IsEmpty(storeTypeNameBase) ? "VARCHAR" : storeTypeNameBase;
+ }
+
var charset = isUnicode ? " CHARACTER SET UTF8" : string.Empty;
- return $"VARCHAR({length}){charset}";
+ return $"{typeName}({maxSize}){charset}";
}
- public virtual string StringParameterQueryType(bool isUnicode)
+ public virtual string StringParameterQueryType(bool isUnicode, string storeTypeNameBase = "", int size = 0)
{
- var size = isUnicode ? FbTypeMappingSource.UnicodeVarcharMaxSize : FbTypeMappingSource.VarcharMaxSize;
- return $"VARCHAR({size})";
+ int maxSize;
+ string typeName;
+ if (storeTypeNameBase.Equals("BLOB SUB_TYPE TEXT", StringComparison.OrdinalIgnoreCase))
+ {
+ maxSize = (isUnicode ? FbTypeMappingSource.UnicodeVarcharMaxSize : FbTypeMappingSource.VarcharMaxSize);
+ typeName = "VARCHAR";
+ }
+ else
+ {
+ maxSize = size > 0 ? size : (isUnicode ? FbTypeMappingSource.UnicodeVarcharMaxSize : FbTypeMappingSource.VarcharMaxSize);
+ typeName = IsEmpty(storeTypeNameBase) ? "VARCHAR" : storeTypeNameBase;
+ }
+ return $"{typeName}({maxSize})";
}
public virtual void GenerateBlockParameterName(StringBuilder builder, string name)
@@ -47,7 +68,7 @@ public virtual void GenerateBlockParameterName(StringBuilder builder, string nam
public virtual string AlternativeStatementTerminator => "~";
- static int MinimumStringQueryTypeLength(string s)
+ private int MinimumStringQueryTypeLength(string s)
{
var length = s?.Length ?? 0;
if (length == 0)
@@ -55,9 +76,8 @@ static int MinimumStringQueryTypeLength(string s)
return length;
}
- static void EnsureStringLiteralQueryTypeLength(int length)
+ private bool IsEmpty(string storeTypeNameBase)
{
- if (length > FbTypeMappingSource.UnicodeVarcharMaxSize)
- throw new ArgumentOutOfRangeException(nameof(length));
+ return (storeTypeNameBase == null || string.IsNullOrEmpty(storeTypeNameBase) || string.IsNullOrWhiteSpace(storeTypeNameBase));
}
}
diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbTypeMappingSource.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbTypeMappingSource.cs
index 9e41a9efb..8c9f0070c 100644
--- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbTypeMappingSource.cs
+++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbTypeMappingSource.cs
@@ -19,6 +19,7 @@
using System.Collections.Generic;
using System.Data;
using FirebirdSql.Data.FirebirdClient;
+using FirebirdSql.EntityFrameworkCore.Firebird.Infrastructure.Internal;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage;
@@ -38,9 +39,9 @@ public class FbTypeMappingSource : RelationalTypeMappingSource
readonly IntTypeMapping _integer = new IntTypeMapping("INTEGER", DbType.Int32);
readonly LongTypeMapping _bigint = new LongTypeMapping("BIGINT", DbType.Int64);
- readonly FbStringTypeMapping _char = new FbStringTypeMapping("CHAR", DbType.StringFixedLength, FbDbType.Char);
- readonly FbStringTypeMapping _varchar = new FbStringTypeMapping("VARCHAR", DbType.String, FbDbType.VarChar);
- readonly FbStringTypeMapping _clob = new FbStringTypeMapping("BLOB SUB_TYPE TEXT", DbType.String, FbDbType.Text);
+ readonly FbStringTypeMapping _char;
+ readonly FbStringTypeMapping _varchar;
+ readonly FbStringTypeMapping _clob;
readonly FbByteArrayTypeMapping _binary = new FbByteArrayTypeMapping();
@@ -60,10 +61,17 @@ public class FbTypeMappingSource : RelationalTypeMappingSource
readonly Dictionary _storeTypeMappings;
readonly Dictionary _clrTypeMappings;
readonly HashSet _disallowedMappings;
+ readonly IFbOptions _fbOptions;
- public FbTypeMappingSource(TypeMappingSourceDependencies dependencies, RelationalTypeMappingSourceDependencies relationalDependencies)
+ public FbTypeMappingSource(TypeMappingSourceDependencies dependencies, RelationalTypeMappingSourceDependencies relationalDependencies, IFbOptions fbOptions)
: base(dependencies, relationalDependencies)
{
+ _fbOptions = fbOptions;
+ _char = new FbStringTypeMapping("CHAR", DbType.StringFixedLength, FbDbType.Char, unicode: fbOptions.IsUnicode);
+ _varchar = new FbStringTypeMapping("VARCHAR", DbType.String, FbDbType.VarChar, unicode: fbOptions.IsUnicode);
+ _clob = new FbStringTypeMapping("BLOB SUB_TYPE TEXT", DbType.String, FbDbType.Text, unicode: fbOptions.IsUnicode);
+
+
_storeTypeMappings = new Dictionary(StringComparer.OrdinalIgnoreCase)
{
{ "BOOLEAN", _boolean },
@@ -111,7 +119,13 @@ public FbTypeMappingSource(TypeMappingSourceDependencies dependencies, Relationa
protected override RelationalTypeMapping FindMapping(in RelationalTypeMappingInfo mappingInfo)
{
- return FindRawMapping(mappingInfo)?.Clone(mappingInfo) ?? base.FindMapping(mappingInfo);
+ var mapping = FindRawMapping(mappingInfo);
+ if (mapping != null)
+ {
+ var nonUnicodeInfo = mappingInfo with { IsUnicode = _fbOptions.IsUnicode && mapping.IsUnicode == true && mappingInfo.IsUnicode == true };
+ return mapping.Clone(nonUnicodeInfo);
+ }
+ return mapping?.Clone(mappingInfo) ?? base.FindMapping(mappingInfo);
}
protected override void ValidateMapping(CoreTypeMapping mapping, IProperty property)
@@ -134,7 +148,11 @@ RelationalTypeMapping FindRawMapping(RelationalTypeMappingInfo mappingInfo)
var clrType = mappingInfo.ClrType;
var storeTypeName = mappingInfo.StoreTypeName;
var storeTypeNameBase = mappingInfo.StoreTypeNameBase;
- var isUnicode = IsUnicode(mappingInfo.IsUnicode);
+ var isUnicode = IsUnicode(mappingInfo.IsUnicode, _fbOptions);
+ if (isUnicode && !_fbOptions.IsUnicode)
+ {
+ isUnicode = false;
+ }
if (storeTypeName != null)
{
@@ -199,7 +217,7 @@ RelationalTypeMapping FindRawMapping(RelationalTypeMappingInfo mappingInfo)
return null;
}
- public static bool IsUnicode(RelationalTypeMapping mapping) => IsUnicode(mapping?.IsUnicode);
- public static bool IsUnicode(RelationalTypeMappingInfo mappingInfo) => IsUnicode(mappingInfo.IsUnicode);
- public static bool IsUnicode(bool? isUnicode) => isUnicode ?? true;
+ public static bool IsUnicode(RelationalTypeMapping mapping, IFbOptions fbOptions) => IsUnicode(mapping?.IsUnicode, fbOptions);
+ public static bool IsUnicode(RelationalTypeMappingInfo mappingInfo, IFbOptions fbOptions) => IsUnicode(mappingInfo.IsUnicode, fbOptions);
+ public static bool IsUnicode(bool? isUnicode, IFbOptions fbOptions) => isUnicode ?? fbOptions.IsUnicode;
}
diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/IFbSqlGenerationHelper.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/IFbSqlGenerationHelper.cs
index 56c4c1f57..bb6af11c5 100644
--- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/IFbSqlGenerationHelper.cs
+++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/IFbSqlGenerationHelper.cs
@@ -22,8 +22,8 @@ namespace FirebirdSql.EntityFrameworkCore.Firebird.Storage.Internal;
public interface IFbSqlGenerationHelper : ISqlGenerationHelper
{
- string StringLiteralQueryType(string s, bool isUnicode);
- string StringParameterQueryType(bool isUnicode);
+ string StringLiteralQueryType(string s, bool isUnicode, string storeTypeNameBase = "", int size = 0);
+ string StringParameterQueryType(bool isUnicode, string storeTypeNameBase = "", int size = 0);
void GenerateBlockParameterName(StringBuilder builder, string name);
string AlternativeStatementTerminator { get; }
}
diff --git a/src/Versions.props b/src/Versions.props
index e134dd2ec..d06757548 100644
--- a/src/Versions.props
+++ b/src/Versions.props
@@ -1,4 +1,4 @@
-
+
11.0.0-alpha1
@@ -15,4 +15,7 @@
10.3.2
6.5.1
+
+ 1.7.1
+