Oracle DB 与 .NET Core 使用 ODP.Net Provider - 如何设置架构

标签 oracle .net-core entity-framework-core odp.net

在 .NET Core 中使用 Oracle 数据库时遇到问题。

我能够创建与数据库的连接。
我的问题似乎是当我尝试执行一条语句时。 我首先使用 EF Core 和 DbContext 从数据库中检索单个实体,在这种情况下,我在以下行中收到异常:

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 在评论中所建议的,它返回了正确的架构名称,我相信这意味着我已经处于正确的架构中?

最佳答案

所以,最终我意识到我正在错误地设置架构。 看来,虽然数据库连接具有正确的架构,但 Entity Framework 可能不知道正确的架构(或类似的东西)。

我在另一篇文章中找到了这个答案,这让我明白了: [https://stackoverflow.com/a/35405309/3341533][1]

如链接的答案所示,我只需将以下行添加到我的上下文的 OnModelCreating 方法中,并使用相应的架构名称作为参数:

modelBuilder.HasDefaultSchema(string schema);

这并不是 Oracle 特有的,因为我之前实际上必须为 MS SQL Server 执行此操作。
(不幸的是,我没有查看其他项目并尽早发现这个错误。)

关于Oracle DB 与 .NET Core 使用 ODP.Net Provider - 如何设置架构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60921375/

相关文章:

azure - 如何在 Azure Devops 上安装多个 .NET Core SDK 版本

c# - Linux : missing all bower packages 上的 asp dotnet 核心

c# - 如何添加AuthController add role default IdentityCore

c# - Entity Framework 核心 : SqlException: A transport-level error has occurred when receiving results from the server

Oracle 调整/分析表

java - 每当我需要使用 c3Po 池获取连接时,是否有必要在每个类中调用 getConnection() ?

c# - 我可以使用 EF 中的 ExecuteUpdate 从 select 进行更新吗?

c# - Entity Framework 和.NET 的一对一关系

sql - 查找时间戳和标识不按顺序排列的行的有效方法是什么?

c# - Oracle INTERVAL DAY TO SECOND 数据类型的 NHibernate 映射