C# ODP.Net托管驱动程序-ORA-12704:生成的代码中的字符集不匹配

C# ODP.Net托管驱动程序-ORA-12704:生成的代码中的字符集不匹配,c#,entity-framework-6,odp.net,C#,Entity Framework 6,Odp.net,我目前正在使用Oracle托管驱动程序(v12.1.2400)作为我的实体框架驱动程序,并且在执行过程中看到ORA-12704:字符集不匹配错误 我使用的LINQ->SQL代码如下: from c in CUSTOMER.AsNoTracking() where c.ACCOUNT.Contains("DE") && c.DELETED == "N" orderby (c.FORENAME + c.SURNAME) select new { c.ACCOUNT, c.FOR

我目前正在使用Oracle托管驱动程序(v12.1.2400)作为我的实体框架驱动程序,并且在执行过程中看到
ORA-12704:字符集不匹配
错误

我使用的LINQ->SQL代码如下:

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})
this.Property(t => t.FORENAME).HasColumnName("FORENAME").IsUnicode(false).HasMaxLength(35);
this.Property(t => t.SURNAME).HasColumnName("SURNAME").IsUnicode(false).HasMaxLength(35);
这将创建以下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;
调试该SQL时,我可以看到问题是SQL在
CASE
部分中使用了
N'
。由于这些列不是unicode,如果我删除前面的
N
而只保留
'
,那么sql将按预期工作

有什么方法可以防止这种违约

所有db列当前都是
VARCHAR
,并在C中建模为
string

两列的代码优先映射如下所示:

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})
this.Property(t => t.FORENAME).HasColumnName("FORENAME").IsUnicode(false).HasMaxLength(35);
this.Property(t => t.SURNAME).HasColumnName("SURNAME").IsUnicode(false).HasMaxLength(35);
我希望
IsUnicode(false)
语句能够解决这个问题

仅供参考,当我使用EF5和非托管驱动程序时,这一功能正常。

此外,Devart dotConnectForOracle驱动程序没有此问题,因此我认为这是Oracle驱动程序中的一个错误。

我从未找到解决此问题的正确方法,但我确实找到了一个行之有效的解决方法

我创建了一个拦截器类
nvarchrinterceptor
实现
idbcomandinterceptor
,并覆盖了所有
。执行(…)
方法以包含以下代码:

if (command != null && !string.IsNullOrWhiteSpace(command.CommandText))
    command.CommandText = command.CommandText.Replace("N''", "''");   
这将有效地从my
DbContext
上执行的任何命令中删除任何不需要的
NVarchar
引用

为了添加拦截器,我在by
DBConfiguration
class中添加了以下代码:

this.AddInterceptor(new NVarcharInterceptor());

您还可以为字符串连接创建自定义函数,并在LINQ中调用它,而不是直接字符串连接

例如: 创建数据库功能

create or replace FUNCTION CONCAT2
(
  PARAM1 IN VARCHAR2 
, PARAM2 IN VARCHAR2 
) RETURN VARCHAR2 AS 
BEGIN
  RETURN PARAM1 || PARAM2;
END CONCAT2;
我使用数据库优先的方法,所以我只需要更新模型。 代码中的映射函数:

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);
    }
}
并在LINQ查询中使用它:

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})

当我在IQueryable上使用字符串连接时,在select子句上使用Lambda表达式也有同样的症状

然后,我只在第一次选择中公开所有deisred字段,然后将其转换为列表,最后在转换后进行连接。然后错误消失了


该应用程序将EF4与Oracle.DataAccess一起使用,我使用ManagedDataAccess迁移到EF6,因此我必须对我的代码进行重构。

也有同样的问题。。你有没有找到一个合理的解决方案?补充我的解决方案作为一个答案