oracle - Oracle DB with .NET Core Using ODP.Net Provider - 如何设置架构
问题描述
在 .NET Core 中使用 Oracle 数据库时遇到问题。
我能够创建到数据库的连接。
我的问题似乎是当我尝试执行语句时。我首先使用带有 DbContext 的 EF Core 从数据库中检索单个实体,在这种情况下,我在以下行中得到异常:
var item = _context.CSProf.SingleOrDefault(e => e.Id == id);
异常和跟踪似乎信息量不大。
Exception has occurred: CLR/Oracle.ManagedDataAccess.Client.OracleException
An exception of type 'Oracle.ManagedDataAccess.Client.OracleException' occurred in Microsoft.EntityFrameworkCore.dll but was not handled in user code: 'External component has thrown an exception.'
at OracleInternal.ServiceObjects.OracleConnectionImpl.VerifyExecution(Int32& cursorId, Boolean bThrowArrayBindRelatedErrors, SqlStatementType sqlStatementType, Int32 arrayBindCount, OracleException& exceptionForArrayBindDML, Boolean& hasMoreRowsInDB, Boolean bFirstIterationDone)
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, OracleConnection connection, OracleLogicalTransaction& oracleLogicalTransaction, IEnumerable`1 adrianParsedStmt, Boolean isDescribeOnly, Boolean isFromEF)
at Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteReader(Boolean requery, Boolean fillRequest, CommandBehavior behavior)
at Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.ExecuteReader()
...
我知道无论如何我都需要更改架构,所以我也尝试在 DbContext 构造函数中执行此操作:
var conn = this.Database.GetDbConnection();
conn.Open();
Console.WriteLine("DB Server Version with open conn = " + conn.ServerVersion); //no problem here -version is "12.1.0.2.0"
var command = conn.CreateCommand();
command.CommandText = "ALTER SESSION SET CURRENT_SCHEMA = {SchemaName};";
int res = command.ExecuteNonQuery(); //Error on this line - 'External component has thrown an exception.' at OracleInternal.ServiceObjects.OracleConnectionImpl.VerifyExecution( ...
command.Dispose();
conn.Close();
然后我也尝试像这样更改架构,使用 Oracle.ManagedDataAccess.Client OracleConnection 类而不是通过 EFCore 的 DbContext,得到相同的错误:
var oconn = new OracleConnection({ConnectionString});
oconn.Open();
Console.WriteLine("DB Server Version with open conn = " + oconn.ServerVersion); //no problem here -version is "12.1.0.2.0"
OracleCommand orclCmd = oconn.CreateCommand();
orclCmd.CommandText = "ALTER SESSION SET CURRENT_SCHEMA = {SchemaName};";
int res = orclCmd.ExecuteNonQuery(); // <---- Error on this line - 'External component has thrown an exception.' at OracleInternal.ServiceObjects.OracleConnectionImpl.VerifyExecution( ...
Console.WriteLine("Result of Alter Session Schema = " + res);
orclCmd.Dispose();
oconn.Close();
这是我的环境:
Windows Server 2016
Developing / Debugging in VS Code
.NETCoreApp,Version=v3.1
Microsoft.EntityFrameworkCore/2.1.11 Microsoft.EntityFrameworkCore.Relational/2.1.11 Oracle.EntityFrameworkCore/2.19.60
Oracle.ManagedDataAccess.Core/2.19.60
关于可能导致此“外部组件引发异常”或尝试什么的任何想法?
--------------------------------------
编辑:
在对实体的查询中,我注意到打印到调试控制台的跟踪中除了“外部组件已抛出”之外还有更多信息:
Microsoft.EntityFrameworkCore.Database.Command: Error: 2020-03-30 10:18:31.153037 ThreadID:4 (ERROR) OracleRelationalCommand.Execute() : Oracle.ManagedDataAccess.Client.OracleException (0x80004005): ORA-00942: table or view does not exist
当我将打印到调试控制台的 SQL 粘贴到 SQL Developer 中时,它返回的结果很好。但是从我的应用程序执行时,似乎数据库找不到表。听起来我可能不在正确的架构中,但是当我执行以下操作时:
SELECT sys_context('userenv', 'current_schema') FROM dual
正如@Sam 在评论中所建议的那样,它返回正确的架构名称,我相信这意味着我已经在正确的架构中?
解决方案
所以,最终我意识到我正在错误地设置模式。似乎虽然数据库连接具有正确的架构,但实体框架可能不知道正确的架构(或类似的东西)。
我在另一个让我直截了当的帖子上找到了这个答案:[ https://stackoverflow.com/a/35405309/3341533][1]
如链接答案所示,我只需将以相应的模式名称作为参数将以下行添加到我的 Context 的 OnModelCreating 方法中:
modelBuilder.HasDefaultSchema(string schema);
这不是 Oracle 特有的,因为我之前实际上必须为 MS SQL Server 执行此操作。
(不幸的是,我没有看其他项目并早点发现这个错误。)
推荐阅读
- sql-server - 将变量作为属性添加到 TSQL 中 XML 的子节点
- reactjs - /bin/sh: SET: 找不到命令
- objective-c - class-dump Mail.app 生成未知加载命令:0x00000032
- javascript - Materialize - 如何在多选中动态选择选项?
- kubernetes - 一旦我的笔记本电脑连接到 VPN,minikube 就无法启动
- reactjs - 为什么反应钩子在事件处理程序中引用旧数据?
- kotlin - 字符串列表的 min max 函数在什么基础上返回
- android - 高速视频会话的实时处理
- java - Kubernetes 上与 ActiveMQ 的 TCP 连接不断变化
- if-statement - If 语句中的内存和 CPU 效率