C#中安全绑定Oracle存储过程?

4
我们正在使用C#部署多个与Oracle数据库相关的项目。我希望将所有的数据库逻辑都实现在Oracle存储过程中,因为这样做有以下好处:
  • 将所有的数据库逻辑保留在数据库中
  • 当数据库结构发生变化时,更容易维护
  • 更容易地在不同的编程语言中重用存储过程
我已经编写了测试代码,使用SYS_REFCURSOR返回行,并手动对结果进行数据绑定,因为SYS_REFCURSOR可能返回任何类型的数据,即它不是类型安全的。
我的问题是 - 有没有办法在存储过程的返回类型中定义正确的类型,并在我的C#代码中正确地安全绑定到该类型?
例如,我的PL/SQL存储过程如下所示 - 返回部分不是类型安全的 - 它可以是任何类型。如果我想要从另一个Oracle包中重用它,则不会具有正确的类型检查。
PROCEDURE get_risk (p_process_id IN NUMBER, p_risk OUT sys_refcursor);

我的C#代码大致如下。我从几个类中拼凑了这些代码,所以希望它们是有意义的。当我从数据库调用中提取数据时,我手动定义数据类型-我需要在C#代码中知道Oracle的数据类型。

// setup procedure call
_oracleCommand = new OracleCommand("risk_pkg.get_risk", _conn.OracleConnection);
_oracleCommand.Parameters.Add(new OracleParameter("p_process_id", OracleDbType.Int64, processId, ParameterDirection.Input));
_oracleCommand.Parameters.Add(new OracleParameter("p_risk", OracleDbType.RefCursor, null, ParameterDirection.Output));

_oracleDataAdapter = new OracleDataAdapter(_oracleCommand);
_dataSet = new DataSet();

// call Oracle
_oracleDataAdapter.Fill(_dataSet);

// extract data - hand coded binding
Int64 dbRiskId = (Int64)_dataSet.Tables[0].Rows[0][_dataSet.Tables[0].Columns["risk_id"]];
Int64 dbClientId = (Int64)_dataSet.Tables[0].Rows[0][_dataSet.Tables[0].Columns["client_id"]];

return new Risk(dbRiskId, dbClientId);

这并不一定是个问题 - 我只是想知道是否有更好的方法来使我的PL/SQL返回结果更加明显,让我的C#代码不必知道Oracle数据类型 - 使我免受数据库结构变化的影响。

被接受的解决方案:这似乎是实际的解决方案。我仍然稍微感到不满意的是我的Oracle过程没有明确定义其返回类型,但这就是生活。

2个回答

2

你应该发布一个测试代码样例,因为我不确定是否正确理解了你的问题。

返回类型是Object,以服务于任何可能的返回值。你需要手动转换它。但你可以生成转换代码。定义一张表或一个文件,包含这些元信息:哪个存储过程返回哪种类型,以及应将其转换为哪种 .Net 类型。使用这些元信息来创建 C# 代码。

我们将 RefCursors 填充到 DataTable 中。将表字段分配给它们相应的成员变量的代码是从我们的元数据表中生成的。


这可能是可行的方法 - 我正在寻找一种完全定义 Oracle 存储过程返回类型的方法。这将使与存储过程交互的任何其他代码也具有类型安全性。我想我遇到的问题是我没有完全定义接口 - 当我知道数据类型时,我通常不编写函数并返回对象。 - Chris Gill
是的,请定义那个接口。我们支持Oracle和SQL Server。我们有一个类专门处理数据库特定的事情,两者都实现了相同的接口。 - John Smithers
你是否从Oracle中以SYS_REFCURSOR的形式返回数据? - Chris Gill
不,作为Ref Cursor:TYPE resc IS REF CURSOR;Procedure foo(bla in varchar2, bla2 in char, pResult IN OUT resc)是不可能使用Sys_refcursor的。如果我没记错的话,因为我们必须支持不支持它的Oracle 8。但我不确定。你认为这有什么区别吗? - John Smithers

1

我使用了T4文本模板来与SQL Server一起完成这个任务。效果非常好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接