Insert and Update with XML in stored procedure - asp.net

I need some help in using a stored procedure in my case below: I have a table with a single XML column which takes in fields VoucherCode and Quantity, the data in SQL xml column looks like this:
<CampaignVoucher xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" VoucherCode="Vouch001" Quantity="2" />
The below method will call my stored procedure to check if a particular voucher exist based on my voucher code and then either add a new row or update an existing voucher in my gridview:
Protected Sub btnAdd_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnAdd.Click
Dim dbCommand As DbCommand = Nothing
'Dim cmd As New SqlCommand()
If TextBox1.Text = "" Or DropDownList1.SelectedIndex = 0 Then
Exit Sub
End If
Dim con As New SqlConnection(ConfigurationManager.ConnectionStrings("Test").ConnectionString)
Dim da As New SqlDataAdapter("SELECT CustomerID, VoucherXML FROM Customers", con)
Dim cmd As New SqlCommand("Campaign_InsertRewardsVoucher_XML", con)
cmd.CommandType = CommandType.StoredProcedure
Dim dt As New DataTable()
da.Fill(dt)
' Here we'll add a blank row to the returned DataTable
Dim dr As DataRow = dt.NewRow()
dt.Rows.InsertAt(dr, 0)
'Creating the first row of GridView to be Editable
GridView1.EditIndex = 0
GridView1.DataSource = dt
GridView1.DataBind()
'Changing the Text for Inserting a New Record
DirectCast(GridView1.Rows(0).Cells(0).Controls(0), LinkButton).Text = "Insert"
' Serialization ----------------------------
Dim cm As New CampaignVoucher(DropDownList1.SelectedValue, TextBox1.Text)
Dim serializer As New XMLserializer(cm.[GetType]())
Dim memoryStream As New MemoryStream()
Dim writer As New XmlTextWriter(memoryStream, Encoding.UTF8)
serializer.Serialize(writer, cm)
'get the stream from the writer
memoryStream = TryCast(writer.BaseStream, MemoryStream)
'apply encoding to the stream
Dim enc As New UTF8Encoding()
Dim xml As String = enc.GetString(memoryStream.ToArray()).Trim()
' -------------------------------------------
cmd.Parameters.Add("#p1", SqlDbType.VarChar, 50).Value = DropDownList1.SelectedValue
cmd.Parameters.Add("#p2", SqlDbType.Text).Value = xml
cmd.Connection = con
con.Open()
cmd.ExecuteScalar()
con.Close()
GridView1.EditIndex = -1
BindData()
TextBox1.Text = ""
End Sub
Backtrack a little, I wrote this working stored proc as shown below for the same purpose just that it was meant for a conventional storage: 1 table with a VoucherCode and Quantity column, now with the XML column, now encapsulating both VoucherCode and Quantity values, I am lost to how to rewrite my stored proc, tried different ways but apparently I made a mess out of it, please advice, thanks!:
ALTER PROCEDURE [dbo].[Campaign_InsertRewardsVoucher]
#VoucherCode nvarchar(50) =NULL,
#Quantity int = NULL
--#ExistingQuantity int = NULL
AS
BEGIN
DECLARE #ExistingQuantity Int = Null
IF EXISTS (SELECT * FROM ForTest_Campaign_Voucher WHERE VoucherCode=#VoucherCode)
BEGIN
SET #ExistingQuantity = (SELECT Quantity from ForTest_Campaign_Voucher Where VoucherCode=#VoucherCode)
SET #ExistingQuantity = (#ExistingQuantity + #Quantity)
UPDATE ForTest_Campaign_Voucher SET VoucherCode=#VoucherCode, Quantity=#ExistingQuantity Where VoucherCode=#VoucherCode
END
ELSE
INSERT INTO ForTest_Campaign_Voucher(VoucherCode, Quantity) VALUES(#VoucherCode, #Quantity)
END

ALTER PROCEDURE [dbo].[Campaign_InsertRewardsVoucher]
#VoucherCode nvarchar(50) =NULL,
#Quantity int = NULL
AS
BEGIN
DECLARE #ExistingQuantity Int
SET #ExistingQuantity = (SELECT xmlFieldName.value('(/CampaignVoucher/#Quantity)[1]', 'int')
FROM ForTest_Campaign_Voucher
WHERE xmlFieldName.value('(/CampaignVoucher/#VoucherCode)[1]', 'nvarchar(50)') = #VoucherCode)
IF #ExistingQuantity IS NULL
BEGIN
INSERT INTO ForTest_Campaign_Voucher
(
xmlFieldName
)
VALUES
(
'<CampaignVoucher xmlns:xsd="http://www.w3.org/2001/XMLSchema" VoucherCode="' + #VoucherCode + '" Quantity="' + CAST(#Quantity AS NVARCHAR(16)) + '" />'
)
END
ELSE
DECLARE #NewQuantity INT
SET #NewQuantity = #ExistingQuantity + #Quantity
UPDATE ForTest_Campaign_Voucher
SET xmlFieldName='<CampaignVoucher xmlns:xsd="http://www.w3.org/2001/XMLSchema" VoucherCode="' + #VoucherCode + '" Quantity="' + CAST(#NewQuantity AS NVARCHAR(16)) + '" />'
WHERE xmlFieldName.value('(/CampaignVoucher/#VoucherCode)[1]', 'nvarchar(50)') = #VoucherCode
END
GO

Related

GridViewUpdateEventArgs not working with update to sql table

I'm not getting my GridViewUpdateEventArgs to work for some reason.
I'm trying to update my gridview(table in sql) but it´s not working.
And i don´t know how to write the the Where clause in the sql to match.
Public Sub GridView1_RowUpdating(sender As Object, e As GridViewUpdateEventArgs)
Dim SelectRow As GridViewRow = Gridview1.Rows(e.RowIndex)
Dim RowID As HiddenField = Gridview1.FindControl("ID")
Dim Report As String = SelectRow.Cells(1).Text
Dim BusinessArea As String = SelectRow.Cells(2).Text
Dim Salesdepartment As String = SelectRow.Cells(3).Text
Using SqlConnection As New SqlConnection(SqlConnectionString)
SqlConnection.Open()
Dim SqlCommand As New SqlCommand("UPDATE TEST SET Report = ('" & Report & "'), [Business Area] = ('" & BusinessArea & "'), Salesdepartment = ('" & Salesdepartment & "') WHERE ID = #RowID ", SqlConnection)
Dim SqlDataAdapter As New SqlDataAdapter(SqlCommand)
Dim dataSet As New DataSet()
SqlDataAdapter.Fill(dataSet)
Gridview1.EditIndex = -1
BindDataToGridView()
SqlConnection.Close()
End Using
The "ID" column is my PK in the table and is in a (ItemTemplate) (Hidden)
In this Way SqlDataAdapter can't update database record, see here how to update record using SqlDataAdapter .
or you can try like this:
Dim row As GridViewRow = Gridview1.Rows(e.RowIndex)
Dim hf As HiddenField = TryCast(row.FindControl("ID"), HiddenField)
Dim Report As [String] = row.Cell(1).Text
Dim BusinessArea As [String] = row.Cell(2).Text
Dim Salesdepartment As [String] = row.Cell(3).Text
Using SqlConnection As New SqlConnection(SqlConnectionString)
SqlConnection.Open()
Dim cmd As New SqlCommand("UPDATE TEST SET Report = #Report,[Business Area] =#BusinessArea, Salesdepartment=#Salesdepartment WHERE ID = #RowID ", SqlConnection)
cmd.Parameters.AddWithValue("#Report", Report)
cmd.Parameters.AddWithValue("#BusinessArea", BusinessArea)
cmd.Parameters.AddWithValue("#Salesdepartment", Salesdepartment)
cmd.Parameters.AddWithValue("#RowID", hf.Value)
cmd.ExecuteNonQuery()
Gridview1.EditIndex = -1
BindDataToGridView()
SqlConnection.Close()
End Using

Conversion failed when converting the varchar value 'table' to data type int

I'm creating multiple choice question system. So far i create these 4 tables and 1 view.
The tables are tblQuestion, tblAnswer, tblQuiz, tblResult and tblResultDetail. tblQuestion is to store the questions, tblAnswer to store the answers of the question,tblResult is to record for every user that answers the quiz, and store the users answers in TblResultDetails.
Based on the code below, the data is read from view. I use 1 , 2 , 3, 4 as it is the column name of the view. I did this to randomize the answers.
Sub soalan()
conn.Open()
Dim myArr(3) As String
Dim cmd As New SqlCommand("Select * From view_Soalan Where QuestionID=#IdSoalan", conn)
cmd.Parameters.AddWithValue("#IdSoalan", Counter)
Dim dr1 As SqlDataReader
dr1 = cmd.ExecuteReader
If dr1.Read() Then
Me.lblSoalan.Text = dr1("QuestionTxt")
Me.RadioButton1.Text = dr1("1")
myArr(0) = dr1("1")
Me.RadioButton2.Text = dr1("2")
myArr(1) = dr1("2")
Me.RadioButton3.Text = dr1("3")
myArr(2) = dr1("3")
Me.RadioButton4.Text = dr1("4")
myArr(3) = dr1("4")
Dim answerId As String
If Me.RadioButton1.Checked = True Then
answerId = dr1("1")
ElseIf Me.RadioButton2.Checked = True Then
answerId = dr1("2")
ElseIf Me.RadioButton3.Checked = True Then
answerId = dr1("3")
ElseIf Me.RadioButton4.Checked = True Then
answerId = dr1("4")
End If
'Dim jawapan As Integer = CInt(answerId)
Session("jaw") = answerId
Else
conn.Close()
Counter += 1
soalan()
End If
conn.Close()
End Sub
Sub bersih()
RadioButton1.Checked = False
RadioButton2.Checked = False
RadioButton3.Checked = False
RadioButton4.Checked = False
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
soalan()
End Sub
Sub masuk()
conn.Open()
Dim cmdGetId As New SqlCommand("Select MAX(ResultId) From TblResult", conn)
cmdGetId.ExecuteNonQuery()
Dim drBaca As SqlDataReader
drBaca = cmdGetId.ExecuteReader
While drBaca.Read
Dim maxID As Integer = drBaca(0)
Session("maximum") = maxID
End While
conn.Close()
conn.Open()
Dim cmdInsert As New SqlCommand("Insert into TblResultDetail (ResultDetail_Result_Id,ResultDetail_Answer_Id) values ('" & Session("maximum") & "','" & Session("jaw") & "')", conn)
cmdInsert.ExecuteNonQuery()
conn.Close()
End Sub
End Class
I got error
Conversion failed when converting the varchar value 'table' to data
type int.
at the cmdInsert command. I know that i cant insert the session("jaw") into table directly. So how to replace it?
In your query you are quoting integers:
... values ('" & Session("maximum") & "','"
Simply remove the quotes. Also you should user Parameters instead to prevent SQL Injection.
I.e.
Dim cmdInsert As New SqlCommand("Insert into TblResultDetail (ResultDetail_Result_Id,ResultDetail_Answer_Id) values (#max, #jaw)", conn)
cmdInsert.Parameters.AddWithValue("#max", Session("maximum"))
cmdInsert.Parameters.AddWithValue("#jaw", Session("jaw"))
I think that you have store in some of this fields a wrong value.
use this
Public Module MyExtensions
<System.Runtime.CompilerServices.Extension()> _
Public Function IsInteger(ByVal value As String) As Boolean
If String.IsNullOrEmpty(value) Then
Return False
Else
Return Integer.TryParse(value, Nothing)
End If
End Function
<System.Runtime.CompilerServices.Extension()> _
Public Function ToInteger(ByVal value As String) As Integer
If value.IsInteger() Then
Return Integer.Parse(value)
Else
Return 0
End If
End Function
End Module
and then
value.ToInteger() <-- returns 0 if it is not an integer
There is another error in your code. You should use ExecuteScalar instead of ExecuteNonQuery in the query that starts with
"Select MAX(ResultId)...."
Dim cmdGetId As New SqlCommand("Select MAX(ResultId) From TblResult", conn)
Dim maxID As Integer= cmdGetId.ExecuteScalar
Session("maximum") = maxID
ExecuteScalar is typically used when your query returns a single value.
ExecuteNonQuery is typically used for SQL statements without results (UPDATE, INSERT, etc.).
Refer this

Stored Procedure Variable (Code error I believe is there)

I am trying to create a script to tidy all the columns and rows in SQL Server (I will be doing more than trimming but once it works I can plug into app-code I have already)
I think I am there but it does not seem to update - maybe the stored procedure is wrong? I believe the error is here.. -- I have looked around about variables in stored procedures and think it looks correct to me.
Insert statements for procedure here
UPDATE systemUsers
SET #ColumnName = #Update
WHERE ID = #ID
Full script...
Protected Sub btnTest_Click(sender As Object, e As System.EventArgs) Handles btnTest.Click
'Select the column names
Dim cn As SqlConnection = New SqlConnection()
Dim cmd As SqlCommand = New SqlCommand()
Dim dr As SqlDataReader
Dim i As Integer = 0
cn.ConnectionString = ConfigurationManager.ConnectionStrings("mySQLConnectionString").ConnectionString
cmd.Connection = cn
' this gets the colum name
cmd.CommandText = "select COLUMN_NAME FROM INFORMATION_SCHEMA.Columns where TABLE_NAME = 'systemUsers'"
'Open the connection to the database
cn.Open()
' Execute the sql.
dr = cmd.ExecuteReader()
' Read all of the rows generated by the command (in this case only one row).
CheckBoxList1.Items.Clear() 'remove all items for the new list
Do While dr.Read()
i = i + 1
Session.Item("ColumnName" & i) = dr.Item("COLUMN_NAME").ToString()
Loop
' Close your connection to the DB.
dr.Close()
cn.Close()
Dim j As Integer = 1
For j = 1 to i
cn.ConnectionString = ConfigurationManager.ConnectionStrings("mySQLConnectionString").ConnectionString
cmd.Connection = cn
cmd.CommandText = "Select * From [systemUsers]"
'Open the connection to the database
cn.Open()
' Execute the sql.
dr = cmd.ExecuteReader()
' Read all of the rows generated by the cmd (in this case only one row).
Dim vName As String = ""
If vName = "ID" Then
'skip as ID should never be edited!!
Else
Do While dr.Read()
vName = Session.Item("ColumnName" & j).ToString ' put into vName for Stored Procedure
Dim sConnString As String = System.Web.Configuration.WebConfigurationManager.ConnectionStrings("mySQLConnectionString").ConnectionString
Dim dsNames As SqlDataSource
dsNames = New SqlDataSource
dsNames.ConnectionString = sConnString
Dim sSQL As String
sSQL = "SPTidy"
dsNames.UpdateCommand = sSQL
dsNames.UpdateCommandType = SqlDataSourceCommandType.StoredProcedure
dsNames.UpdateParameters.Clear()
dsNames.UpdateParameters.Add("ID", dr.Item("ID").ToString())
dsNames.UpdateParameters.Add("Update", Trim(dr.Item(vName).ToString()))
dsNames.UpdateParameters.Add("ColumnName", vName)
dsNames.Update()
dsNames = Nothing
Loop
End If
j = j + 1
' Close your connection to the DB.
dr.Close()
cn.Close()
Next
End Sub
Stored procedure:
create PROCEDURE [dbo].[SPTidy]
#ID bigint,
#Update nvarchar(max),
#ColumnName nvarchar(max)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
UPDATE systemUsers
SET #ColumnName = #Update
WHERE ID = #ID
END
That code won't throw an error message because it's simply updating the variable. To have a dynamic column name you need to use dynamic SQL (or complicated case statements) but dynamic SQL is better in this instance.
DECLARE #sql nvarchar(max) = '';
SET #sql = N'UPDATE systemUsers SET ' + #ColumnName + N' = ' + #Update + N' WHERE ID=' + #ID
EXEC sp_executesql #sql
Hope this helps :)

ASP.NET variable not getting assigned values

Im having problem with this asp.net code.
the variables qty and itname are not getting valid values ...can anyone find out the problem ?
Imports System.Data
Imports System.Data.SqlClient
Partial Class consolidate
Inherits System.Web.UI.Page
Public lastreq_no As Int32
Protected Sub btnconsolidate_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnconsolidate.Click
Dim qtypen As Integer
Dim qtypencil As Integer
Dim qtygbag As Integer
Dim qtysugar As Integer
Dim i As Integer
Dim req As Integer
Dim qty As Integer
Dim itname As String = ""
Dim sqlcon As New SqlConnection("Data Source=user-hp\sqlexpress;initial catalog=campco;integrated security=true;")
If sqlcon.State = ConnectionState.Open Then
sqlcon.Close()
End If
sqlcon.Open()
Dim str As String
str = "Select Req_no from Requirements "
Dim cmd As New SqlCommand(str, sqlcon)
Dim sdr As SqlDataReader
sdr = cmd.ExecuteReader()
sdr.Read()
lastreq_no = sdr.GetInt32(sdr.VisibleFieldCount - 1)
For i = 0 To sdr.VisibleFieldCount - 1
req = sdr.GetInt32(i)
While req > lastreq_no
Dim selcomnd1 As String
Dim selcomnd2 As String
selcomnd1 = "Select #itname=It_name from Requirements where Req_no= #req"
selcomnd2 = "Select #qty= Quantity from Requirements where Req_no= #req"
Dim sqlcomnd1 As New SqlCommand(selcomnd1, sqlcon)
Dim sqlcomnd2 As New SqlCommand(selcomnd2, sqlcon)
sqlcomnd1.Parameters.AddWithValue("#itname", itname)
sqlcomnd2.Parameters.AddWithValue("#qty", qty)
sqlcomnd1.ExecuteScalar()
sqlcomnd2.ExecuteScalar()
TextBox1.Text = itname
TextBox2.Text = qty
sqlcon.Close()
sqlcon.Open()
Select Case (itname)
Case "Pen"
qtypen += qty
lastreq_no = req
Case "Pencil"
qtypencil += qty
lastreq_no = req
Case "Gunny bag"
qtygbag += qty
lastreq_no = req
Case "Sugar"
qtysugar += qty
lastreq_no = req
End Select
End While
Next
sqlcon.Close()
If sqlcon.State = ConnectionState.Open Then
sqlcon.Close()
End If
sqlcon.Open()
Dim comm As String
comm = "Insert into Consolidate (lastr_no,qtypen,qtypencil,qtygunnybag,qtysugar)values('" + lastreq_no.ToString + "','" + qtypen.ToString + "','" + qtypencil.ToString + "','" + qtygbag.ToString + "','" + qtysugar.ToString + "')"
Dim sqlcomm As New SqlCommand(comm, sqlcon)
Dim s As String
s = sqlcomm.ExecuteNonQuery()
sqlcon.Close()
End Sub
End Class
To start with, neither scalar statement is valid. Have you attempted to run those statements in SQL Management Studio or similar program to test the statements themselves? They should be something like:
selcomnd1 = "Select It_name from Requirements where Req_no=#req"
selcomnd2 = "Select Quantity from Requirements where Req_no=#req"
And then you would assign them in this manner:
itname = CType(sqlcmnd1.ExecuteScalar(), String) ' .ToString() would probably work here as well
qty = Convert.Int32(sqlcmnd2.ExecuteScalar())
Or you could use .TryParse for the qty:
Integer.TryParse(sqlcmnd2.ExecuteScalar(), qty)
The line
sqlcomnd1.Parameters.AddWithValue("#itname", itname)
provides an input parameter with the value itname. No value has been assigned to this variable.
You need to add an output parameter: see here for how to do this.
Get output parameter value in ADO.NET

retrieving whole database into dataset

I have access db with 3 different tables,I want to load the whole database into dataset so I will be able to work with the data without load the db serval times.
all the examples of working with dataset are showing how to get part of the database using ".fill"
for example :
OleDbCommand CommandObject = new OleDbCommand ("Select * from employee");
OleDbAdapter myDataAdapter = new OleDbAdapter (null, con);
myDataAdapter.SelectCommand = CommandObject;
myDataAdapter.Fill (myDataSet, "EmployeeData");
this example load only from employee but how can I etrieve the all tables in once into dataset?
in xml for instance there is command to load all the document to dataset with:" dataset.ReadXml"
How can I achive it in access db?
Thanks for any help
Baaroz
Protected Function getDataSetAndFill(ByRef connection As OleDb.OleDbConnection,
Optional ByVal isExportSchema As Boolean = True) As DataSet
Dim myDataSet As New DataSet
Dim myCommand As New OleDb.OleDbCommand
Dim myAdapter As New OleDb.OleDbDataAdapter
myCommand.Connection = connection
'Get Database Tables
Dim tables As DataTable = connection.GetOleDbSchemaTable( _
System.Data.OleDb.OleDbSchemaGuid.Tables, _
New Object() {Nothing, Nothing, Nothing, "TABLE"})
'iterate through all tables
Dim table As DataRow
For Each table In tables.Rows
'get current table's name
Dim tableName As String = table("TABLE_NAME")
Dim strSQL = "SELECT * FROM " & "[" & tableName & "]"
Dim adapter1 As New OleDb.OleDbDataAdapter(New OleDb.OleDbCommand(strSQL, connection))
adapter1.FillSchema(myDataSet, SchemaType.Source, tableName)
'Fill the table in the dataset
myCommand.CommandText = strSQL
myAdapter.SelectCommand = myCommand
myAdapter.Fill(myDataSet, tableName)
Next
''''''''''''''''''''''''''''''''''''''
'''' Add relationships to dataset ''''
''''''''''''''''''''''''''''''''''''''
'First, get relationships names from database (as well as parent table and child table names)
Dim namesQuery As String = "SELECT DISTINCT szRelationship, szReferencedObject, szObject " & _
"FROM MSysRelationships"
Dim namesCommand As New System.Data.OleDb.OleDbCommand(namesQuery, connection)
Dim namesAdapter As New System.Data.OleDb.OleDbDataAdapter(namesCommand)
Dim namesDataTable As New DataTable
namesAdapter.Fill(namesDataTable)
'Now, get MSysRelationship from database
Dim relationsQuery As String = "SELECT * FROM MSysRelationships"
Dim command As New System.Data.OleDb.OleDbCommand(relationsQuery, connection)
Dim adapter As New System.Data.OleDb.OleDbDataAdapter(command)
Dim relationsDataTable As New DataTable
adapter.Fill(relationsDataTable)
Dim relationsView As DataView = relationsDataTable.DefaultView
Dim relationName As String
Dim parentTableName As String
Dim childTablename As String
Dim row As DataRow
For Each relation As DataRow In namesDataTable.Rows
relationName = relation("szRelationship")
parentTableName = relation("szReferencedObject")
childTablename = relation("szObject")
'Keep only the record of the current relationship
relationsView.RowFilter = "szRelationship = '" & relationName & "'"
'Declare two arrays for parent and child columns arguments
Dim parentColumns(relationsView.Count - 1) As DataColumn
Dim childColumns(relationsView.Count - 1) As DataColumn
For i As Integer = 0 To relationsView.Count - 1
parentColumns(i) = myDataSet.Tables(parentTableName). _
Columns(relationsView.Item(i)("szReferencedColumn"))
childColumns(i) = myDataSet.Tables(childTablename). _
Columns(relationsView.Item(i)("szColumn"))
Next
Dim newRelation As New DataRelation(relationName, parentColumns, childColumns, False)
myDataSet.Relations.Add(newRelation)
Next
If isExportSchema Then
Dim schemaName = GetXmlSchemaFileName()
If File.Exists(schemaName) Then File.SetAttributes(schemaName, FileAttributes.Normal)
myDataSet.WriteXmlSchema(schemaName)
End If
Return myDataSet
End Function
You should just call the OleDbDataAdapter.Fill method with different SelectCommands and pass the same DataSet but different table names inside. In this case, your dataSet will contain different filled tables.

Resources