2015-11-13 25 views
4

我目前使用的Oracle管理驅動程序(v12.1.2400)字符集不匹配,並在執行過程中我目前看到ORA-12704: character set mismatch錯誤。ODP.Net管理驅動程序 - 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}) 

,這是創建的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''。 AS德列不是unicode的,如果我去掉前面N只留下''那麼SQL按預期工作。

有沒有什麼辦法可以防止這種違約?

所有db列當前都是VARCHAR,並且在C#中被模擬爲string。是
的兩列代碼首先映射如下:

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驅動程序中的一個錯誤。

+0

有同樣的問題..你曾經找到一個合理的解決方案嗎? – solidau

+1

將解決方案作爲解答添加到我的解決方案中 – Nick

回答

3

我從來沒有找到適當的解決方案,但我找到了一個解決方案,效果很好。

我創建了一個攔截器類NVarcharInterceptor實施IDbCommandInterceptor,而壓倒所有的..Executing(..)方法包括如下代碼:

if (command != null && !string.IsNullOrWhiteSpace(command.CommandText)) 
    command.CommandText = command.CommandText.Replace("N''", "''"); 

這將有效消除任何不必要的NVarchar引用,從任何命令在執行我的DbContext

this.AddInterceptor(new NVarcharInterceptor()); 
+0

工作正常!感謝您的更新! – solidau

1

你也可以創建字符串拼接自定義函數,並調用它的LINQ,而不是直接的字符串連接:

要添加攔截器,我通過DBConfiguration類添加以下代碼。

例如: 創建數據庫功能。

create or replace FUNCTION CONCAT2 
(
    PARAM1 IN VARCHAR2 
, PARAM2 IN VARCHAR2 
) RETURN VARCHAR2 AS 
BEGIN 
    RETURN PARAM1 || PARAM2; 
END CONCAT2; 

將它添加到您的model.I使用數據庫的第一種方法,所以我只需要更新模型。在代碼 地圖功能:

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}) 
相關問題