How use Transaction within an ASMX Web Service? - c#

i begin use Transaction in Web Service. i use C# and begin insert with Transaction.
But i don't insert to database.
Code WebService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Data.SqlClient;
using System.Data;
[WebService(Namespace = "example.org")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class WebService : System.Web.Services.WebService
{
SqlConnection conn;
SqlCommand comm1, comm2, comm3;
SqlTransaction trans;
SqlDataAdapter adapter1, adapter2;
DataSet ds1, ds2;
string constring = "Database=transaction;server=localhost;user=sa;password=toon2255";
[WebMethod(Description = "Transaction")]
public string transaction(int userid, int amount)
{
conn = new SqlConnection(constring);
conn.Open();
comm2 = new SqlCommand("INSERT INTO moneytrans VALUES('" + userid + "','" + amount + "')");
trans = conn.BeginTransaction();
comm2.Transaction = trans;
try
{
comm2.ExecuteNonQuery();
trans.Commit();
return "Transaction Complted. ";
}
catch (Exception)
{
trans.Rollback();
return "Transaction Failed..";
}
finally
{
conn.Close();
}
}
}
Code Default.aspx.cx (Website)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
protected void btnok_Click(object sender, EventArgs e)
{
WSLogin.WebService obj = new WSLogin.WebService();
lblmsg.Text = obj.transaction(Convert.ToInt32(txtuserid.Text), Convert.ToInt32(txtamount.Text));
}
But Result now "Transaction Failed.."
i want Result "Transaction Compelted" and insert to database complete.

The main problem with your code is that you're ignoring exceptions. Don't ever ignore exceptions. They will usually tell you what's wrong with your code.
Your code has several other problems, as I'll explain with the following corrected code:
[WebService(Namespace = "example.org")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class WebService : System.Web.Services.WebService
{
// 1
const string constring = "Database=transaction;server=localhost;user=sa;password=toon2255";
[WebMethod(Description = "Transaction")]
public string transaction(int userid, int amount)
{
// 2
using (SqlConnection conn = new SqlConnection(constring))
{
conn.Open();
// 3
using (SqlCommand comm2 = new SqlCommand("INSERT INTO moneytrans VALUES(#userid,#amount)"))
{
comm2.Parameters.AddWithValue("#userid", userid);
comm2.Parameters.AddWithValue("#amount", amount);
// 4
using (SqlTransaction trans = conn.BeginTransaction())
{
comm2.Transaction = trans;
try
{
comm2.ExecuteNonQuery();
trans.Commit();
return "Transaction Completed. ";
}
// 5
catch (Exception ex)
{
trans.Rollback();
// 6
return string.Format("Transaction Failed: {0}", ex);
}
// 7
//finally Not needed because of using block
//{
// conn.Close();
//}
}
}
}
}
}
It is usually best to declare variables near their point of use. As none of these variables were used except in the web method, I moved them all inside. I left the string constant outside.
The SqlConnection, SqlCommand and SqlTransaction all need to be in using blocks, to make certain that any resources they use will be cleaned up with the block is finished, whether or not an exception is thrown. This is true for classes which implement the IDisposable interface, when you create them, use them, and finish using them all in the same span of code.
Another using block, but more importantly, I have used parameters as a best practice. You should not build SQL queries by string concatenation, as it allows your callers (or your users) to dictate the text of the query you will be executing. This prevents "SQL Injection Attacks".
Another using block. The SqlTransaction is created by the BeginTransaction method.
This is the worst problem with your code. Don't ever ignore exceptions. At the very least, be certain to log the exceptions somewhere where you can read them later.
For this example, I followed your practice of returning a string, but I added the full exception to the end of the string. Not pretty, but all the information will be there.
Because conn is in a using block, the explicit finally is not required. A using block is equivalent to a try/catch/finally.

Related

how to solve exception for the connection string(local database c#)

ok so the first problem is the connection string itself it has this exception that i do not understand so i tried to put it in a try catch syntax but as i inserted it in the public partial class Form1 : Form the parenthesis are acting up so i inserted it in a function and now the fuction has this error:
Severity Code Description Project File Line Suppression State
Error CS0161 'Form1.connection()': not all code paths return a value Restaurant Management System C:\Users\admin\source\repos\Restaurant Management System\Restaurant Management System\Form1.cs 36 Active
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace Restaurant_Management_System
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
panel1.BackColor = Color.FromArgb(50, Color.Black);
label1.BackColor = Color.FromArgb(30, Color.Beige);
label2.BackColor = Color.FromArgb(0, Color.Black);
Password.BackColor = Color.FromArgb(0, Color.Black);
}
SqlCommand cmd;
SqlDataReader dr;
public SqlConnection connection()
{
try
{
SqlConnection con = new SqlConnection("Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename= \"|Data Directory|\\Coffee(LoginEmployee).mdf\";Integrated Security=True;");
}
catch (Exception ex)
{
MessageBox.Show("Error message: COULD NOT CONNECT STRING: " + ex);
}
}
private string getUsername()
{
SqlConnection con = connection();
cmd = new SqlCommand("SELECT nalue FROM EmployeeLog where Property=Username", con);
dr = cmd.ExecuteReader();
dr.Read();
return dr[0].ToString();
}
private string getPassword()
{
SqlConnection con = connection();
cmd = new SqlCommand("SELECT nalue FROM EmployeeLog where Property=Password", con);
dr = cmd.ExecuteReader();
dr.Read();
return dr[0].ToString();
}
What do i need to replace? why does it not all return a value? if i use the void case it will also have this error that i cannot explicitly convert it to sqlconnection. this is made in the latest visual studio 2017
If you catch the exception, no SqlConnection will be returned. So you could return null after showing the message box.
Then of course, you will need to do a null check after calling connection() so you don't get a null reference exception trying to use it.
You also need to return the connection you are creating:
return new SqlConnection("Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=|Data Directory|Coffee(LoginEmployee).mdf;Integrated Security=True;");
Note: I don't recommend hard-coding your connection string either! You would normally add the connection string to your app.config/web.config and read it using ConfigurationManager.ConnectionStrings... - this is because you might have different instance names on different machines, or you might want to point to a database on a server rather than local. You will not need to change the code and recompile just to make it work on more than one machine.
There is information on microsoft's class library site (https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnectionstringbuilder.attachdbfilename(v=vs.110).aspx) saying: An error will be generated if a log file exists in the same directory as the data file and the 'database' keyword is used when attaching the primary data file. In this case, remove the log file. Once the database is attached, a new log file will be automatically generated based on the physical path.

Adding Data to Database but get a breakpoint everytime a function is called

I am trying to write myself a Music record database program.
It works perfectly untill I try using a form to add data using input from textboxes and a button.
It generates a break point and the following error
An Unhandled exception of type 'System.ArgumentException' Occured in
System.Data.dll
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace Musicrecord
{
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
--> using(var connection = new SqlConnection("connectionString"))**
{
connection.Open();
var sql = "INSERT INTO Table(Artist, Album, Release Year) VALUES(#Artist, #Album, #Release year)";
using(var cmd = new SqlCommand(sql, connection))
{
cmd.Parameters.AddWithValue("#Artist", textBox1.Text);
cmd.Parameters.AddWithValue("#Album", textBox2.Text);
cmd.Parameters.AddWithValue("#Release Year ", textBox3.Text);
cmd.ExecuteNonQuery();
}
I haven't found after several hours of googling a solution.
If connectionString is a local variable, you need to use it as;
using(var connection = new SqlConnection(connectionString))
not
using(var connection = new SqlConnection("connectionString"))
If you use it as "connectionString", SqlConnection expects it is a valid connection string. But it is not.
Also, if your column name more than one word, you need to use it with square brackets like [Release Year]. It is the same as it's paramter name.
And don't use AddWithValue. It may generate unexpected results. Use .Add() method or it's overloads.
using(var connection = new SqlConnection(connectionString))
using(var cmd = connection.CreateCommand())
{
cmd.CommandText = "INSERT INTO Table(Artist, Album, [Release Year]) VALUES(#Artist, #Album, #ReleaseYear)";
cmd.Parameters.Add(#Artist, SqlDbType.NVarChar).Value = textBox1.Text;
cmd.Parameters.Add(#Album, SqlDbType.NVarChar).Value = textBox2.Text;
cmd.Parameters.Add(#ReleaseYear, SqlDbType.NVarChar).Value = textBox3.Text;
connection.Open();
cmd.ExecuteNonQuery();
}
I assumed your all data types are NVarChar. Also it is a good practice to specify size value as a third parameter in .Add() method.

mysql datareader not finding rows c#

I got a question about c# and mysql. I would like to make a very simpel login form that is connected to my local db. I got the connection to work (tested it) but i have a problem with reading my data that is returned from a select.
I'm trying to put an ID into a string so I can display it(this is just for testing). Now I have searched a lot on google and almost everyone has something like this. When I execute it doesn't give error but my sqldatareader finds nothing. In the first if I ask if it has got any rows and there are none.
What am I doing wrong? My username/password do exist in my db.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MySql.Data.MySqlClient;
namespace eindwerk
{
public partial class LoginForm : Form
{
string myConnection = "Server=localhost;Database=mydb;Uid=root;Pwd=root;";
MySqlCommand cmd;
MySqlConnection connection;
public LoginForm()
{
InitializeComponent();
connection = new MySqlConnection(myConnection);
connection.Open();
}
private void loginForm_Load(object sender, EventArgs e)
{
this.Location = new Point((Screen.PrimaryScreen.WorkingArea.Width - this.Width) / 2,
(Screen.PrimaryScreen.WorkingArea.Height - this.Height) / 2);
}
private void btnLogin_Click(object sender, EventArgs e)
{
try
{
cmd = connection.CreateCommand();
cmd.CommandText = "SELECT idlogin FROM login WHERE (username='#username') AND (password='#password') LIMIT 1;";
cmd.Parameters.AddWithValue("#username", txtbxLoginUsername.Text);
cmd.Parameters.AddWithValue("#password", txtbxLoginPassword.Text);
MySqlDataReader rdr = cmd.ExecuteReader();
rdr.Read();
if (rdr.HasRows)
{
while (rdr.Read())
{
label1.Text = rdr.GetInt32("idlogin").ToString();
}
}
else
{
lblLoginError.Visible = true;
}
rdr.Close();
}
catch {
lblLoginError.Text = "Nope";
lblLoginError.Visible = true;
}
}
}
}
You are calling Read() Multiple time. Call the While(Reader.Read()) single time and check the result by if(rdr.HasRows()){} for check result is return or nothing is come in the response.
You are returning only 1 row, but you are calling Read() twice. Your row is effectively discarded before you look at your data.
After a long search i have found the problem ! In my sql query i put username='#username', there lies the problem. You can't use single quotes !!!. I removed the quotes and it works perfectly.
That is whay you get for trusthing a search result on the third page of google...
Thanks to all !

Doesnt execute my MySql Query

i have a little problem with my C# code(im normally a c++ dev so i just know most of the basics of c#)
I wanted to write a class to execute a SQL query using that programm but atm it does nothing and i donĀ“t get any error from it.
The MySqlConnectionHandler Class which i wrote:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MySql.Data.MySqlClient;
using System.Windows.Forms;
namespace WS_Studio_tool
{
class MySqlConnectionHandler
{
private MySqlConnection connection;
private string ConnectionString;
public MySqlConnectionHandler()
{
try
{
ConnectionString = "SERVER=localhost;" +
"DATABASE=ws_creator_beta;" +
"UID=root;" +
"PASSWORD=AF362GL!";
connection = new MySqlConnection(ConnectionString);
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message, "MySql Fehler!");
}
}
public bool InsertRow(string SQL_Query)
{
try
{
MySqlCommand command = connection.CreateCommand();
command.CommandText = SQL_Query;
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message, "MySql Fehler!");
}
return true;
}
}
}
My Function Call(I played a lot with it so it could contain things that are not necessary):
string newquery = QueryTextBox1.ToString();
MySqlConnectionHandler SqlHandler = new MySqlConnectionHandler();
SqlHandler.InsertRow(newquery);
And my MySql Query:
INSERT INTO user_data (username,passwd) VALUES ('asdf', 'asdf');
It would be very nice if somebody could take a quick look at it, maybe you are able to find the error..
You're not telling the command to execute: also, you need to explicitly open the connection before using it, so add these lines to InsertRow:
connection.Open();
command.ExecuteNonQuery();
I'd also suggest disposing of the connection once you're done with it - either by implementing IDisposable on the MySqlConnectionHandler class, or - easier - just create a connection within a using block when executing the query:
using (var connection = new new MySqlConnection(ConnectionString))
{
using (var command = connection.CreateCommand())
{
command.CommandText = SQL_Query;
connection.Open();
command.ExecuteNonQuery();
}
}
You did not call command.Execute, so your SQL never gets executed.

Trying to update multiple rows in a gridview, keep getting the error 'The ConnectionString property has not been initialized.'

I've seen this question asked a lot but the answers I've found seem out of date for my version of VWD because it calls them 'obsolete'. I am just in school and I am very new to this. I am trying to update a value for every line in a gridview that is checked. The first checked value always gets updated but the second, third, etc. never work because the connectionstring property has not been initialized. These are the namespaces I have used:
using System;
using System.Data;
using System.Data.Sql;
using System.Data.SqlTypes;
using System.Data.SqlClient;
using System.Configuration;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
This is the code that makes me run into problems (it is inside of a button click method). The error seems to come the second time it runs through the 'try' statement and tries to open the connection:
string NewASNConnStr = ConfigurationManager.ConnectionStrings["Order"].ConnectionString;
SqlConnection ShipConnection = new
SqlConnection(ConfigurationManager.ConnectionStrings["Order"].ToString());
string insertSQL = "INSERT INTO [TRUCKS] ([DateSent]) VALUES (#DateSent)";
SqlCommand InsertCommand = new SqlCommand(insertSQL, ShipConnection);
InsertCommand.Parameters.Add("#DateSent", SqlDbType.Date).Value = DateTime.Now;
Int32 ASNNumber = GetASN();
foreach (GridViewRow grvRows in grvShipPallets.Rows)
{
if (((CheckBox)grvRows.FindControl("chkShip")).Checked)
{
string RFID = Convert.ToString(grvRows.Cells[1].Text);
SqlCommand UpdateCommand = new SqlCommand("UPDATE PALLETS SET TRUCKS$ASNNumber=#ASNNumber WHERE RFID=#RFID", ShipConnection);
UpdateCommand.Parameters.Add("#ASNNumber", System.Data.SqlDbType.Int).Value = ASNNumber;
UpdateCommand.Parameters.Add("#RFID", System.Data.SqlDbType.VarChar).Value= RFID;
ShipConnection.Open();
InsertCommand.ExecuteNonQuery();
ShipConnection.Close();
int InsertChecker = -2;
try
{
ShipConnection.Open();
InsertChecker = UpdateCommand.ExecuteNonQuery();
lblASNConfirmation.Text = "You have shipped the selected Order(s) on ASN # " + ASNNumber;
}
catch (Exception MyError)
{
lblError.Visible = true;
lblError.Text = "There has been an error with the database. <br/>";
lblError.Text += MyError.Message.ToString();
}
finally
{
ShipConnection.Dispose();
ShipConnection.Close();
}
}
}
grvShipPallets.DataBind();
}
Try
string NewASNConnStr = ConfigurationManager.ConnectionStrings["Order"].ConnectionString;
and
SqlConnection ShipConnection =
new SqlConnection(ConfigurationManager.ConnectionStrings["Order"].ConnectionString);
instead of
string NewASNConnStr = ConfigurationManager.ConnectionStrings["Order"].ToString();
and
SqlConnection ShipConnection =
new SqlConnection(ConfigurationManager.ConnectionStrings["Order"].ToString());
It's because your disposing the object in your finally statement. So in subsequent loops your connection no longer exists as an object. Remove the dispose line. Closing the connection is sufficient. Don't dispose of it until you no longer need it.

Categories