Closed
Description
Hi Oracle Team,
Invalid query parameter value is passed to query when server side select contains the filter value and some other column from entity.
See that the filter query is run on char(80) column so the parameter value should be passed to the query like
example:
// Prepare data
var db = new NcharContext();
var entity = new B30TEST();
entity.Tschar = "ts";
entity.Index = 666;
db.B30TestRepo.Add(entity);
db.SaveChanges();
// Test
var result = db.B30TestRepo.Where(x => x.Tschar == entity.Tschar).Select(x => new { Val = entity.Tschar, val2 = x.Tsbool }) .ToList();
Debug.Assert(result.Count == 1); // This fails! - record not found
Problem
The filter column type is char(80) and the parameter value passed is
Parameters=[:entity_Tschar_0='ts' (Size = 2000)]
Looking at the log I see this:
11/24/2023 14:51:17.741 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (2ms) [Parameters=[:entity_Tschar_0='ts' (Size = 2000)], CommandType='Text', CommandTimeout='0']
SELECT :entity_Tschar_0 "Val", "b"."TSBOOL" "val2"
FROM "B30TEST" "b"
WHERE "b"."TSCHAR" = :entity_Tschar_0
Expected:
while the parameter value should be
: :entity_Tschar_0='ts '
Full Code Example and db definition of the table
CREATE TABLE "XXORA"."B30TEST"
( "MA_INDEX" NUMBER(*,0) DEFAULT 0 NOT NULL ENABLE,
"TSBOOL" NUMBER(*,0) DEFAULT 0 NOT NULL ENABLE,
"TSSHORT" NUMBER(*,0) DEFAULT 0 NOT NULL ENABLE,
"TSINT" NUMBER(*,0) DEFAULT 0 NOT NULL ENABLE,
"TSFLOAT" FLOAT(63) DEFAULT 0 NOT NULL ENABLE,
"TSDOUBLE" FLOAT(126) DEFAULT 0 NOT NULL ENABLE,
"TSLONG" NUMBER(*,0) DEFAULT 0 NOT NULL ENABLE,
"TSCHAR" CHAR(80 BYTE) DEFAULT ' ' NOT NULL ENABLE,
"TSNCHAR" NCHAR(80) DEFAULT ' ' NOT NULL ENABLE,
"TSVARCHAR" VARCHAR2(200 BYTE) DEFAULT NULL,
"TSNVARCHAR" NVARCHAR2(200) DEFAULT NULL,
"TSDATE" DATE DEFAULT '1900-01-01 00:00:00' NOT NULL ENABLE,
"TSTIME" DATE DEFAULT '1900-01-01 00:00:00' NOT NULL ENABLE,
"TSBLOB" BLOB DEFAULT NULL,
"MAROWVER" NUMBER(*,0) DEFAULT 1,
CONSTRAINT "B30TEST_PRIM_KEY" PRIMARY KEY ("MA_INDEX")
)
csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.22"/>
<PackageReference Include="Oracle.EntityFrameworkCore" Version="6.21.110"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.22"/>
</ItemGroup>
</Project>
using System.Diagnostics;
using Microsoft.EntityFrameworkCore;
namespace FixedLengthCharFilter;
public partial class B30TEST
{
public virtual int RowVersion { get; set; }
public virtual Int32 Index { get; set; }
/// <summary>
/// TEST of BOOLEAN
/// </summary>
public virtual Int16 Tsbool { get; set; }
/// <summary>
/// TEST of SHORT
/// </summary>
public virtual Int16 Tsshort { get; set; }
/// <summary>
/// TEST of INT
/// </summary>
public virtual Int32 Tsint { get; set; }
/// <summary>
/// TEST of FLOAT
/// </summary>
public virtual Single Tsfloat { get; set; }
/// <summary>
/// TEST of DOUBLE
/// </summary>
public virtual Decimal Tsdouble { get; set; }
/// <summary>
/// TEST of LONG
/// </summary>
public virtual Int32 Tslong { get; set; }
/// <summary>
/// TEST of CHAR
/// </summary>
public virtual String Tschar { get; set; }
/// <summary>
/// TEST of NCHAR
/// </summary>
public virtual String Tsnchar { get; set; }
/// <summary>
/// TEST of VARCHAR/VARCHAR2
/// </summary>
public virtual String Tsvarchar { get; set; }
/// <summary>
/// TEST of NVARCHAR/NVARCHAR2
/// </summary>
public virtual String Tsnvarchar { get; set; }
/// <summary>
/// TEST of DATE/DATETIME
/// </summary>
public virtual DateTime Tsdate { get; set; }
/// <summary>
/// TEST of DATE/DATETIME Time with only HH:MM:SS
/// </summary>
public virtual DateTime Tstime { get; set; }
/// <summary>
/// TEST of BLOB/VARBINARY
/// </summary>
public virtual Byte[] Tsblob { get; set; }
public B30TEST()
{
Index = 0;
Tsbool = 0;
Tsshort = 0;
Tsint = 0;
Tsfloat = 0;
Tsdouble = 0;
Tslong = 0;
Tschar = " ";
Tsnchar = " ";
Tsdate = new DateTime(1900, 1, 1, 0, 0, 0);
Tstime = new DateTime(1900, 1, 1, 0, 0, 0);
}
}
public class NcharContext : DbContext
{
public DbSet<B30TEST> B30TestRepo { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseOracle(
"Data Source=YourDatabaseConnection",
_ =>
{
optionsBuilder.LogTo(Console.WriteLine).EnableDetailedErrors().EnableSensitiveDataLogging();
});
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<B30TEST>(entity =>
{
entity.Property(e => e.RowVersion).IsRequired().IsConcurrencyToken().ValueGeneratedOnAddOrUpdate();
entity.HasKey(e=>e.Index).HasName("B30TEST_prim_key");
entity.Property(e=>e.Index).IsRequired().ValueGeneratedNever();
entity.Property(e=>e.Tsbool).IsRequired();
entity.Property(e=>e.Tsshort).IsRequired();
entity.Property(e=>e.Tsint).IsRequired();
entity.Property(e=>e.Tsfloat).IsRequired();
entity.Property(e=>e.Tsdouble).IsRequired();
entity.Property(e=>e.Tslong).IsRequired();
entity.Property(e=>e.Tschar).IsRequired().IsUnicode(false).HasMaxLength(80).IsFixedLength().HasConversion(v => v.PadRight(80), v => v.TrimEnd());
entity.Property(e=>e.Tsnchar).IsRequired().IsUnicode(true).HasMaxLength(80).IsFixedLength().HasConversion(v => v.PadRight(80), v => v.TrimEnd());
entity.Property(e=>e.Tsvarchar).IsUnicode(false).HasMaxLength(200);
entity.Property(e=>e.Tsnvarchar).IsUnicode(true).HasMaxLength(200);
entity.Property(e=>e.Tsdate).IsRequired();
entity.Property(e=>e.Tstime).IsRequired();
entity.Property(e=>e.Tsblob);
});
modelBuilder.Entity<B30TEST>(entity =>
{
entity.ToTable("B30TEST");
entity.Property(e => e.RowVersion).HasColumnName("MAROWVER");
entity.Property(e=>e.Index).HasColumnName("MA_INDEX");
entity.Property(e=>e.Tsbool).HasColumnName("TSBOOL");
entity.Property(e=>e.Tsshort).HasColumnName("TSSHORT");
entity.Property(e=>e.Tsint).HasColumnName("TSINT");
entity.Property(e=>e.Tsfloat).HasColumnName("TSFLOAT");
entity.Property(e=>e.Tsdouble).HasColumnName("TSDOUBLE").HasColumnType("FLOAT(126)");
entity.Property(e=>e.Tslong).HasColumnName("TSLONG");
entity.Property(e=>e.Tschar).HasColumnName("TSCHAR").HasColumnType("CHAR(80)");
entity.Property(e=>e.Tsnchar).HasColumnName("TSNCHAR").HasColumnType("NCHAR(80)");
entity.Property(e=>e.Tsvarchar).HasColumnName("TSVARCHAR");
entity.Property(e=>e.Tsnvarchar).HasColumnName("TSNVARCHAR");
entity.Property(e=>e.Tsdate).HasColumnName("TSDATE");
entity.Property(e=>e.Tstime).HasColumnName("TSTIME");
entity.Property(e=>e.Tsblob).HasColumnName("TSBLOB");
});
}
}
static class Program
{
static void Main(string[] args)
{
var db = new NcharContext();
var entity = new B30TEST();
entity.Tschar = "ts";
entity.Index = 666;
db.B30TestRepo.Add(entity);
db.SaveChanges();
//var result2= db.B30TestRepo.Where(x => x.Tschar == entity.Tschar).Select(x => new { Val = entity.Tschar })
// .ToList();
// Debug.Assert(result2.Count == 1); // This works!
var result = db.B30TestRepo.Where(x => x.Tschar == entity.Tschar).Select(x => new { Val = entity.Tschar, val2 = x.Tsbool })
.ToList();
Debug.Assert(result.Count == 1); // This fails! - record not found
}
}