Trong trường hợp này, bạn không nên gọi:
var query = ctx.Database.SqlQuery<CmdRegisterAssetDto>(sql, projectNameParam, countryCodeParam, locationParam, assetRegisteredParam);
Nhưng thay vào đó hãy gọi:
var result = ctx.Database.ExecuteSqlCommand(sql, projectNameParam, countryCodeParam, locationParam, assetRegisteredParam);
Lưu ý rằng sự khác biệt hiệu quả duy nhất là SqlQuery<CmdRegisterAssetDto>
đã được thay thế bằng ExecuteSqlCommand
. Điều này cũng có nghĩa là DTO là không cần thiết. Nếu không, mã của bạn có vẻ như nó sẽ hoạt động. Đây là toàn bộ mã gốc của bạn với những thay đổi mà tôi đã đề cập:
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;
}
Để chứng minh lý thuyết của mình, tôi đã mô phỏng lại hành vi vô hiệu mà bạn đang trải qua và sau đó thực hiện thay đổi đó. Nó bị treo một chút (có thể là để cho EF đá vào bánh răng), nhưng sau đó thực hiện nhanh chóng mỗi lần sau đó. Trong mỗi trường hợp, tôi tìm thấy một giá trị đang đợi trong tham số out.
Nếu có ai đó đang gặp rắc rối, có một biến thể lâu đời sẽ xử lý các chi tiết tập lệnh cho bạn:
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;
}
Như một suy nghĩ sau, về mặt kỹ thuật, bạn có thể sử dụng giải pháp ban đầu của mình nếu bạn gọi truy vấn ngay sau (tức là query.FirstOrDefault()
). Giá trị trả về của truy vấn sẽ luôn là null, nhưng tham số out của bạn ít nhất sẽ được phổ biến. Điều này là do các truy vấn EF sử dụng thực thi hoãn lại.