I am currently using the Oracle Managed Driver (v12.1.2400) as my Entity Framework driver, and am currently seeing a ORA-12704: character set mismatch
error during execution.
The LINQ->SQL code I am using is as follows:
from c in CUSTOMER.AsNoTracking()
where c.ACCOUNT.Contains("DE")
&& c.DELETED == "N"
orderby (c.FORENAME + c.SURNAME)
select new { c.ACCOUNT, c.FORENAME, c.SURNAME})
and this is creating the following SQL:
SELECT "Project1"."C2" AS "C1",
"Project1"."ACCOUNT" AS "ACCOUNT",
"Project1"."FORENAME" AS "FORENAME",
"Project1"."SURNAME" AS "SURNAME"
FROM (
SELECT( (CASE WHEN ("Extent1"."FORENAME" IS NULL) THEN N''
ELSE "Extent1"."FORENAME" END)
||(CASE WHEN ("Extent1"."SURNAME" IS NULL) THEN N''
ELSE "Extent1"."SURNAME" END)) AS "C1",
"Extent1"."ACCOUNT" AS "ACCOUNT",
"Extent1"."FORENAME" AS "FORENAME",
"Extent1"."SURNAME" AS "SURNAME",
1 AS "C2"
FROM "TEST"."CUSTOMER" "Extent1"
WHERE (("Extent1"."ACCOUNT" LIKE '%DE%')
AND ('N' = "Extent1"."DELETED"))) "Project1"
ORDER BY "Project1"."C1" ASC;
When I debug that SQL, I can see the issue is that the SQL is using N''
in the CASE
sections. AS teh columns are not unicode, if I remove the preceding N
to leave just ''
then the sql works as expected.
Is there any way I can prevent this defaulting?
All db columns are currently VARCHAR
, and are modeled in C# as string
.
Code first mappings for the two columns are as follows:
this.Property(t => t.FORENAME).HasColumnName("FORENAME").IsUnicode(false).HasMaxLength(35);
this.Property(t => t.SURNAME).HasColumnName("SURNAME").IsUnicode(false).HasMaxLength(35);
I was expecting that the IsUnicode(false)
statement would take care of this.
FYI, this used to work when I used EF5 and the non-managed driver.
In addition, the Devart dotConnectForOracle drivers dont have this issue, so I am thinking this is a bug in the Oracle drivers.
I never did find the proper solution to this, however I did find a workaround that works well.
I created an Interceptor class NVarcharInterceptor
implementing IDbCommandInterceptor
, and overrode all of the ..Executing(..)
methods to contain the following code:
if (command != null && !string.IsNullOrWhiteSpace(command.CommandText))
command.CommandText = command.CommandText.Replace("N''", "''");
This effectively removes any of the unwanted NVarchar
references, from any command being executed on my DbContext
.
To add the interceptor, I added the following code to by DBConfiguration
class:
this.AddInterceptor(new NVarcharInterceptor());
Also you can create custom function for strings concatenation, and call it in LINQ instead of direct string concatenation.
For example: Create database function.
create or replace FUNCTION CONCAT2
(
PARAM1 IN VARCHAR2
, PARAM2 IN VARCHAR2
) RETURN VARCHAR2 AS
BEGIN
RETURN PARAM1 || PARAM2;
END CONCAT2;
Add it to your model.I use database first approach, so I just had to update model. Map function in code:
using System;
using System.Data.Entity;
public static class DbFunctions
{
[DbFunction("Model.Store", "CONCAT2")]
public static string Concat(string arg1, string arg2)
{
return String.Concat(arg1, arg2);
}
}
And use it in yours LINQ queries:
from c in CUSTOMER.AsNoTracking()
where c.ACCOUNT.Contains("DE")
&& c.DELETED == "N"
orderby DbFunctions.Concat(c.FORENAME, c.SURNAME)
select new { c.ACCOUNT, c.FORENAME, c.SURNAME})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With