2016-01-07 45 views
7

私は、このような列の上に.Contains()を行うオラクルからEFでのいくつかの列を結合しようとしています:EFクエリ「ORA-12704:文字セットの不一致」

public IEnumerable<User> SearchUsers(string search) 
{ 
    search = search.ToLower(); 

    return _securityUow.Users 
      .Where(u => (u.FirstName.ToLower() + " " + u.LastName.ToLower() + " (" + u.NetId.ToLower() + ")").Contains(search)) 
      .OrderBy(u => u.LastName) 
      .ThenBy(u => u.FirstName) 
      .AsEnumerable(); 
} 

しかし、私は

{ 
    "Message": "An error has occurred.", 
    "ExceptionMessage": "An error occurred while executing the command definition. See the inner exception for details.", 
    "ExceptionType": "System.Data.Entity.Core.EntityCommandExecutionException", 
    "StackTrace": " at SoftwareRegistration.WebUI.Controllers.Api.V1.UserContactController.Lookup(String search) in C:\LocalRepository\OnlineSupport\SoftwareRegistration\trunk\release\SoftwareRegistration\SoftwareRegistration.WebUI\Controllers\Api\V1\UserContactController.cs:line 40\r\n at lambda_method(Closure , Object , Object[])\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()", 
    "InnerException": { 
    "Message": "An error has occurred.", 
    "ExceptionMessage": "ORA-12704: character set mismatch", 
    "ExceptionType": "Oracle.ManagedDataAccess.Client.OracleException", 
    "StackTrace": " at OracleInternal.ServiceObjects.OracleCommandImpl.VerifyExecution(OracleConnectionImpl connectionImpl, Int32& cursorId, Boolean bThrowArrayBindRelatedErrors, OracleException& exceptionForArrayBindDML, Boolean& hasMoreRowsInDB, Boolean bFirstIterationDone)\r\n at OracleInternal.ServiceObjects.OracleCommandImpl.ExecuteReader(String commandText, OracleParameterCollection paramColl, CommandType commandType, OracleConnectionImpl connectionImpl, OracleDataReaderImpl& rdrImpl, Int32 longFetchSize, Int64 clientInitialLOBFS, OracleDependencyImpl orclDependencyImpl, Int64[] scnForExecution, Int64[]& scnFromExecution, OracleParameterCollection& bindByPositionParamColl, Boolean& bBindParamPresent, Int64& internalInitialLOBFS, OracleException& exceptionForArrayBindDML, Boolean isDescribeOnly, Boolean isFromEF)\r\n at Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteReader(Boolean requery, Boolean fillRequest, CommandBehavior behavior)\r\n at Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteDbDataReader(CommandBehavior behavior)\r\n at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)\r\n at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<Reader>b__c(DbCommand t, DbCommandInterceptionContext`1 c)\r\n at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)\r\n at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader(DbCommand command, DbCommandInterceptionContext interceptionContext)\r\n at System.Data.Entity.Internal.InterceptableDbCommand.ExecuteDbDataReader(CommandBehavior behavior)\r\n at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)\r\n at System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)" 
    } 
} 

私が照会している列は、すべてOracleのVARCHAR2(128)型です。

他のプロジェクトでもまったく同じコードを使用していますが、動作します。唯一の違いは、私がOracle.DataAccessを使っていて、うまく動かないプロジェクトのために、私はOracle.ManagedDataAccess(このプロジェクトにはOracle.DataAccessを使用できません)を使用しているということです。だから私は管理されたドライバにバグ/問題があると信じています。

解決策または回避策があります。

+0

何文字セットされあなたのデータベースを使用して?これを判別するには、SELECT * FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER = 'NLS_CHARACTERSET''を実行します。 –

+0

私はそれを実行した、それは 'WE8MSWIN1252'と言う。 – solidau

+0

それは私が期待していたことに反している。 'WE8MSWIN1252'は1バイト文字セットですが、IIRC .netは内部的にUnicodeを使用しているので、データベースまたはドライバはUnicodeに設定された1バイトのデータベース文字を変換することができるはずです。私は[OracleGlobalizationクラスのドキュメント](http://docs.oracle.com/cd/E51173_01/win.122/e17732/OracleGlobalizationClass.htm#ODPNT3113)を見て、キャラクタ・セットの設定を可能にするメソッドのようには見えません管理対象ドライバの下で使用できます。運が良かった。 –

答えて

14

私は質問を更新するには、このの著者(ODP.Net Managed Driver - ORA-12704: character set mismatch in generated code)を取得することになった、彼はインターセプタを使用して回避策を掲示し、私はここでもう少し詳細に行くよ...

まず、私は私のDBContextを飾っ構成をロードする。あなたはこれをスキップしてちょうど持っていれば、あなたの構成に追加することができます。

[DbConfigurationType(typeof(MyDbConfiguration))] 
public partial class MyContext : DbContext 

は、Configクラスを作成します。

public class MyDbConfiguration : DbConfiguration 
{ 
    public MyDbConfiguration() 
    { 
     this.AddInterceptor(new NVarcharInterceptor()); //add this line to existing config. 
    } 
} 

次に、インターセプタを作成します。

public class NVarcharInterceptor : IDbCommandInterceptor 
{ 
    public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext) 
    { 
     if (command != null && !string.IsNullOrWhiteSpace(command.CommandText)) 
      command.CommandText = command.CommandText.Replace("N''", "''"); 
    } 

    public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext) 
    { 
     if (command != null && !string.IsNullOrWhiteSpace(command.CommandText)) 
      command.CommandText = command.CommandText.Replace("N''", "''"); 
    } 

    public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext) 
    { 
     if (command != null && !string.IsNullOrWhiteSpace(command.CommandText)) 
      command.CommandText = command.CommandText.Replace("N''", "''"); 
    } 

    public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext) 
    { 
     if (command != null && !string.IsNullOrWhiteSpace(command.CommandText)) 
      command.CommandText = command.CommandText.Replace("N''", "''"); 
    } 

    public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext) 
    { 
     if (command != null && !string.IsNullOrWhiteSpace(command.CommandText)) 
      command.CommandText = command.CommandText.Replace("N''", "''"); 
    } 

    public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext) 
    { 
     if (command != null && !string.IsNullOrWhiteSpace(command.CommandText)) 
      command.CommandText = command.CommandText.Replace("N''", "''"); 
    } 
} 
+0

それは働いた!素晴らしい回避策! –

関連する問題