Reputation: 19
I have the following code:
public async Task<(int purchaseOrderId, string PONum)> AddPurchaseOrder(PurchaseOrderMaster purchaseOrderMaster)
{
try
{
var sqlQuery = new StringBuilder();
var paramSearch = new DynamicParameters();
_ = sqlQuery.Append($@"INSERT INTO PurchaseOrder (PONum, VendorID, WHId, PODate, ReferenceNum, EstArrivalDate, POType, SubTotal, TAX, ShippingHandling, Total, EnteredBy, EnteredOn, IsDelete)
OUTPUT inserted.PurchaseOrderId, inserted.PONum
VALUES (FLOOR(RAND() * 900000) + 100000, @VendorID, @WHId, @PODate, @ReferenceNum, @EstArrivalDate, @POType, @SubTotal, @TAX, @ShippingHandling, @Total, @EnteredBy, GETUTCDATE(), 'N');
");
paramSearch.Add("@VendorID", purchaseOrderMaster.VendorID);
paramSearch.Add("@WHId", purchaseOrderMaster.WHId);
paramSearch.Add("@PODate", purchaseOrderMaster.PODate);
paramSearch.Add("@ReferenceNum", purchaseOrderMaster.ReferenceNum);
paramSearch.Add("@EstArrivalDate", purchaseOrderMaster.EstArrivalDate);
paramSearch.Add("@POType", purchaseOrderMaster.POType);
paramSearch.Add("@SubTotal", purchaseOrderMaster.SubTotal);
paramSearch.Add("@TAX", purchaseOrderMaster.TAX);
paramSearch.Add("@ShippingHandling", purchaseOrderMaster.ShippingHandling);
paramSearch.Add("@Total", purchaseOrderMaster.Total);
paramSearch.Add("@EnteredBy", purchaseOrderMaster.EnteredBy);
return await dbHelper.ExecuteScalarAsync<(int, string)>(sqlQuery.ToString(), paramSearch).ConfigureAwait(false);
}
catch (Exception ex)
{
throw new BadRequestException(ex.Message);
}
}
I am getting PurchaseOrderId
and PONum
from the SQL query result and want to return as a tuple (int purchaseOrderId, string PONum)
in the C# code.
At query execution statement, I am getting an error as below:
{"Invalid cast from 'System.Int32' to 'System.ValueTuple`2[[System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]'."}
How can the result be converted to a tuple?
Upvotes: -1
Views: 99
Reputation: 19
all I have to use is "SelectData" instead of "ExecuteScalarAsync" that is returning multiple values as a tuple post SQL insert query.
return await dbHelper.SelectData<(int, string)>(sqlQuery.ToString(), paramSearch).ConfigureAwait(false);
Thanks
Upvotes: 0
Reputation: 1063433
ExecuteScalar
, by definition, returns only a single cell (one row, one column, one grid) - so you cannot use ExecuteScalar
to read two columns - you'd need to use a reader. I don't know what dbHelper
is, but it should have an API that returns a DbDataReader
, allowing something like:
// something like...
using var reader = await dbHelper.ExecuteReaderAsync(sqlQuery.ToString(), paramSearch).ConfigureAwait(false);
if (!reader.Read())
{
throw new InvalidOperationException("row not found"); // or something else suitable
}
var purchaseOrderId = reader.ReadInt32(0);
var PONum = reader.ReadString(1);
return (purchaseOrderId, PONum);
However, you might also want to consider tools that do this for you, for example, with Dapper (presumably instead of dbHelper
):
return await connection.QuerySingleAsync<(int, string)>("""
INSERT INTO PurchaseOrder (PONum, VendorID, WHId, PODate, ReferenceNum, EstArrivalDate, POType, SubTotal, TAX, ShippingHandling, Total, EnteredBy, EnteredOn, IsDelete)
OUTPUT inserted.PurchaseOrderId, inserted.PONum
VALUES (FLOOR(RAND() * 900000) + 100000, @VendorID, @WHId, @PODate, @ReferenceNum, @EstArrivalDate, @POType, @SubTotal, @TAX, @ShippingHandling, @Total, @EnteredBy, GETUTCDATE(), 'N');
""", purchaseOrderMaster).ConfigureAwait(false);
(Dapper has multiple ways of passing the parameters, but in this case it looks like it should be able to just pull the values from the DTO directly)
Upvotes: 1
Reputation: 3273
Change your ExecuteScalarAsync into ExecuteReaderAsync. Create your tuple by reading the 2 separate values.
var myTuple = Tuple.Create(
(int)Reader["PurchaseOrderId"],
(string)Reader["PONum"]
);
Upvotes: 1