5

我有一個簡單的Oracle存儲過程獲取傳入三個參數,並且有一個輸出參數:使用帶有輸出參數的實體框架調用Oracle存儲過程?

CREATE OR REPLACE PROCEDURE RA.RA_REGISTERASSET 
(
    INPROJECTNAME IN VARCHAR2 
    ,INCOUNTRYCODE IN VARCHAR2 
    ,INLOCATION IN VARCHAR2 
    ,OUTASSETREGISTERED OUT VARCHAR2 
) 
AS 
BEGIN 
    SELECT 
     INPROJECTNAME || ', ' || INLOCATION || ', ' || INCOUNTRYCODE 
    INTO 
     OUTASSETREGISTERED 
    FROM 
     DUAL;  
END RA_REGISTERASSET; 

我試圖使用實體框架6.1找回OutAssetRegistered值,但是,我得到一個空撥打SqlQuery後無一例外:

public class CmdRegisterAssetDto 
{ 
     public string inProjectName { get; set; } 
     public string inCountryCode { get; set; } 
     public string inLocation { get; set; } 
     public string OutAssetRegistered { get; set; } 
} 

// ---------------------------------- --------------------------

string projectName = "EXCO"; 
string location = "ANYWHERE"; 
string countryCode = "XX"; 

using (var ctx = new RAContext()) 
{ 
    var projectNameParam = new OracleParameter("inProjectName", OracleDbType.Varchar2, projectName, ParameterDirection.Input); 
    var countryCodeParam = new OracleParameter("inCountryCode", OracleDbType.Varchar2, countryCode, ParameterDirection.Input); 
    var locationParam = new OracleParameter("inLocation", OracleDbType.Varchar2, location, ParameterDirection.Input); 
    var assetRegisteredParam = new OracleParameter("OutAssetRegistered", OracleDbType.Varchar2, ParameterDirection.Output); 

    var sql = "BEGIN RA.RA_RegisterAsset(:inProjectName, :inCountryCode, :inLocation, :OutAssetRegistered); END;"; 
    var query = ctx.Database.SqlQuery<CmdRegisterAssetDto>(sql, projectNameParam, countryCodeParam, locationParam, assetRegisteredParam 
    ); 

    assetRegistered = (string)assetRegisteredParam.Value; 
} 

我一直在努力爭取這個工作無濟於事,檢查了不同的博客,所有其他crud操作工作,任何人都可以請協助,並指示我哪裏出錯了?

+0

我有類似的要求,你能解決它嗎? –

+0

我有同樣的問題,請讓我知道,如果你找到了解決方案。 – pforsthoff

回答

0

在這種情況下,你不應該叫:

var query = ctx.Database.SqlQuery<CmdRegisterAssetDto>(sql, projectNameParam, countryCodeParam, locationParam, assetRegisteredParam); 

而是應該呼籲:

var result = ctx.Database.ExecuteSqlCommand(sql, projectNameParam, countryCodeParam, locationParam, assetRegisteredParam); 

注意,唯一有效的區別是SqlQuery<CmdRegisterAssetDto>ExecuteSqlCommand取代。這也意味着DTO是不必要的。否則,你的代碼看起來應該起作用。這是你的原代碼,將其全部與我提到的更改:

string projectName = "EXCO"; 
string location = "ANYWHERE"; 
string countryCode = "XX"; 

using (var ctx = new RAContext()) 
{ 
    var projectNameParam = new OracleParameter("inProjectName", OracleDbType.Varchar2, projectName, ParameterDirection.Input); 
    var countryCodeParam = new OracleParameter("inCountryCode", OracleDbType.Varchar2, countryCode, ParameterDirection.Input); 
    var locationParam = new OracleParameter("inLocation", OracleDbType.Varchar2, location, ParameterDirection.Input); 
    var assetRegisteredParam = new OracleParameter("OutAssetRegistered", OracleDbType.Varchar2, ParameterDirection.Output); 

    var sql = "BEGIN RA.RA_RegisterAsset(:inProjectName, :inCountryCode, :inLocation, :OutAssetRegistered); END;"; 
    var result = ctx.Database.ExecuteSqlCommand(sql, projectNameParam, countryCodeParam, locationParam, assetRegisteredParam); 

    assetRegistered = (string)assetRegisteredParam.Value; 
} 

爲了證明我的理論,我轉載你所遇到的無效行爲,然後做出一個改變。它掛了一下(可能讓EF啓動),但之後每次都快速執行。在每種情況下,我都在out參數中找到了一個值。

如果有人在那裏運行陷入困境,有一個手寫的變化是需要照顧的腳本細節爲您提供:

string projectName = "EXCO"; 
string location = "ANYWHERE"; 
string countryCode = "XX"; 

using (var ctx = new RAContext()) 
using (var cmd = ctx.Database.Connection.CreateCommand()) 
{ 
    cmd.CommandType = CommandType.StoredProcedure; 
    cmd.CommandText = "RA.RA_REGISTERASSET"; 

    var projectNameParam = new OracleParameter("inProjectName", OracleDbType.Varchar2, projectName, ParameterDirection.Input); 
    var countryCodeParam = new OracleParameter("inCountryCode", OracleDbType.Varchar2, countryCode, ParameterDirection.Input); 
    var locationParam = new OracleParameter("inLocation", OracleDbType.Varchar2, location, ParameterDirection.Input); 
    var assetRegisteredParam = new OracleParameter("OutAssetRegistered", OracleDbType.Varchar2, ParameterDirection.Output); 
    cmd.Parameters.AddRange(new[] { projectNameParam, countryCodeParam, locationParam, assetRegisteredParam }); 

    cmd.Connection.Open(); 
    var result = cmd.ExecuteNonQuery(); 
    cmd.Connection.Close(); 

    assetRegistered = (string)assetRegisteredParam.Value; 
} 

在事後,你在技術上可以與你原來的解決方案去,如果你調用查詢後立即(即query.FirstOrDefault())。查詢的返回值將始終爲空,但您的out參數至少會被填充。這是因爲EF查詢使用延遲執行。

相關問題