I am using following code for fetching customer details using Stored Procedure
public List<Customer> GetPacketReconciliation(int customerId, int size, DateTime billDate, ref DateTime lastRunDate)
{
List<Customer> getCustomer = new List<Customer>();
SqlParameter[] arParms = new SqlParameter[4];
arParms[0] = new SqlParameter("#Cust_ID", SqlDbType.Int);
arParms[0].Value = customerId;
arParms[1] = new SqlParameter("#Size", SqlDbType.Int);
arParms[1].Value = size;
arParms[2] = new SqlParameter("#Last_Run_Date", SqlDbType.DateTime);
arParms[2].Direction = ParameterDirection.InputOutput;
arParms[2].Value = lastRunDate;
arParms[3] = new SqlParameter("#Bill_Date", SqlDbType.DateTime);
arParms[3].Value = billDate;
using (SqlConnection sqlCon = new SqlConnection(this.GetConnectionString()))
{
sqlCon.Open();
using (SqlDataReader reader = SqlHelper.ExecuteReader(sqlCon, CommandType.StoredProcedure, "dbo.GetCustomer", arParms))
{
if (reader.HasRows)
{
getCustomer= MapToEntityCollection<Customer>(reader);
}
}
}
if (arParms[2].Value != DBNull.Value)
{
lastRunDate = Convert.ToDateTime(arParms[2].Value);
}
return getCustomer;
}
Store Procedure
SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
CREATE PROCEDURE [dbo].[GetCustomer]
#Cust_ID SMALLINT,
#Size INT,
#Last_Run_Date DATETIME OUTPUT,
#Bill_Date DATETIME
AS
BEGIN
END
Here i am using one ref variable lastRunDate. When debugging i can see that lastdate value is setting properly in sqlparameter.But when i view it using sql profiler,i can see that lastRunDate is setting as null.if i hardcode it like arParms[2].Value = DateTime.Parse("2017-01-01") ,it works.Any issue with reference parameter ??
Anyone seeing any issue in this code ..
Related
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("user_storedproc_name", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 0;
cmd.Parameters.Clear();
SqlParameter[] parameters = new SqlParameter[14];
parameters[0] = new SqlParameter("#p1", vlaue);
String ts = String.IsNullOrEmpty(value1)?"0":value1;
parameters[1] = new SqlParameter("p2", Convert.ToInt64(ts));
parameters[2] = new SqlParameter("p3", value3);
String strDate1 = String.IsNullOrEmpty(value4)? "01/01/1900":value4;
parameters[3] = new SqlParameter("#p4", ConvertDate(strDate1).ToString("dd/mm/yyyy"));
String strDate2 = String.IsNullOrEmpty(value5)? "01/01/1900":value5;
parameters[4] = new SqlParameter("#p5", ConvertDate(strDate2).ToShortDateString());
parameters[5] = new SqlParameter("#p6", value6);
String strDate3 = String.IsNullOrEmpty(value7)? "01/01/1900":value7;
parameters[6] = new SqlParameter("#p7", ConvertDate(strDate3).ToShortDateString());
String strDate4 = String.IsNullOrEmpty(value8)? "01/01/1900":value8;
parameters[7] = new SqlParameter("#p8", ConvertDate(strDate4).ToShortDateString());
parameters[8] = new SqlParameter("#p9", value9);
parameters[9] = new SqlParameter("#p10", value10);
parameters[10] = new SqlParameter("#p11", value11);
parameters[11] = new SqlParameter("#p12", value12);
String strDate5 = String.IsNullOrEmpty(value13)?"01/01/1900":value13;
parameters[12] = new SqlParameter("#p13", ConvertDate(strDate5).ToShortDateString());
string strp14val = String.IsNullOrEmpty(Convert.ToString(value14)) ? "0" : value14;
parameters[13] = new SqlParameter("#p14",DbType.Int32);
parameters[13].Direction = ParameterDirection.Output;
int r_retval = SQLHelper.ExecuteNonQuery(SQLHelper.GetConnString(), CommandType.StoredProcedure, "user_storedproc_name", "DB_NAME_STRING", parameters);
private DateTime ConvertDate(String date)
{
String str = String.Empty;
try
{
if (date.Contains("/") || date.Contains("-"))
{
str = date.Split('/')[2] + "-" + date.Split('/')[1] + "-" + date.Split('/')[0];
}
}
catch (Exception ex)
{
throw ex;
}
return Convert.ToDateTime(str);
}
Code behind throwing error nvarchar to datetime.
Note: This working fine with SqlCommand object and adding parameters with binding values. but the calling function was sqlParameter[] (parameters array) but the SqlCommand object parameters is a SqlParameterCollection. I spent almost 48 hours of time till now debugging and troubleshooting with no fair success. Throw some light, Something that my sight is not able to get in code that is wrong. awaiting for comments/answers what is possible to guide.
Note: Stored procedure is working fine
ALTER PROCEDURE [dbo].[User_StoredProc]
(#p1 nvarchar(500)
,#p2 nvarchar(50)=null
,#p3 bigint=null
,#p4 nvarchar(50)=null
,#p5 nvarchar(50)=null
,#p6 varchar(40)=null
,#p7 nvarchar(50)=null
,#p8 nvarchar(50)=null
,#p9 nvarchar(50)=null
,#p10 nvarchar(50)=null
,#p11 nvarchar(50)=null
,#p12 nvarchar(50)=null
,#p13 nvarchar(50)=null
,#p14 int OUTPUT)
AS
--DECLARE #USP_PROJECT_ID INT
BEGIN
IF (#p14=0)
--print 'enter'
SET dateformat 'dmy';
INSERT INTO Project_Details
(col1
,col2
,col3
,col4
,col5
,col6
,col7
,col8
,col9
,col10
,col11
,col12
,col13)
VALUES(#p1
,#p2
,#p3
,Convert(Datetime,#p4,103)
,Convert(Datetime,#p5,103)
,#p6
,Convert(Datetime,#p7,103)
,Convert(Datetime,#p8,103)
,#p9
,#p10
,#p11
,#p12
,#p13)
-- print SCOPE_IDENTITY()
SET #p13=SCOPE_IDENTITY()
SELECT Project_Details.Project_Id FROM Project_Details WHERE Project_Id=#Project_id
END
I'm trying to pass list of objects and some other numbers and strings parameters to a SQL Server stored procedure using ado.net and execute it, and retrieve a value from an output parameter.
To capture the list of objects from the SQL Server stored procedure, I used a user-defined table type as shown here:
And this is the stored procedure:
ALTER PROCEDURE [dbo].[UpdateMailjetDetails]
#listCode VARCHAR(1000),
#listName VARCHAR(1000),
#mailjetListId BIGINT,
#mailjetListStatus INT,
#autoAsync BIT,
#contacts Contact READONLY,
#companyId INT,
#tblContactCompanyStatus INT,
#espListContactStatus INT,
#outputMessage VARCHAR(1000) OUT
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION [Tran1]
BEGIN TRY
-- logic
--
--
SET #outputMessage = 'success';
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION [Tran1];
SELECT
'Error - Rollbacked -' AS CustomMessage,
ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage;
SET #outputMessage = 'error - ' + ERROR_MESSAGE();
END CATCH
END
This is the C# code which calls the stored procedure.
public string SaveAndPassToMailjetWindowsService(string listCode, string listName, long mailjetListId, MailjetListStatus mailjetListStatus, bool autoSync, List<Contact> contacts, int companyId, TblContactCompanyStatus tblContactCompanyStatus, EspListContactStatus espListContactStatus)
{
try
{
string result;
var conString = GetMailCoreConnectionString();
using (var conn = new SqlConnection(conString))
{
var command = new SqlCommand("UpdateMailjetDetails", conn)
{ CommandType = CommandType.StoredProcedure };
command.Parameters.Add(new SqlParameter("#listCode", listCode));
command.Parameters.Add(new SqlParameter("#listName", listName));
command.Parameters.Add(new SqlParameter("#mailjetListId", mailjetListId));
command.Parameters.Add(new SqlParameter("#mailjetListStatus", (int) mailjetListStatus));
command.Parameters.Add(new SqlParameter("#autoAsync", autoSync));
var contactsParam =
new SqlParameter("#contacts", SqlDbType.Structured)
{
TypeName = "dbo.Contact",
Value = GetSqlDataRecordsContactsList(contacts)
};
command.Parameters.Add(new SqlParameter("#contacts", contactsParam));
command.Parameters.Add(new SqlParameter("#companyId", companyId));
command.Parameters.Add(new SqlParameter("#tblContactCompanyStatus", (int) tblContactCompanyStatus));
command.Parameters.Add(new SqlParameter("#espListContactStatus", (int) espListContactStatus));
var outputParameter = new SqlParameter
{
ParameterName = "#outputMessage",
SqlDbType = SqlDbType.VarChar,
Direction = ParameterDirection.Output
};
command.Parameters.Add(outputParameter);
conn.Open();
command.ExecuteNonQuery(); // throws exception
result = outPutParameter.Value.ToString();
conn.Close();
}
return result;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
And below is the C# method which converts the contacts list to a data table.
private List<SqlDataRecord> GetSqlDataRecordsContactsList(List<Contact> contacts)
{
try
{
List<SqlDataRecord> datatable = new List<SqlDataRecord>();
SqlMetaData[] sqlMetaData = new SqlMetaData[5];
sqlMetaData[0] = new SqlMetaData("Email", SqlDbType.NVarChar, 512);
sqlMetaData[1] = new SqlMetaData("Name", SqlDbType.NVarChar, 512);
sqlMetaData[2] = new SqlMetaData("TblContactId", SqlDbType.BigInt);
sqlMetaData[3] = new SqlMetaData("CompanyId", SqlDbType.Int);
sqlMetaData[4] = new SqlMetaData("TblContactCompanyId", SqlDbType.BigInt);
foreach (var contact in contacts)
{
SqlDataRecord row = new SqlDataRecord(sqlMetaData);
row.SetValues(contact.Email, contact.Name, contact.TblContactId ?? (object) DBNull.Value,
contact.CompanyId ?? (object) DBNull.Value,
contact.TblContactCompanyId ?? (object) DBNull.Value);
datatable.Add(row);
}
return datatable;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
Now, when I run the code it does all the logic in stored procedure properly and completes all the changes I'm trying to do. I can see that data has been added via the stored procedure properly, but SaveAndPassToMailjetWindowsService methods
command.ExecuteNonQuery();
throws an exception in the C# side (even though the stored procedure executed its logic properly).
No mapping exists from object type System.Data.SqlClient.SqlParameter to a known managed provider native type.
Any guidance to fix this is much appreciated. Thanks.
Here you are adding the parameter as a value for a parameter:
var contactsParam =
new SqlParameter("#contacts", SqlDbType.Structured)
{
TypeName = "dbo.Contact",
Value = GetSqlDataRecordsContactsList(contacts)
};
command.Parameters.Add(new SqlParameter("#contacts", contactsParam)); //Problem is here
It should just be:
command.Parameters.Add(contactsParam);
Can somebody help me debug my code?
Basically I have created a stored procedure and I want to call that stored procedure inside my website (ASP.NET).
This code is for my stored procedure:
CREATE PROCEDURE usp_hotelRoom
#country VARCHAR(50),
#name VARCHAR(50)
AS
BEGIN
SELECT
Room.roomID, Room.roomName, Room.type, Room.capacity, Room.roomSize,
Room.description, Room.remarks, Room.services, Room.photo,
Room.price, Hotel.name
FROM
Room
INNER JOIN
Hotel ON Hotel.orgEmail = Room.orgEmail
WHERE
country = #country
AND Hotel.name = #name;
END
EXEC usp_hotelRoom 'singapore', 'marina bay sands';
This code is for calling the stored procedure:
public static List<Room> getHotelRoomByCountry(string country, string name)
{
SqlConnection con = new SqlConnection(conStr);
try
{
SqlCommand command = new SqlCommand();
command.Connection = con;
command.CommandType = System.Data.CommandType.StoredProcedure;
command.CommandText = "usp_hotelRoom";
var paramname = new SqlParameter
{
ParameterName = "#country",
Value = country
};
command.Parameters.Add(paramname);
var paramhotel = new SqlParameter
{
ParameterName = "#hotel.name",
Value = name
};
command.Parameters.Add(paramhotel);
con.Open();
SqlDataReader reader = command.ExecuteReader();
List<Room> rooms = null;
if (reader.HasRows)
rooms = new List<Room>();
while (reader.Read())
{
rooms.Add(
new Room()
{
RoomID = reader["roomID"].ToString(),
RoomName = reader["roomName"].ToString(),
Type = reader["type"].ToString(),
Capacity = reader["capacity"].ToString(),
RoomSize = reader["roomSize"].ToString(),
Desc = reader["description"].ToString(),
Remarks = reader["remarks"].ToString(),
Services = reader["services"].ToString(),
Pictures = reader["photo"].ToString(),
Price = reader["price"].ToString(),
});
}
reader.Close();
return rooms;
}
finally
{
con.Close();
}
}
Hope someone can help me. I would appreciate it on your work!
I try to do it by myself and doesn't work, until I try to add new class attributes inside of the Room class (Hotel.Name)
Thanks!
Change this line of code
ParameterName = "#hotel.name"
to
ParameterName = "#name"
I have class with the list of objects as shown below.
public class Details
{
public string Reference { get; set; }
public List<Hotel> HotelDetails { get; set; }
}
I already created stored procedure to save the Details table values. and its working fine.Following is my stored procedure.
USE [UL_SLHEV]
GO
/****** Object: StoredProcedure [dbo].[SP_EVoucherDetails_Insert] Script Date: 8/9/2017 11:20:31 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[SP_Details_Insert]
#XRequestReference varchar(15),
AS
BEGIN
DECLARE #RequestReference AS VARCHAR(15) = ISNULL(#XRequestReference,'')
INSERT INTO Voucher(
RequestReference,
)
VALUES(
#RequestReference,
)
END
In here I have to save the hotel details list in another table in the same save method and in the same stored procedure. Following is the C# code that I used to save the hotel details in table.
public EVoucherDetails SaveEVoucherDetails(EVoucherDetails detailsModel)
{
Func<SqlCommand, EVoucherDetails> injector = (cmd) =>
{
cmd.Parameters.Add("#XRequestReference", SqlDbType.VarChar).Value = detailsModel.RequestReference;
var pList = new SqlParameter("#XHotelInfoDetails", SqlDbType.Structured);
pList.TypeName = "dbo.HotelInfo";
pList.Value = GetHotelList(detailsModel.HotelInfo, detailsModel.RequestReference);
cmd.Parameters.Add(pList);
};
return _sqlHelper.SqlSpExecute("SP_Details_Insert", injector);
}
private List<SqlDataRecord> GetHotelList(List<HotelInfo> list, string RequestRef)
{
List<SqlDataRecord> datatable = new List<SqlDataRecord>();
SqlMetaData[] sqlMetaData = new SqlMetaData[11];
sqlMetaData[0] = new SqlMetaData("HotelID", SqlDbType.Int);
sqlMetaData[1] = new SqlMetaData("RequestReference", SqlDbType.VarChar, 15);
sqlMetaData[2] = new SqlMetaData("FromDate", SqlDbType.DateTime);
sqlMetaData[3] = new SqlMetaData("ToDate", SqlDbType.DateTime);
sqlMetaData[4] = new SqlMetaData("Nights", SqlDbType.Int);
sqlMetaData[5] = new SqlMetaData("MealPlan", SqlDbType.VarChar, 10);
sqlMetaData[6] = new SqlMetaData("StarCategory", SqlDbType.Int);
sqlMetaData[7] = new SqlMetaData("Status", SqlDbType.Int);
sqlMetaData[8] = new SqlMetaData("LastUpdatedBy", SqlDbType.VarChar, 50);
sqlMetaData[9] = new SqlMetaData("LastUpdatedDate", SqlDbType.DateTime);
sqlMetaData[10] = new SqlMetaData("CreatedDateTime", SqlDbType.DateTime);
sqlMetaData[10] = new SqlMetaData("CreatedUserId", SqlDbType.VarChar, 15);
foreach (var info in list) {
SqlDataRecord row = new SqlDataRecord(sqlMetaData);
int? hotelId = GetHoteId(info.HotelName);
row.SetValues(hotelId, RequestRef, info.FromDate, info.ToDate, info.Nights, info.MealPlan, info.StarCategory, info.Status, info.LastUpdatedBy, info.LastUpdatedDateTime, info.CreatedDateTime, info.CreatedUserId);
datatable.Add(row);
}
return datatable;
}
I don' t know how to get hoteldetails by using same stored procedure above mentioned. Can anybody help with me this?
Thanks
When using a parameter in sql it looks like:
exec SP_Details_Insert "InputValueHere"
You have a multiple fields at your:
sqlMetaData[0] = new SqlMetaData("HotelID", SqlDbType.Int);
sqlMetaData[1] = new SqlMetaData("RequestReference", SqlDbType.VarChar, 15);
sqlMetaData[2] = new SqlMetaData("FromDate", SqlDbType.DateTime);
sqlMetaData[3] = new SqlMetaData("ToDate", SqlDbType.DateTime);
sqlMetaData[4] = new SqlMetaData("Nights", SqlDbType.Int);
sqlMetaData[5] = new SqlMetaData("MealPlan", SqlDbType.VarChar, 10);
sqlMetaData[6] = new SqlMetaData("StarCategory", SqlDbType.Int);
sqlMetaData[7] = new SqlMetaData("Status", SqlDbType.Int);
sqlMetaData[8] = new SqlMetaData("LastUpdatedBy", SqlDbType.VarChar, 50);
sqlMetaData[9] = new SqlMetaData("LastUpdatedDate", SqlDbType.DateTime);
sqlMetaData[10] = new SqlMetaData("CreatedDateTime", SqlDbType.DateTime);
sqlMetaData[10] = new SqlMetaData("CreatedUserId", SqlDbType.VarChar, 15);
Now if you want to Insert all this record Your Stored Procedure cannot handle this data because it uses only one parameter values which is VALUES(
#RequestReference,
).
You need to have a multiple parameter at your SP too same as your data and loop your data<List> to insert it all one at a time.
For the past few hours I am trying to do the simplest of the simple things (at least for SQL SERVER) in an Oracle Data Base, through a .NET application using ADO.NET. It seems impossible.
For SQL SERVER I would do this simple task, supposing I have an SqlCommand object
comm.CommandText = #"
DECLARE #next_id INT
SET #next_id = (SELECT ISNULL(MAX(id_col),0) FROM TABLE_1) + 1
INSERT INTO TABLE_1 (id_col, col1, ...) VALUES (#next_id, val1, ...)
SELECT #next_id";
int id = Convert.ToInt32(comm.ExecuteScalar());
That would insert a new record to table TABLE_1 and I would take back the new id in the "id" variable in c# code.
Four simple steps
Declare a variable
Set it to the next available id
Insert the record with the new variable
Return the variable's value
Ok I managed to declare the variable in Oracle query. Also I (think) I managed to give it a value (With SELECT INTO)
How can I get back this variable's value back in c#? How can i SELECT a variable's value to the output stream in Oracle SQL?
I know that there are better ways to achieve getting back an identity column, but that's not the question here. It could be a totally different example. The question is simple.: I have declared a variable inside an oracle sql script that will be executed from within .net app. How can i get the variable's value back to c#, from an oracle query? What is the above code's equivalent with Oracle ADO.NET query?
You'll want to use ODP.NET (Oracle's Oracle Data Access Components):
An example of this is below. Note that in ODP.NET, you can establish a parameters direction (input, inputoutput, output, returnvalue) to correspond with the parameters of the procedure or statement you're running. In this example, I'm grabbing a returnvalue, which is an ID that is generated by the db via a sequence and trigger (its created automagically as far as the .NET app is concerned):
int event_id = 0;
using (OracleConnection oraConn = new OracleConnection(connStr))
{
string cmdText = #"insert into EVENT
(EVENT_NAME, EVENT_DESC)
values
(:EVENT_NAME, :EVENT_DESC)
RETURNING EVENT_ID INTO :EVENT_ID
";
using (OracleCommand cmd = new OracleCommand(cmdText, oraConn))
{
oraConn.Open();
OracleTransaction trans = oraConn.BeginTransaction();
try
{
OracleParameter prm = new OracleParameter();
cmd.BindByName = true;
prm = new OracleParameter("EVENT_NAME", OracleDbType.Varchar2);
prm.Value = "SOME NAME"; cmd.Parameters.Add(prm);
prm = new OracleParameter("EVENT_DESC", OracleDbType.Varchar2);
prm.Value = "SOME DESC"; cmd.Parameters.Add(prm);
prm = new OracleParameter( "EVENT_ID"
, OracleDbType.Int32
, ParameterDirection.ReturnValue);
cmd.Parameters.Add(prm);
cmd.ExecuteNonQuery();
trans.Commit();
// return value
event_id = ConvertFromDB<int>(cmd.Parameters["EVENT_ID"].Value);
}
catch
{
trans.Rollback();
throw;
}
finally
{
trans.Dispose();
}
oraConn.Close();
}
}
The ConvertFromDB is just a generic to cast the return value to its .NET equivalent (an int in this case).
Hope that helps.
EDIT:
You can easily bind an array of values (and retrieve an array of return values) in ODP.NET:
using (OracleConnection oraConn = new OracleConnection(connStr))
{
string cmdText = #"insert into TEST_EVENT
(EVENT_NAME, EVENT_DESC)
values
(:EVENT_NAME, :EVENT_DESC)
RETURNING EVENT_ID INTO :EVENT_ID
";
using (OracleCommand cmd = new OracleCommand(cmdText, oraConn))
{
oraConn.Open();
OracleTransaction trans = oraConn.BeginTransaction();
try
{
string[] event_names = new string[2];
string[] event_descs = new string[2];
int[] event_ids = new int[2];
event_names[0] = "Event1";
event_descs[0] = "Desc1";
event_names[1] = "Event2";
event_descs[1] = "Desc2";
OracleParameter prm = new OracleParameter();
cmd.Parameters.Clear();
cmd.ArrayBindCount = 2;
cmd.BindByName = true;
prm = new OracleParameter("EVENT_NAME", OracleDbType.Varchar2);
prm.Value = event_names; cmd.Parameters.Add(prm);
prm = new OracleParameter("EVENT_DESC", OracleDbType.Varchar2);
prm.Value = event_descs; cmd.Parameters.Add(prm);
prm = new OracleParameter( "EVENT_ID"
, OracleDbType.Int32
, ParameterDirection.ReturnValue);
cmd.Parameters.Add(prm);
cmd.ExecuteNonQuery();
trans.Commit();
// get return values
event_ids = (int[])(cmd.Parameters["EVENT_ID"].Value);
}
catch
{
trans.Rollback();
throw;
}
finally
{
trans.Dispose();
}
oraConn.Close();
}
}