“即时”创建和编译来自 C#/.Net 的 oracle 中的存储过程
我知道之前已经有人问过这个问题,但这些解决方案似乎不适合我。
我目前正在尝试执行以下操作:
- 为 oracle 构建一个“CREATE PROCEDURE”脚本字符串
- 使用企业库 5.0 创建 SQL 命令并将该字符串作为参数传递
- 将过程保存在 oracle 数据库中
所以到目前为止第 3 点似乎有效,如果我打开 SQL Developer 并展开过程树列表,那么我实际上可以看到该过程,但带有红色十字圆圈,这意味着它有编译器错误,尽管在 SQL Developer 查询窗口中运行相同的代码(相当小)工作正常并编译它。我不确定 SQL Developer 会在幕后执行某些操作,因为运行“CREATE PROCEDURE”脚本不会引发任何错误,然后我可以查看并执行该过程,但不能从 C# 中执行此操作。
我在本文开头发布的链接中读到,我应该调用 IDBCommand.Prepare()
,但该方法仅在您的 SQLCommand.CommandType 类型为 StoredProcedure 时才相关,并且因为我没有调用实际上是一个过程,但运行纯 sql 来创建该过程,那么这是行不通的,尽管如此,我只是为了测试,创建了一个新命令,将其分配给 StoredProcedure,然后在该命令上调用 Prepare() 方法,最后ExecuteNonQuery()
方法抛出对象(存储过程)不可用的异常,这是有道理的,因为它还没有被编译......
所以,我想知道是否有人真正知道你是如何做到的可以创建一个过程并从 C# 编译它,我们目前正在使用企业库,但我不介意直接向 Oracle 提供程序“硬编码”某些内容,只要它有效即可。
顺便说一句,在告诉我从代码创建过程是一种不好的做法之前,我告诉你不幸的是这是一个客户的项目,我们没有做出任何决定,实际上我们正在尝试将其从 SQL Server 迁移到 Oracle。
I know this has been asked before but those solutions seems not to work with me.
I'm currently trying to do this:
- Build a "CREATE PROCEDURE" script string for oracle
- Create a SQL Command using enterprise library 5.0 and pass this string as parameter
- Have the procedure saved in the oracle database
So point #3 seems to work so far, if I open SQL Developer and expand the procedure tree list then I can actually see the procedure but with the red cross circle which means it has compiler errors though running this same code, which is pretty small, in a SQL Developer query window works fine and compiles it. I'm not sure in SQL Developer does something under the hood because running that "CREATE PROCEDURE" script throws no error whatsoever, I can then see and execute the procedure but not so doing it from C#.
I read in the link posted in the beginning of this that I should call IDBCommand.Prepare()
, but that method is only relevant if your SQLCommand.CommandType is of type StoredProcedure and since I'm not calling a procedure actually but running pure sql to CREATE the procedure then this wouldn't work, nevertheless, I, just for the sake of testing, created a new command which I assigned to StoredProcedure and then called the Prepare() method on that command, finally the ExecuteNonQuery()
method which throws an exception of the object (the stored procedure) not being available which makes sense since it hasn't been compiled...
So, I wonder if anybody actually knows how you can create a procedure and compile it from C#, we are currently using enterprise library but I wouldn't mind "hard coding" something directly to the oracle provider as long as it works.
Btw, before telling me that creating a procedure from the code is a bad practice I tell you that unfortunely this is a customer's project and we had no decisions on the making, actually we are trying to migrate the thing from SQL Server to Oracle.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我有点生疏,现在没有 Oracle 访问权限,但我想我知道你的要求。您想要使用 ADO.NET OracleCommand 类和 Oracle EXECUTE IMMEDIATE 语句。像这样的事情:
那应该有效。但请注意,我一直使用 ODP.NET (Oracle 的自己的数据提供程序)而不是库存 ADO.NET 数据提供程序,因此如果您只使用库存库,可能会存在一些细微的差异。
正如 Pete 所建议的,您也可以使用动态 SQL 来达到相同的效果。您可以将整个 CREATE PROCEDURE 语句作为参数传递给现有存储过程,然后该存储过程会为您调用 EXECUTE IMMEDIATE。但我不认为您必须这样做。如果您想将其保持在最低限度,上述内容应该可行。
另一件事。我不知道为什么会发生这种情况,但如果 Oracle 告诉您该过程无效,即使您知道它没问题,请尝试执行
我经常发现 Oracle 在不必要地使对象无效方面有点脆弱。
I'm a bit rusty and have no Oracle access right now, but I think I know what your'e asking for. You want to use the ADO.NET OracleCommand class and the Oracle EXECUTE IMMEDIATE statement. Something like this:
That should work. But note that I've always used ODP.NET (Oracle's own data provider) instead of the stock ADO.NET one, so there may be some slight differences if you're just using the stock library.
As Pete suggested you could also use dynamic SQL to the same effect. You'd pass the whole CREATE PROCEDURE statement as a parameter to an existing stored procedure which then calls EXECUTE IMMEDIATE for you. However I don't believe that you have to do it that way. The above should work if you want to keep it minimal.
One other thing. I don't know why this would be happening, but if Oracle is telling you the procedure is invalid even though you know it's fine, try executing
I've often found Oracle to be a bit fragile with regards to invalidating objects unnecessarily.
如果要在 SQL Server 或 Oracle 中动态执行 DDL 语句,则必须将在 C# 中创建的 DDL 传递给 Oracle 中的过程,然后该过程将使用 EXECUTE IMMEDIATE 将字符串作为命令运行并创建过程。
Oracle 的此页面提到您如果“您想要执行纯静态 SQL 程序不支持的 DDL 语句和其他 SQL 语句”,则必须使用动态 sql。
我希望这对你有帮助。
If you want to execute DDL statements dynamically in either SQL Server or Oracle, you have to pass the DDL that you create in C# to a procedure in Oracle that will then use EXECUTE IMMEDIATE to run the string as a command and create the procedure.
This page from Oracle mentions that you'll have to use dynamic sql if "You want to execute DDL statements and other SQL statements that are not supported in purely static SQL programs".
I hope this helps you.
最后的角色是什么?
Oracle 最初的 SQL*Plus 使用斜杠字符来执行当前命令。许多 IDE 要么使用相同的斜杠,要么将斜杠解释为不属于过程/包的一部分
因此,如果您将斜杠(在新行上)作为“CREATE ...”字符串的末尾,那么它将是一个错误。但是,如果由 IDE 加载并重新编译,IDE 可能会为您删除它。
在 C# 加载后检查 USER_ERRORS,看看该程序单元是否报告有任何错误。
What's the final character ?
Oracle's original SQL*Plus uses a slash character to execute the current command. A lot of IDEs either use the same or interpret the slash as not being part of the procedure/package
So if you have a slash (on a new line) as the end of your 'CREATE ...' string, then it would be an error. However if loaded by the IDE and recompiled, the IDE might strip it out for you.
Do a check of USER_ERRORS after the load by C# and see if anything is reported as wrong with that program unit.