Có một số hạn chế khi gọi các hàm / thủ tục ORACLE với nHibernate.
Như đã nêu trong tài liệu tham khảo (17.2.2.1):
Đối với Oracle, các quy tắc sau được áp dụng :
Một hàm phải trả về một tập kết quả. Tham số đầu tiên của aprocedure phải là OUT trả về tập kết quả. Điều này được thực hiện bằng cách sử dụng kiểu SYS_REFCURSOR trong Oracle 9 hoặc 10. Trong Oracle, bạn cần xác định kiểu REF CURSOR, xem tài liệu Oracle.
Tôi đã cố gắng giải quyết một chút với nó vì tôi đang gặp phải vấn đề tương tự.
Đây là QUY TRÌNH TRỌN GÓI:
ĐẦU:
create or replace
PACKAGE "MYPACKAGE" AS
TYPE ReferenceCursor IS REF CURSOR;
PROCEDURE usp_GetDual
(
pCursor OUT ReferenceCursor,
a IN CHAR,
b IN CHAR
);
END MYPACKAGE;
CƠ THỂ:
PROCEDURE usp_GetDual
(
pCursor OUT ReferenceCursor,
a IN CHAR,
b IN CHAR
)
IS
err_code NUMBER;
err_msg VARCHAR2(200);
BEGIN
OPEN pCursor FOR
SELECT * FROM dual;
EXCEPTION
WHEN OTHERS THEN
err_code := SQLCODE;
err_msg := substr(SQLERRM, 1, 200);
END usp_GetDual;
Đây là tệp ánh xạ của tôi:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MyAssembly">
<sql-query name="GetDaul">
{ call MYPACKAGE.usp_GetDual ( :a, :b ) }
</sql-query>
</hibernate-mapping>
và đây là mã tôi đã sử dụng để kiểm tra nó:
var value = Session.GetNamedQuery("GetDaul")
.SetParameter<string>("a", "AAA")
.SetParameter<string>("b", "BBB")
.UniqueResult();
Như bạn có thể thấy REF CURSOR phải là tham số đầu tiên trong thủ tục của bạn (pCursor OUT ReferenceCursor
) và bạn không cần phải tham chiếu nó trong bản đồ hoặc cuộc gọi của mình.
Nếu bạn muốn trả về các thực thể, mọi thứ sẽ phức tạp hơn một chút.
Tệp ánh xạ của bạn phải chỉ định kiểu trả về (lớp):
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MyAssembly">
<sql-query name="GetOrders">
<return class="MyAssembly.Domain.MyOrder, MyAssembly" />
{ call MYPACKAGE.usp_GetOrders ( :pCompanyCode , :pOrderNumer ) }
</sql-query>
</hibernate-mapping>
Bạn phải xác định thực thể của mình:
public class MyOrder
{
public virtual string Number { get; set; }
public virtual int Ver { get; private set; }
public virtual string Company { get; set; }
public virtual string Customer { get; set; }
public override bool Equals(object obj)
{
if (obj == null)
return false;
Order order = obj as Order;
if (order == null)
return false;
if (this.Number.Trim() == order.Number.Trim() &&
this.Ver == order.Ver &&
this.Company.Trim() == order.Company.Trim()
)
return true;
else
return false;
}
public override int GetHashCode()
{
int hash = 0;
hash = hash +
(null == this.Number ? 0 : this.Number.GetHashCode())
+
(this.Ver.GetHashCode())
+
(null == this.Company ? 0 : this.Company.GetHashCode());
return (hash);
}
}
và đây là tệp ánh xạ cho thực thể của bạn:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MyAssembly" namespace="MyAssembly.Domain">
<class name="MyOrder" table="OCSAORH" mutable="false">
<composite-id>
<key-property name="Number" column="OCHORDN" type="String" length="10"></key-property>
<key-property name="Ver" column="OCHAMND" type="Int32"></key-property>
<key-property name="Company" column="OCHCOSC" type="String" length="5"></key-property>
</composite-id>
<property name="Customer" column="OCHCLII" type="String"></property>
</class>
</hibernate-mapping>
Đây là gói ORACLE của tôi:
PROCEDURE usp_GetOrders
(
pCursor OUT ReferenceCursor,
pCompanyCode IN CHAR,
pOrderNumer IN CHAR
)
IS
err_code NUMBER;
err_msg VARCHAR2(200);
BEGIN
OPEN pCursor FOR
SELECT
OCSAORH.*
FROM OCSAORH
WHERE OCSAORH.OCHAMND = 0
AND OCSAORH.OCHCOSC = pCompanyCode
AND OCSAORH.OCHORDN = pOrderNumer;
EXCEPTION
WHEN OTHERS THEN
err_code := SQLCODE;
err_msg := substr(SQLERRM, 1, 200);
END usp_GetOrders;
Và bây giờ bạn có thể dễ dàng nhận được đơn đặt hàng của mình bằng cách sử dụng các tham số:
var listOfOrders = Session.GetNamedQuery("GetOrder")
.SetParameter<string>("pCompanyCode", "ABC")
.SetParameter<string>("pOrderNumer", "XYZ")
.List<Domain.MyOrder>();
Bài viết này đã giúp tôi hiểu mọi thứ phải được thực hiện như thế nào.