Why can't I consume my webservice more than once? - asp.net

When I consuming a webservice (asmx) the first time and return a DataTable to my aspx project, everything is ok. However, if I consume the webservice again on that same aspx the previous DataTable object is completely empty. Why is that?
This is my webservice method:
<WebMethod()> _
public Function QueryGeneralText() As DataTable
ds.Reset()
com.Parameters.Clear()
com.CommandText = queryString
com.CommandType = select booksID from Books"
com.Connection = con
conectarBD()
da = New SqlDataAdapter(com)
da.Fill(ds)
con.Close()
Return ds.Tables(0)
End Function
On the aspx.vb section:
Public Sub CreateDatatable()
Dim example1 As DataTable = ws.QueryGeneralText() ' RETURNS DATA
Dim example2 As DataTable = ws.QueryGeneralText() ' RETURNS DATA, BUT EXAMPLE ITS EMPTY
End Sub

It looks like you are using a global ds object - so you function is working on the same resultset.
First time you execute the function it works, nobody else has any results in ds, but next time you already have results there but now your reset drops the results.
If this is true, you might fix it by creating the ds inside the function instead if possible.

Related

How to call gridview from a shared function

I have a routine that i call clientside using Javascript. For this reason, it has to be a webmethod hence it must be 'shared' (static in C#)
<System.Web.Services.WebMethod()> _
Public Shared Sub LoadBewerkIndirecteKosten(_team As String, _year As Integer)
Try
' dconnection = DatabaseConnection.Instance
Dim con As New Connection
Dim sql As String = ""
sql = String.Format(" exec CSSSR_FEZ_Get_BewerkIndirecteKosten '{0}', {1} ", _team, _year)
Dim dt As DataTable ' = New DataTable
Dim ds As DataSet = con.QueryUnsecure(sql, Nothing, EDLQueryOptions.DataSet)
dt = ds.Tables(0)
SSR_IndirecteKosten.gvBewerkIndirecteKosten.DataSource = dt
gvBewerkIndirecteKosten.DataBind()
Catch ex As Exception
log.Fatal(String.Format("Error in: {0}: {1}", "LoadBewerkIndirecteKosten", ex.Message))
End Try
End Sub
In the javascript (which is in my aspx), i call this function like this:
PageMethods.LoadBewerkIndirecteKosten('FEZ', 2014, OnSucceeded, OnFailed);
Normally this construction works perfectly, as long is a don't call sreen components, but in this case, i run a stored procedure, fill a datatable and want to databind it to the gridview.
Does anyone know how?? Thanks in advance!!

How can I call bind method of grid through webmethod

This is my method to bind in code behind,I want to call it through web method
Private Sub BindData()
Dim objtable As New DataTable("projectinfoclass")
Dim Conn As SqlConnection = New SqlConnection(ConfigurationManager.ConnectionStrings("conString").ConnectionString)
Dim Cmd As SqlDataAdapter = New SqlDataAdapter("select * from ProjectInfoNew", Conn)
Cmd.Fill(objtable)
projectinfolist.Clear()
For Each dr As DataRow In objtable.Rows
projectinfolist.Add(New Projectinfoclass With {
.ProjectNumber = dr("ProjectNumber").ToString(),
.projectId = dr("Projectid").ToString(),
.Projectname = dr("ProjectName").ToString(),
.projectmodifiedDate = dr("ProjectmodifiedDate").ToString(),
.Recordupdateddate = dr("Recordupdateddate").ToString(),
.ProjectLocation = dr("ProjectLocation").ToString(),
.LocationServerName = dr("LocationServerName").ToString(), .ProjectModifiedBy = dr("ProjectModifiedBy").ToString(),
.DBServer = dr("DBServer").ToString(),
.DBName = dr("DBName").ToString(),
.Flag = Nothing})
Next
GridView1.DataSource = objtable
GridView1.DataBind()
End Sub
put your GridView in a usercontrol and follow the solutions here:
How do I get the HTML output of a UserControl in .NET (C#)?
1) Keep the data source and bind bits in the page code behind, move the rest into a web method. The web method can be called in the code behind and you use the result.
or
2) move code into web method as above but use as an object data source in the aspx and that removes all the code behind wiring up.
I hope that's what you're after.

.NET Framework Data Provider for Oracle multiple open connection

I have the below mentioned code in a seperate class file for establishing connection and carry out DB transactions. I have an issue where multiple connections being opened which sometime exceed the connection pool. When I stepped through the code I found that there are codes which call ConnectDB() in a loop without calling DisconnectDB(). But I expected that the condition OraConn.State = ConnectionState.Closed should handle the situation. Somehow the condition is always satisfied hence openning another set of connection. Can you suggest where am I going wrong and also what best practice can be adopted here?
Public Class Connection
Dim Str_conn As String = "Data Source=...; User=...; password=...; Min Pool Size=10; Max Pool Size=500;"
Public OraConn As OracleConnection
Dim cmd As OracleCommand
Dim dr As OracleDataReader
Dim data_adapt As OracleDataAdapter
Dim dt As DataTable
Dim ds As DataSet
Public Sub ConnectDB()
OraConn = New OracleConnection(Str_conn)
If OraConn.State = ConnectionState.Closed Then
OraConn.Open()
End If
End Sub
Public Sub DisconnectDB()
If OraConn.State = ConnectionState.Open Then
OraConn.Close()
End If
End Sub
Public Function get_dataset(ByVal query As String, ByRef ds As DataSet) As DataSet
data_adapt = New OracleDataAdapter(query, OraConn)
data_adapt.Fill(ds)
Return ds
End Function
Public Function get_datareader(ByVal query As String) As OracleDataReader
cmd = New OracleCommand(query, OraConn)
dr = cmd.ExecuteReader()
Return dr
End Function
Public Sub UpdateDB(ByVal query As String)
cmd = New OracleCommand(query, OraConn)
cmd.ExecuteNonQuery()
cmd.Dispose()
End Sub
The class is refered in other classes or directly in the aspx.vb pages like this.
Public Function InsertData(ByVal var1 As String, ByVal var2 As String) As Integer
conn.ConnectDB()
Dim qryInsert As String
qryInsert = " INSERT INTO TABLE VALUES ('" & var1 & "', "
qryInsert = qryInsert & var2 & "')"
Try
conn.UpdateDB(qryInsert)
Catch ex As OracleException
If ex.Code = 1 Then
updData(var1, var2)
ElseIf ex.Code = 2091 Then
msgprompt("Duplicate Unique Key!", "Warning")
End If
Finally
conn.DisconnectDB()
End Try
Return count
End Function
The connection is again opened in function updData(). While I understand that it has to be closed correctly but keeping tab on every developer is not possible. Hence I want to control it directly from the connection class by using the same connection but the condition If OraConn.State = ConnectionState.Closed is not helping.
UPDATE
I have put the code in UpdateDB under a Using block and removed call to ConnectDB and DisconnectDB from function like InsertData(...). It seems that the issue has been resolved. But I would like to know in case of exception will the connection remain open? and also OraConn is a public variable defined outside Using block so will it be disposed of by the GC?
Public Sub UpdateDB(ByVal query As String)
Using OraConn = New OracleConnection(Str_conn)
cmd = New OracleCommand(query, OraConn)
Try
OraConn.Open()
cmd.ExecuteNonQuery()
Catch ex As Exception
Throw
Finally
cmd.Dispose()
End Try
End Using
End Sub
You must close all the connections as soon as you are done with it, no matter what.
Suggestion:
The best practice for closing the connection is to do it in finally block. So that even if there is any error, catch it (log it if required) in catch block, and then connection will get close in finally block.
UPDATE
You can put one private static counter in your Connection class. When ever ConnectDB() is called you increment this counter and decrement it in every DisconnectDB(). Now in ConnectDB() you check the value of counter, if it exceeds a minimum threshold you throw error, by doing this way; you can come to know idle connection present in your code and refactor it. On production keep this threshold value high or ignore it in code.

Accessing data from sqldatereader within a function

I want to output some data to the user based on their username. This data is held in a table that is linked to the aspnet_Users table. I'm trying to write a sqldatareader as part of a function so I don't have to rewrite the code when it could be called from several pages. I know this is probably very simple buty I can't seem to access the data from outside the function. The function I have so far is as follows:
Public Shared Function AgencyDetails() As SqlDataReader
Dim details As String = "SELECT * FROM tbl_Relationships WHERE ContactSub = #Username"
Dim connString As String = ConfigurationManager.ConnectionStrings("ApplicationServices").ConnectionString
Using dbConnection As New SqlConnection(connString)
dbConnection.Open()
Dim cmdAgency As New SqlCommand(details, dbConnection)
cmdAgency.Parameters.AddWithValue("#Username", membership.getuser)
Return cmdAgency.ExecuteReader()
End Using
End Function
How can I call this function and access the information on my page? Something like the following?
lblAgencyDetails.text = AgencyDetails(0)
Thanks
The way you have it now, it won't work because you enclosed the connection in a using statement, by the time you return the Reader the connection will be closed and disposed so the reader won't be able to read anything.
What you should do in that function is load the info in a DataTable and return the datatable.
Example:
Public Shared Function AgencyDetails() As DataTable
Dim details As String = "SELECT * FROM tbl_Relationships WHERE ContactSub = #Username"
Dim connString As String = ConfigurationManager.ConnectionStrings("ApplicationServices").ConnectionString
Using dbConnection As New SqlConnection(connString)
dbConnection.Open()
Dim cmdAgency As New SqlCommand(details, dbConnection)
cmdAgency.Parameters.AddWithValue("#Username", membership.getuser)
Dim dt as new DataTable()
dt.Load(cmdAgency.ExecuteReader())
return dt
End Using
End Function
You can access the rows in the data table by doing:
For Each row as DataRow in dt.Rows
Console.WriteLine(row("ColumnName"))
Next
To be able to retrieve the data from the DataReader object, you should call the Read() method:
While reader.Read()
Console.WriteLine(String.Format("{0}, {1}", _
reader(0), reader(1)))
End While
This method moves the SqlDataReader to the next record.

How to add Transactions with a DataSet created using the Add Connection Wizard?

I have a DataSet that I have added to my project where I can Insert and Add records using the Add Query function in Visual Studio 2010, however I want to add transactions to this, I have found a few examples but cannot seem to find one that works with these.
I know I need to use the SQLClient.SQLTransaction Class somehow. I used the Add New Data Source Wizard and added the Tables/View/Functions I need, I just need an example using this process such as How to get the DataConnection my DataSet has used. Assuming all options have been set in the wizard and I am only using the pre-defined adapters and options asked for in this wizard, how to I add the Transaction logic to my Database.
For example I have a DataSet called ProductDataSet with the XSD created for this, I have then added my Stock table as a Datasource and Added an AddStock method with a wizard, this also if a new item calls an AddItem method, if either of these fails I want to rollback the AddItem and AddStock in this case.
In this example, I have a dataset called "dsMain" and a few direct queries in a "QueriesTableAdapter". I extend the partial class for the TableAdapter with a function that will create a transaction based on the first (0) connection and then apply it to every connection in the table adapter.
Namespace dsMainTableAdapters
Partial Public Class QueriesTableAdapter
Public Function CreateTransaction() As Data.IDbTransaction
Dim oConnection = Me.CommandCollection(0).Connection
oConnection.Open()
Dim oTrans = oConnection.BeginTransaction()
For Each cmd In Me.CommandCollection
cmd.Connection = oConnection
cmd.Transaction = oTrans
Next
Return oTrans
End Function
End Class
End Namespace
You begin the transaction by calling the new function
Dim qa As New dsMainTableAdapters.QueriesTableAdapter
Dim oTrans = qa.CreateTransaction()
Then you can call TableAdapter queries within your transaction
qa.Query1
qa.Query2
When you are done with your queries you commit the transaction
oTrans.Commit()
You can do the same thing for any TableAdapter that was created for your datasets.
If you have multiple TableAdapters that need to use the same transaction, then in addition to a "CreateTransaction" you should make a "SetTransaction" and have the Transaction be a parameter.
first of all thanks for your answer carter, it helped me very much!
but iam not able to handle the part with the parameters
You can do the same thing for any TableAdapter that was created for your datasets. If you have multiple TableAdapters that need to use the same transaction, then in addition to a "CreateTransaction" you should make a "SetTransaction" and have the Transaction be a parameter.
so iam able to handle 1 transactions with 1 tableadapter, but not 1 transaction with 2 tableadapters:
iam doing this for a school project, and i really need your help!!
here is the code to add a new material and a historical price to it(a changing price, like by fuel; iam saving it in an related table to material in the database):
Namespace DataSetTableAdapters
Partial Public Class MaterialPriceTableAdapter
Public Function SetTransaction() As Data.IDbTransaction
Dim oConnection = Me.CommandCollection(0).Connection
oConnection.Open()
Dim oTrans = oConnection.BeginTransaction()
For Each cmd In Me.CommandCollection
cmd.Connection = oConnection
cmd.Transaction = oTrans
Next
Return oTrans
End Function
End Class
Partial Public Class MaterialTableAdapter
Public Function CreateTransaction(ByVal MaterialPrice As System.Data.Odbc.OdbcTransaction) As Data.IDbTransaction
Dim oConnection = Me.CommandCollection(0).Connection
oConnection.Open()
Dim oTrans = oConnection.BeginTransaction()
For Each cmd In Me.CommandCollection
cmd.Connection = oConnection
cmd.Transaction = oTrans
Next
Return oTrans
End Function
End Namspace
`
and now the code in the form the form:
Public Class AddMaterial
Dim material As New DataSetBATableAdapters.MaterialTableAdapter
Dim materialprice As New DataSetBATableAdapters.MaterialPriceTableAdapter
Dim oTrans = material.CreateTransaction(materialprice.SetTransaction())
Private Sub Save_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Save.Click
Try
material.InsertQuery(NameTextBox.Text, UnitComboBox.SelectedValue)
materialprice.InsertQuery(Date_BeginDateTimePicker.Value, PriceTextBox.Text, Date_EndDateTimePicker.Value, Me.LkwTableAdapter.ScalarQuery())
oTrans.Commit()
Catch ex As Exception
oTrans.Rollback()
MsgBox("Error by Insert")
End Try
Me.Close
End Sub
End Class
if i save a new record the materialprice.insertquery isnt commited by otrans.commit. what am i doing wrong? if you have an idea what it is, please tell me
thanks,
Xeras
This is untested, but this is how I imaging the CreateTransaction/SetTransaction combo should be written (with your OdbcTransaction object).
Public Function CreateTransaction() As System.Data.Odbc.OdbcTransaction
Dim oConnection = Me.CommandCollection(0).Connection
oConnection.Open()
Dim oTrans = oConnection.BeginTransaction()
SetTransaction(oTrans)
Return oTrans
End Function
Public Sub SetTransaction(ByVal oTrans As System.Data.Odbc.OdbcTransaction)
For Each cmd In Me.CommandCollection
cmd.Connection = oTrans.Connection
cmd.Transaction = oTrans
Next
End Sub

Resources