Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ODP.Net Managed Driver - ORA-12704: character set mismatch in generated code

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.

like image 401
Nick Avatar asked Nov 13 '15 13:11

Nick


2 Answers

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());
like image 167
Nick Avatar answered Nov 14 '22 23:11

Nick


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})
like image 24
Bazaleev Nikolai Avatar answered Nov 14 '22 22:11

Bazaleev Nikolai