Insert chunk using linq to sql? - c#

in a c# application, I need to insert into sql server 2005 table a lot or records. I split datatable in 2000 records chunk, using linq to sql server but dont work good becasue dont stop ever! I've 900.000 recors and insert a lot more thant this. What I'm doing wrong?
This is my code:
int jump = 0;
while (ds.Tables[0].Rows.Count < ds.Tables[0].Rows.Count + 1)
{
String xmlData = ConvertDataTableToXML(ds.Tables[0].AsEnumerable().Skip(jump).Take(2000 + jump).CopyToDataTable());
jump = jump + 2001;
SqlConnection conn = new SqlConnection
("Data Source=SERVER;Initial Catalog=DATABASE;Persist Security Info=True;User ID=USER;Password=PASS;");
conn.Open();
SqlCommand insert = new SqlCommand
("sp_InsertData'" + xmlData + "'", conn);
insert.ExecuteNonQuery();
conn.Close();
}

if you understand Temp Tables in SQL Server as well as how to use the OPENXML command you can try the following. it works even if your DBA disables BULK INSERTS
substitute my field names with your own and the field mappings in this portion of the code should match your tables schema / field definitions / data types
FROM OPENXML (#xmlHandle, '/NewDataSet/XMLDataTable',1)
WITH (
ALTER PROCEDURE [dbo].[sp_InsertData]
(#xmlString VARCHAR(MAX))
AS
BEGIN
/* Initialize a handle for the XmlDocument */
DECLARE #xmlHandle INT
/*
Created by #MethodMan you first want to create / declare a TEMP TABLE which
Mimic's the structure of the Target table that you are inserting into
*/
DECLARE #someTargetTable TABLE
(
[EN_INTFC_ID] varchar(25),
[EN_INTFC_LINE_NUM] varchar(5),
[EN_BILL_SOURCE_ID] varchar(10),
[EN_BUSINESS_UNIT] varchar(12),
[EN_ASSET_NAME] varchar(4),
[EN_POSTING_DATE] DateTime,
[EN_FISCAL_YEAR] varchar(4),
[EN_FISCAL_PERIOD] varchar(3),
[EN_CUSTOMER_ID] varchar(50),
[EN_DOC_TYPE] varchar(4),
[EN_TARGET_INVOICE] varchar(16),
[EN_INVOICE_DT] DateTime,
[EN_REVNUE_TYPE] varchar(15),
[EN_QTY] decimal(15,0),
[EN_GROSS_EXT_AMT] decimal(25,2),
[EN_DESCR] varchar(50),
[EN_CONTRACT] varchar(20),
[EN_PRODUCT_TYPE] varchar(15),
[EN_UNIT_OF_MEASURE] varchar(3)
)
/*
Create the XmlDocument using the handle above and the Xml
string as parameters. If your stored procedure has an varchar input
parameter named #xmlString, it would look like this instead:
EXEC sp_xml_preparedocument #xmlHandle output,#xmlString
*/
EXEC sp_xml_preparedocument #xmlHandle output, #xmlString
/*
Use the OPENXML method to query the XmlDocument starting at
/NewDataSet/SampleDataTable node.
*/
INSERT INTO #someTargetTable
SELECT [EN_INTFC_ID],
[EN_INTFC_LINE_NUM],
[EN_BILL_SOURCE_ID],
[EN_BUSINESS_UNIT],
[EN_ASSET_NAME],
[EN_POSTING_DATE],
[EN_FISCAL_YEAR],
[EN_FISCAL_PERIOD],
[EN_CUSTOMER_ID],
[EN_DOC_TYPE],
[EN_TARGET_INVOICE],
[EN_INVOICE_DT],
[EN_REVNUE_TYPE],
[EN_QTY],
[EN_GROSS_EXT_AMT],
[EN_DESCR],
[EN_CONTRACT],
[EN_PRODUCT_TYPE],
[EN_UNIT_OF_MEASURE]
FROM OPENXML (#xmlHandle, '/NewDataSet/XMLDataTable',1)
WITH (
[EN_INTFC_ID] varchar(25) '#EN_INTFC_ID',
[EN_INTFC_LINE_NUM] varchar(5) '#EN_INTFC_LINE_NUM',
[EN_BILL_SOURCE_ID] varchar(10) '#EN_BILL_SOURCE_ID',
[EN_BUSINESS_UNIT] varchar(12) '#EN_BUSINESS_UNIT',
[EN_ASSET_NAME] varchar(4) '#EN_ASSET_NAME',
[EN_POSTING_DATE] DateTime '#EN_POSTING_DATE',
[EN_FISCAL_YEAR] varchar(4) '#EN_FISCAL_YEAR',
[EN_FISCAL_PERIOD] varchar(3) '#EN_FISCAL_PERIOD',
[EN_CUSTOMER_ID] varchar(50) '#EN_CUSTOMER_ID',
[EN_DOC_TYPE] varchar(4) '#EN_DOC_TYPE',
[EN_TARGET_INVOICE] varchar(16) '#EN_TARGET_INVOICE',
[EN_INVOICE_DT] DateTime '#EN_INVOICE_DT',
[EN_REVNUE_TYPE] varchar(15) '#EN_REVNUE_TYPE',
[EN_QTY] decimal(15,0) '#EN_QTY',
[EN_GROSS_EXT_AMT] decimal(25,2) '#EN_GROSS_EXT_AMT',
[EN_DESCR] varchar(50) '#EN_DESCR',
[EN_CONTRACT] varchar(20) '#EN_CONTRACT',
[EN_PRODUCT_TYPE] varchar(15) '#EN_PRODUCT_TYPE',
[EN_UNIT_OF_MEASURE] varchar(3) '#EN_UNIT_OF_MEASURE'
)
/*Insert the records into the table variable */
INSERT INTO Your_Actual_Table_Name (
[EN_INTFC_ID],
[EN_INTFC_LINE_NUM],
[EN_BILL_SOURCE_ID],
[EN_BUSINESS_UNIT],
[EN_ASSET_NAME],
[EN_POSTING_DATE],
[EN_FISCAL_YEAR],
[EN_FISCAL_PERIOD],
[EN_CUSTOMER_ID],
[EN_DOC_TYPE],
[EN_TARGET_INVOICE],
[EN_INVOICE_DT],
[EN_REVNUE_TYPE],
[EN_QTY],
[EN_GROSS_EXT_AMT],
[EN_DESCR],
[EN_CONTRACT],
[EN_PRODUCT_TYPE],
[EN_UNIT_OF_MEASURE] )
(SELECT [EN_INTFC_ID],
[EN_INTFC_LINE_NUM],
[EN_BILL_SOURCE_ID],
[EN_BUSINESS_UNIT],
[EN_ASSET_NAME],
[EN_POSTING_DATE],
[EN_FISCAL_YEAR],
[EN_FISCAL_PERIOD],
[EN_CUSTOMER_ID],
[EN_DOC_TYPE],
[EN_TARGET_INVOICE],
[EN_INVOICE_DT],
[EN_REVNUE_TYPE],
[EN_QTY],
[EN_GROSS_EXT_AMT],
[EN_DESCR],
[EN_CONTRACT],
[EN_PRODUCT_TYPE],
[EN_UNIT_OF_MEASURE]
FROM #someTargetTable)
/* Remove the document from memory */
EXEC sp_xml_removedocument #xmlHandle
END
// your sql command below.
SqlCommand insert = new SqlCommand ("sp_InsertData '" + xmlData + "'", conn);
insert.CommandTimeout = 5000;
insert.ExecuteNonQuery();
conn.Close()
// my code and how you can utilize the using(){} statement along with code to convert a DataTable to XML then pass that xml to the stored procedure which I have depicted above
private bool ProcessSomeDataTableToXML(DataTable dataTable)
{
String xmlData = ConvertDataTableToXML(dataTable);
var ConnString = System.Configuration.ConfigurationManager.ConnectionStrings["yourdatabase"].ConnectionString;
using (SqlConnection connection = new SqlConnection(ConnString))
{
using (SqlCommand command = new SqlCommand("sp_InsertData '" + xmlData + "'", connection))
{
connection.Open();
try
{
command.ExecuteNonQuery();
fileInserted = true;
}
catch (SqlException sqlEx)
{
fileInserted = false;
Console.WriteLine(sqlEx.Message);
}
}
}
return fileInserted;
}
private static string ConvertDataTableToXML(DataTable dtData)
{
DataSet dsData = new DataSet();
StringBuilder sbSQL;
StringWriter swSQL;
string XMLformat;
try
{
sbSQL = new StringBuilder();
swSQL = new StringWriter(sbSQL);
dsData.Merge(dtData, true, MissingSchemaAction.AddWithKey);
dsData.Tables[0].TableName = "XMLDataTable";
foreach (DataColumn col in dsData.Tables[0].Columns)
{
col.ColumnMapping = MappingType.Attribute;
}
dsData.WriteXml(swSQL, XmlWriteMode.WriteSchema);
XMLformat = sbSQL.ToString();
sbSQL = null;
swSQL = null;
return XMLformat;
}
catch (Exception sysException)
{
throw sysException;
}
}

An obvious problem is in your while condition:
ds.Tables[0].Rows.Count < ds.Tables[0].Rows.Count + 1
i.e. count < count + 1
i.e. true
Your loop is designed never to stop. You might change it to
while (jump < ds.Tables[0].Rows.Count)

1) You have an infite loop (ds.Tables[0].Rows.Count < ds.Tables[0].Rows.Count + 1)
2) Connection management: You don't need to open an close the connection on each iteration. Use a using block for disposing the connection once you are done with it.

Related

C# Inserting a DataSet Into SQL Database

I'm trying to insert a dataset into an SQL database but I am having difficulties passing my dataset as an argument to my DB class. I am not sure if it is allowed to pass as an argument. If not, what are my alternatives?
The way I create my dataset:
public static void getLogs() {
string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\someDir";
SQLiteConnection cn = new SQLiteConnection("Data Source=" + path + ";Version=3;New=False;Compress=True;");
cn.Open();
SQLiteDataAdapter sd = new SQLiteDataAdapter("SELECT * FROM table", cn);
DataSet ds = new DataSet();
sd.Fill(ds);
cn.Close();
db.InsertLogs(Form1.adminID, Form1.deviceID, ds);
}
My database class and insert method looks like the following:
public void InsertLogs(string user_id, string device_id, DataSet history)
{
string query = "INSERT INTO table (column1, column2, column3, column4, column5, column6, column7) VALUES (#value1, #value2, #value3, #value4, #value5, #value6, #value7);";
if (OpenConnection() == true)
{
foreach (DataTable table in history.Tables)
{
foreach (DataRow row in table.Rows)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
cmd.Parameters.AddWithValue("#value1", int.Parse(user_id));
cmd.Parameters.AddWithValue("#value2", int.Parse(device_id));
cmd.Parameters.AddWithValue("#value3", row[0]);
cmd.Parameters.AddWithValue("#value4", row[1]);
cmd.Parameters.AddWithValue("#value5", row[2]);
cmd.Parameters.AddWithValue("#value6", row[3]);
cmd.Parameters.AddWithValue("#value7", row[4]);
cmd.ExecuteNonQuery();
}
}
CloseConnection();
}
}
Thank you
you can loop through datatables in a dataset and can pass a datatable as a stored procedure paramater,
found an example here
1.- Go to SQL Server, under your DB name go to "programmability\Types\User-Defined Table Types, right click and create a new one:
USE DBNAME
GO
-- Create the data type
CREATE TYPE ValuesToInsert AS TABLE
(
Value1 INT NOT NULL,
Value2 INT NOT NULL,
Value3 VARCHAR(20)
)
GO
2.- Create a SP to receive the table as parameter, parameter must be the new User-Defined table type created in step 1
USE [DBNAME]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--
CREATE PROCEDURE [dbo].[spImportData]
#DataImported dbo.ValuesToInsert READONLY
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO [dbo].[TableName] (Value1, Value2, Value3)
SELECT Value1, Value2, Value3
FROM #DataImported
3.- Pass a datatable from your code to DB, in this case using Dapper.net as following:
DataTable dtExcelData = new DataTable();
//Fill dtExcelData and pass as parameter
ParametersCollection param = new ParametersCollection();
param.Add(CreateParameter("#DataImported", dtExcelData));
ExecuteDataSet("spImportData", CommandType.StoredProcedure, param);

Error CODE : procedure has too many arguments specified

I have a this SQL Server stored procedure. When I execute it, I'm getting this error:
SQL Server procedure has too many arguments specified
How can I solve this problem? Code is shown below.
When my stored procedure is working, I need to do if record exist update then add record.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Insert_MS]
(#SID char(20),
#CREATE_DATETIME char(14),
#MODIFY_DATETIME char(14),
#CREATOR_SID char(20),
#MODIFIER_SID char(20),
#MARK_DELETED char(1),
#TARGET_SID nvarchar(20),
#TARGET_CODE nvarchar(50),
#UNIT nvarchar(100),
#SPECIFICATION nvarchar(1000),
#MATERIALS_SUBCAT nvarchar(1000),
#SORT int,
#SET_UNIT nvarchar(1000),
#ENABLED char(1),
#MARKET_TYPE nvarchar(2)
)
AS
BEGIN
IF EXISTS (SELECT *
FROM [dbo].[M_S]
WHERE [MARKET_TYPE] = #MARKET_TYPE
AND [TARGET_CODE] = #TARGET_CODE
AND [TARGET_SID] = #TARGET_SID)
BEGIN
--update existing record
UPDATE [dbo].[M_S]
SET [MATERIALS_SUBCAT] = #MATERIALS_SUBCAT ,
[SPECIFICATION] = #SPECIFICATION,
[UNIT] = #UNIT
WHERE [MARKET_TYPE] = #MARKET_TYPE
AND [TARGET_CODE] = #TARGET_CODE
AND [TARGET_SID] = #TARGET_SID
END
ELSE
BEGIN
--insert new record
INSERT INTO [dbo].[M_S] ([SID], [CREATE_DATETIME], [MODIFY_DATETIME],
[CREATOR_SID], [MODIFIER_SID], [MARK_DELETED],
[TARGET_SID], [TARGET_CODE], [UNIT], [SPECIFICATION],
[MATERIALS_SUBCAT], [SORT], [SET_UNIT],
[ENABLED], [MARKET_TYPE])
VALUES (#SID, #CREATE_DATETIME, #MODIFY_DATETIME,
#CREATOR_SID, #MODIFIER_SID, #MARK_DELETED,
#TARGET_SID, #TARGET_CODE, #UNIT,
#SPECIFICATION,
#MATERIALS_SUBCAT, #SORT, #SET_UNIT,
#ENABLED, #MARKET_TYPE)
END
END
Then my aspx.cs code is here
cnn.Open();
insertSql += " INSERT INTO [dbo].[MATERIALS_SUBCAT] ([SID],[CREATE_DATETIME], [MODIFY_DATETIME],";
insertSql += " [CREATOR_SID], [MODIFIER_SID], [MARK_DELETED],[TARGET_SID], [TARGET_CODE],";
insertSql += " [UNIT], [SPECIFICATION], [MATERIALS_SUBCAT], [SORT],[SET_UNIT], [ENABLED], [MARKET_TYPE])";
insertSql += " VALUES (#SID, #CREATE_DATETIME, #MODIFY_DATETIME, #CREATOR_SID, #MODIFIER_SID, #MARK_DELETED, #TARGET_SID, #TARGET_CODE, #UNIT, #SPECIFICATION,";
insertSql += "#MATERIALS_SUBCAT, #SORT, #SET_UNIT, #ENABLED, #MARKET_TYPE) ";
SqlCommand cmdStoredProcedure = new SqlCommand("Insert_MS", cnn);
cmdStoredProcedure.CommandType = CommandType.StoredProcedure;
for (int k = 0; k <= dt_sheet.Rows.Count - 1; k++)
{
cmdStoredProcedure.Parameters.AddWithValue("#SID", dt_sheet.Rows[k]["SID"].ToString());
cmdStoredProcedure.Parameters.AddWithValue("#CREATE_DATETIME", dt_sheet.Rows[k]["CREATE_DATETIME"].ToString());
cmdStoredProcedure.Parameters.AddWithValue("#MODIFY_DATETIME", dt_sheet.Rows[k]["MODIFY_DATETIME"].ToString());
cmdStoredProcedure.Parameters.AddWithValue("#CREATOR_SID", dt_sheet.Rows[k]["CREATOR_SID"].ToString());
cmdStoredProcedure.Parameters.AddWithValue("#MODIFIER_SID", dt_sheet.Rows[k]["MODIFIER_SID"].ToString());
cmdStoredProcedure.Parameters.AddWithValue("#MARK_DELETED", dt_sheet.Rows[k]["MARK_DELETED"].ToString());
cmdStoredProcedure.Parameters.AddWithValue("#TARGET_SID", dt_sheet.Rows[k]["分類代碼"].ToString());
cmdStoredProcedure.Parameters.AddWithValue("#TARGET_CODE", dt_sheet.Rows[k]["品項代碼"].ToString());
cmdStoredProcedure.Parameters.AddWithValue("#UNIT", dt_sheet.Rows[k]["單位"].ToString());
cmdStoredProcedure.Parameters.AddWithValue("#SPECIFICATION", dt_sheet.Rows[k]["規格"].ToString());
cmdStoredProcedure.Parameters.AddWithValue("#MATERIALS_SUBCAT", dt_sheet.Rows[k]["品項名稱"].ToString());
cmdStoredProcedure.Parameters.AddWithValue("#SORT", dt_sheet.Rows[k]["SORT"].ToString());
cmdStoredProcedure.Parameters.AddWithValue("#SET_UNIT",null);
cmdStoredProcedure.Parameters.AddWithValue("#ENABLED", dt_sheet.Rows[k]["ENABLED"].ToString());
cmdStoredProcedure.Parameters.AddWithValue("#MARKET_TYPE", dt_sheet.Rows[k]["MARKET_TYPE"].ToString());
cmdStoredProcedure.ExecuteNonQuery();
cnn.Close();
}
Seems like you want to execute the stored procedure each time you loop through your sheet. Moving the Command into the loop and use "using" to easy dispose the command each time, like this:
for (int k = 0; k <= dt_sheet.Rows.Count - 1; k++)
{
using (SqlCommand cmdStoreProcedure = new SqlCommand("Insert_MS", cnn))
{
cmdStoreProcedure.CommandType = CommandType.StoredProcedure;
cmdStoreProcedure.Parameters.AddWithValue("#SID", dt_sheet.Rows[k]["SID"].ToString());
cmdStoreProcedure.Parameters.AddWithValue("#CREATE_DATETIME", dt_sheet.Rows[k]["CREATE_DATETIME"].ToString());
cmdStoreProcedure.Parameters.AddWithValue("#MODIFY_DATETIME", dt_sheet.Rows[k]["MODIFY_DATETIME"].ToString());
cmdStoreProcedure.Parameters.AddWithValue("#CREATOR_SID", dt_sheet.Rows[k]["CREATOR_SID"].ToString());
cmdStoreProcedure.Parameters.AddWithValue("#MODIFIER_SID", dt_sheet.Rows[k]["MODIFIER_SID"].ToString());
cmdStoreProcedure.Parameters.AddWithValue("#MARK_DELETED", dt_sheet.Rows[k]["MARK_DELETED"].ToString());
cmdStoreProcedure.Parameters.AddWithValue("#TARGET_SID", dt_sheet.Rows[k]["分類代碼"].ToString());
cmdStoreProcedure.Parameters.AddWithValue("#TARGET_CODE", dt_sheet.Rows[k]["品項代碼"].ToString());
cmdStoreProcedure.Parameters.AddWithValue("#UNIT", dt_sheet.Rows[k]["單位"].ToString());
cmdStoreProcedure.Parameters.AddWithValue("#SPECIFICATION", dt_sheet.Rows[k]["規格"].ToString());
cmdStoreProcedure.Parameters.AddWithValue("#MATERIALS_SUBCAT", dt_sheet.Rows[k]["品項名稱"].ToString());
cmdStoreProcedure.Parameters.AddWithValue("#SORT", dt_sheet.Rows[k]["SORT"].ToString());
cmdStoreProcedure.Parameters.AddWithValue("#SET_UNIT", null);
cmdStoreProcedure.Parameters.AddWithValue("#ENABLED", dt_sheet.Rows[k]["ENABLED"].ToString());
cmdStoreProcedure.Parameters.AddWithValue("#MARKET_TYPE", dt_sheet.Rows[k]["MARKET_TYPE"].ToString());
// connection.Open();
cmdStoreProcedure.ExecuteNonQuery();
}
}
cnn.Close();
Your code tries to access SQL Commmand: Insert_Materials_SubCategory
Whereas the shown procedure is called: Insert_MS

Update if exist in SQL Server table

How to update the full row if BatchNumber (in my case) exists?
In my table batch number is unique and I need to update the entire row or the quantity column if Batchnumber is exist
Please, help me to do this in a proper way
{
var conn = new SqlConnection(GetConnectionString());
var StrBuilder = new StringBuilder(string.Empty);
var splitItems = (string[])null;
foreach (string item in SC_PurLinr)
{
const string sqlStatement = "INSERT INTO DEL_Stores (DealerCode, Code, Qty, ExpireDate, BatchNumber) VALUES";
if (item.Contains(","))
{
splitItems = item.Split(",".ToCharArray());
StrBuilder.AppendFormat("{0}('{1}','{2}','{3}','{4}','{5}'); ", sqlStatement, splitItems[0], splitItems[1], splitItems[2], splitItems[3], splitItems[4]);
}
}
try
{
conn.Open();
SqlCommand cmd = new SqlCommand(StrBuilder.ToString(), conn) { CommandType = CommandType.Text };
cmd.ExecuteNonQuery();
wucMessagePopup1.showPopup(1, string.Empty, "Record Saved Successfully.");
}
catch (SqlException ex)
{
}
finally
{
conn.Close();
}
}
Use MERGE from SQL Server 2008:
WITH new_rows (
SELECT #value value
,#BatchNumber BatchNumber)
MERGE DEL_Stores target
USING new_rows source ON source.BatchNumber = target.BatchNumber
WHEN MATCHED THEN
UPDATE SET value = #value
WHEN NOT MATCHED THEN
INSERT (
BatchNumber
,value)
VALUES(
source.BatchNumber
source.value);
You can achieve this by stored procedure in better way.
Your procedure should be like this.
create PROCEDURE usp_Namae
#parmeter INT
,#parmeter INT
,#BatchNumber INT
AS
BEGIN
IF NOT EXISTS (
SELECT *
FROM tblname
WHERE BatchNumber = #BatchNumber
)
BEGIN
--INSERT query
END
ELSE
BEGIN
--Update query
END
END
Just add IF statement before insert data as below:
IF EXISTS (select * from sys.columns where object_id = OBJECT_ID(N'DEL_Stores') and name='BatchNumber')
BEGIN
// Do insert here
END

asp.net C# sql query dependant on session data

I have a Session, which is list int, and I need to make a query that will take from a database only those rows that have the PK value that exists in Session.
I was thinking of doing it with the IN function, or making a new datatable with 1 collumn and values from the Session and doing a double join, probably left...
I just dont know how to make a table from a list.
What I have so far:
String ConnString = "Data Source=BRACO-PC\SQL1;Initial Catalog=DiplomskiSQL1SQL;Integrated Security=True";
SqlConnection Conn = new SqlConnection(ConnString);
Conn.Open();
DataTable ukosarici = new DataTable();
SqlDataAdapter da = new SqlDataAdapter("Select Proizvodi.ime, TipProizvoda.tip, Proizvodi.dimenzije, Proizvodi.cijena from Proizvod LEFT JOIN TipProizvoda On Proizvod.tip=TipProizvoda.id_t WHERE Proizvod.id_p IN ", Conn);
SqlCommandBuilder cmd = new SqlCommandBuilder(da);
da.Fill(ukosarici);
GridView1.DataSource = ukosarici;
GridView1.DataBind();
Conn.Close();
Create a temporary table or table variable, insert the ints into it using INSERT or BULK INSERT, do a join in the SQL query then drop the temp table or table variable.
There are many ways you could do this, but one of my preferred methods is to serialize the list to a CSV, e.g. '1,3,5,33'. I then use a custom SQL Table function to de-serialize the list and filter in the database:
SELECT * FROM mytable t
JOIN dbo.ufn_CSVtoTextList('1,3,5,33' , ',') csv
ON csv.[Entry] = t.Id
The ufn_CSVtoTextList function CREATE script is below:
CREATE FUNCTION [dbo].[ufn_CSVToTextlist] ( #StringInput nVARCHAR(max) ,#SepChar nchar(1) = ',')
RETURNS #OutputTable TABLE ( [Entry] nVarchar(255), [index] int identity (0,1) )
AS
BEGIN
DECLARE #Entry nVarChar(255)
WHILE LEN(#StringInput) > 0
BEGIN
SET #Entry = LEFT(#StringInput,
ISNULL(NULLIF(CHARINDEX(#SepChar, #StringInput) - 1, -1),
LEN(#StringInput)))
SET #StringInput = SUBSTRING(#StringInput,
ISNULL(NULLIF(CHARINDEX(#SepChar, #StringInput), 0),
LEN(#StringInput)) + 1, LEN(#StringInput))
INSERT INTO #OutputTable ( [Entry] )
VALUES ( #Entry )
END
RETURN
END
Try by changing your SqlDataAdapter Call as follows
List<int> list ; // Assign with your session int list values
List<string> l2 = list.ConvertAll<string>(delegate(int i) { return i.ToString(); });
string query = "Select Proizvodi.ime, TipProizvoda.tip, Proizvodi.dimenzije, Proizvodi.cijena from Proizvod LEFT JOIN TipProizvoda On Proizvod.tip=TipProizvoda.id_t WHERE Proizvod.id_p IN (";
query = query + string.Join(",", l2.ToArray()) + ")";
SqlDataAdapter da = new SqlDataAdapter(query, Conn);

Executing SQL Stored Procedure

ALTER PROCEDURE dbo.SP_InsertTicket
/*
(
#parameter1 int = 5,
#parameter2 datatype OUTPUT
)
declare #i as numeric
exec SP_InsertTicket 'asd','cd#y.com','232323','dasasd','sdasdas','01-jan-2010',#i output,'sdas','sdasd','02-jan-2010'
select #i*/
#Client_FullName varchar(30),
#Client_EmailAdd varchar(50),
#Client_Telephn varchar(15),
#Ticket_Subject varchar(50),
#Ticket_Source varchar(15),
#Ticket_CreateDate Datetime,
#Ticket_Id integer output,
#Que_Message varchar(100),
#Que_Attachment varchar(max),
#Que_UpdateDate Datetime
AS
declare #TickID integer;
/* SET NOCOUNT ON */
BEGIN
INSERT INTO tbl_Ticket (Client_FullName,Client_EmailAdd,Client_Telephn,Ticket_Subject,Ticket_Source,Ticket_CreateDate)
VALUES (#Client_FullName, #Client_EmailAdd ,#Client_Telephn,#Ticket_Subject,#Ticket_Source,#Ticket_CreateDate)
Select #TickID = MAX(Ticket_Id) from tbl_Ticket
set #Ticket_Id=#TickID
INSERT INTO tbl_TicketQuestion (Ticket_Id,Que_Message,Que_Attachment,Que_UpdateDate)
VALUES (#TickID,#Que_Message,#Que_Attachment,#Que_UpdateDate)
END
RETURN
This is my store procedure in which i need to return Ticket_Id to send it via email app
It insert records well bt not able to retirn value in DAL
Below is the code for executing stored procedure which returns value
public class cls_DAL
{
public cls_DAL()
{
//
// TODO: Add constructor logic here
//
}
static string strConn = System.Configuration.ConfigurationManager.ConnectionStrings["conString"].ConnectionString.ToString();
SqlConnection con = new SqlConnection(strConn);
SqlCommand cmd = new SqlCommand();
SqlDataAdapter da = new SqlDataAdapter();
DataSet ds = new DataSet();
DataTable dt = new DataTable();
public int insert_NewTicket(string fullname, string emailadd, string telephone, string subject, string source, DateTime date,string Message, string attachment, DateTime updatedate)
{
try
{
con.Open();
cmd = new SqlCommand("SP_InsertTicket", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Client_FullName", fullname);
cmd.Parameters.AddWithValue("#Client_EmailAdd", emailadd);
cmd.Parameters.AddWithValue("#Client_Telephn",telephone);
cmd.Parameters.AddWithValue("#Ticket_Subject", subject);
cmd.Parameters.AddWithValue("#Ticket_Source",source);
cmd.Parameters.AddWithValue("#Ticket_CreateDate",date);
cmd.Parameters.AddWithValue("#Ticket_Id",0);
cmd.Parameters.AddWithValue("#Que_Message", Message);
cmd.Parameters.AddWithValue("#Que_Attachment", attachment);
cmd.Parameters.AddWithValue("#Que_UpdateDate",updatedate);
cmd.Parameters["#Ticket_Id"].Direction = ParameterDirection.InputOutput;
return cmd.ExecuteNonQuery();
int i = (int)cmd.Parameters["#Ticket_Id"].Value;
}
catch
{
throw;
}
finally
{
cmd.Dispose();
con.Close();
con.Dispose();
}
}
}
Its just a guess, not sure. You can give a try the following:
cmd.Parameters["#Ticket_Id"].Direction = ParameterDirection.InputOutput;
TO
cmd.Parameters["#Ticket_Id"].Direction = ParameterDirection.Output;
That won't compile you'll get unreachable code
cmd.Parameters["#Ticket_Id"].Direction = ParameterDirection.InputOutput; cmd.ExecuteNonQuery();
return (int)cmd.Parameters["#Ticket_Id"].Value;
or #Matt's solution below...
That cast is iffy as well...
And in a multi user scenario, ticketid will race.
Think about what could (will!!!) happen if you run two of these at the same time
Should be wrapped in a transaction.
And you don't need Max, either, Use Scope_Identity
You could run Select Scope_Identity() after the Insert statement. Then in your DAL Method return Convert.ToInt32(cmd.ExecuteScalar())
Change this:
return cmd.ExecuteNonQuery();
to
Int i = cmd.ExecuteScalar();
If you are only returning one integer from that procedure.
ExecuteNonQuery() isnt the method you want to be using here

Categories