Im new to ado.net in c#. I need to add a couple of Id's(primary keys) that will be placed in one table.These primary keys have already a value from other tables so i nedd to grab them and fill them in. The the next columns will be filled in by user => firstname,lastname,dateOfBirth,securitynumber. And i need to add the id keywords also. i have no clue how to start with it. I just know how to do an insert. So i have to get the addressId and #vehicleid,#fuelcardid from somwhere but i dont get it how?
string query = "INSERT INTO [Driver] (firstName,lastName,dateOfBirth,addressId,securityNumber,vehicleid,fuelcardid) Values (#firstName,#lastName,#dateOfBirth,#addressId,#securityNumber,#vehicleid,#fuelcardid);SELECT CAST(scope_identity() AS int)";
int? newdriverID= null;
SqlConnection connection = getConnection();
using (SqlCommand command = new SqlCommand(query, connection)) {
SqlTransaction transaction = connection.BeginTransaction();
command.Transaction = transaction;
try {
SqlParameter parDriverFirstName = new SqlParameter();
parDriverFirstName.ParameterName = "#firstName";
parDriverFirstName.SqlDbType = System.Data.SqlDbType.NVarChar;
command.Parameters.Add(parDriverFirstName);
SqlParameter parDriverLastName = new SqlParameter();
parDriverLastName.ParameterName = "#lastName";
parDriverLastName.SqlDbType = System.Data.SqlDbType.NVarChar;
command.Parameters.Add(parDriverLastName);
SqlParameter parDriverDateOfBirth = new SqlParameter();
parDriverDateOfBirth.ParameterName = "#dateOfBirth";
parDriverDateOfBirth.SqlDbType = System.Data.SqlDbType.DateTime;
command.Parameters.Add(parDriverDateOfBirth);
SqlParameter parAddressId = new SqlParameter();
parAddressId.ParameterName = "#addressId";
parAddressId.SqlDbType = System.Data.SqlDbType.Int;
command.Parameters.Add(parAddressId);
SqlParameter parDriverSecurityNr = new SqlParameter();
parDriverSecurityNr.ParameterName = "#securityNumber";
parDriverSecurityNr.SqlDbType = System.Data.SqlDbType.NVarChar;
command.Parameters.Add(parDriverSecurityNr);
SqlParameter parvehicleId = new SqlParameter();
parvehicleId.ParameterName = "#vehicleid";
parvehicleId.SqlDbType = System.Data.SqlDbType.Int;
command.Parameters.Add(parvehicleId);
SqlParameter parFuelCardID = new SqlParameter();
parFuelCardID.ParameterName = "#fuelcardid";
parFuelCardID.SqlDbType = System.Data.SqlDbType.Int;
command.Parameters.Add(parFuelCardID);
command.Parameters["#firstName"].Value = driver.FirstName;
command.Parameters["#lastName"].Value = driver.LastName;
command.Parameters["#dateOfBirth"].Value = driver.DateOfBirth;
command.Parameters["#securityNumber"].Value = driver.SecurityNumber;
command.Parameters["#addressId"].Value = addressId;
command.Parameters["#vehicleid"].Value = vehicleid; //TODO test if this works
command.Parameters["#fuelcardid"].Value = fuelcardid;
connection.Open();
newdriverID = (int)command.ExecuteScalar();
transaction.Commit();
} catch (Exception ex) {
transaction.Rollback();
throw new Exception(ex.Message);
} finally {
connection.Close();
}
}
if(newdriverID != null) {
foreach (string licensetype in driver.DriversLicenceType) {
//if a driver has no license type this will simply not loop once
//inserts a driverid and typeid into the DriversLicenceType table that can be used elsewhere
if (Alldriverlicensetypes.ContainsValue(licensetype)) {
string insertLicenseQuery = "INSERT INTO [DriverLicenseType] (driverId,licenseTypeId) Values (#driverid,#licenseID)";
SqlConnection licenseconnection = getConnection();
using (SqlCommand command = new SqlCommand(insertLicenseQuery, licenseconnection)) {
SqlTransaction transaction = connection.BeginTransaction();
command.Transaction = transaction;
try {
SqlParameter pardriverId = new SqlParameter();
pardriverId.ParameterName = "#driverid";
pardriverId.SqlDbType = System.Data.SqlDbType.Int;
command.Parameters.Add(pardriverId);
command.Parameters["#driverid"].Value = newdriverID;
SqlParameter parlicenseID = new SqlParameter();
parlicenseID.ParameterName = "#licenseID";
parlicenseID.SqlDbType = System.Data.SqlDbType.Int;
command.Parameters.Add(parlicenseID);
int key = Alldriverlicensetypes.FirstOrDefault(x => x.Value == licensetype).Key;
command.Parameters["#driverid"].Value = key;
connection.Open();
command.ExecuteNonQuery();
transaction.Commit();
} catch (Exception ex) {
transaction.Rollback();
throw new Exception(ex.Message);
} finally {
connection.Close();
}
}
} else {
//trying to add a type that is not in the database => ASK what to do here?
}
}
}//if the previous insert failed, the id will be null so dont add anything
}
Related
Here in the code I'm trying to get all data from SQL Server and the method is used to list an users with their rolls in grid form. My question here is how to call/merge two stored procedures and return one result and am I in right way ? If not please explain it and show me the right way so I can learn it how to do it in future. Thanks.
public IEnumerable<ApplicationUser> GetAllUsers()
{
try
{
List<ApplicationUser> userList = new List<ApplicationUser>();
using (SqlConnection con = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand("sp_UsersReadAll", con);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlCommand cmd2 = new SqlCommand("sp_GetUserRolls", con);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
ApplicationUser apUser = new ApplicationUser();
apUser.Id = Convert.ToString(reader["Id"]);
apUser.UserName = reader["Username"].ToString();
apUser.FirstName = reader["FirstName"].ToString();
apUser.LastName = reader["LastName"].ToString();
apUser.Email = reader["Email"].ToString();
userList.Add(apUser);
}
con.Close();
}
return userList;
}
catch (Exception)
{
throw;
}
}
You can call two stored procedures for one shot and then use Data SqlDataReader.NextResult() to read another result set:
public IEnumerable<ApplicationUser> GetAllUsers()
{
try
{
List<ApplicationUser> userList = new List<ApplicationUser>();
using (SqlConnection con = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand(#"exec sp_UsersReadAll
exec sp_GetUserRolls", con);
cmd.CommandType = System.Data.CommandType.Text;
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
ApplicationUser apUser = new ApplicationUser();
apUser.Id = Convert.ToString(reader["Id"]);
apUser.UserName = reader["Username"].ToString();
apUser.FirstName = reader["FirstName"].ToString();
apUser.LastName = reader["LastName"].ToString();
apUser.Email = reader["Email"].ToString();
userList.Add(apUser);
}
reader.NextResult();
while (reader.Read())
{
ApplicationUserRoll apUserRoll = new ApplicationUserRoll();
apUserRoll.Id = Convert.ToString(reader["Id"]);
apUserRoll.UserId = reader["UserId"].ToString();
userList.Single(u => u.Id == apUserRoll.UserId).Rolls.Add(apUserRoll);
}
con.Close();
}
return userList;
}
catch (Exception)
{
throw;
}
}
Hope it helps.
Something like that should work (i'm considering you want unique id)
public IEnumerable<ApplicationUser> GetAllUsers()
{
try
{
ApplicationUser apUser;
List<ApplicationUser> userList = new List<ApplicationUser>();
using (SqlConnection con = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand("sp_UsersReadAll", con);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlCommand cmd2 = new SqlCommand("sp_GetUserRolls", con);
cmd2.CommandType = System.Data.CommandType.StoredProcedure;
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
apUser = new ApplicationUser();
apUser.Id = Convert.ToString(reader["Id"]);
apUser.UserName = reader["Username"].ToString();
apUser.FirstName = reader["FirstName"].ToString();
apUser.LastName = reader["LastName"].ToString();
apUser.Email = reader["Email"].ToString();
userList.Add(apUser);
}
// You can refactor this code in another method for don't have to write it both
reader = cmd2.ExecuteReader();
while (reader.Read())
{
apUser = new ApplicationUser();
apUser.Id = Convert.ToString(reader["Id"]);
// If id doesn't exists, we can continue and add the item
if(!userList.Exists(o=>o.Id==apUser.Id))
{
apUser.UserName = reader["Username"].ToString();
apUser.FirstName = reader["FirstName"].ToString();
apUser.LastName = reader["LastName"].ToString();
apUser.Email = reader["Email"].ToString();
userList.Add(apUser);
}
}
con.Close();
}
return userList;
}
catch (Exception)
{
// Actually it's like if you had not try / catch
throw;
}
}
I just show you the way, i didn't optimised the code.
There may be many approaches to do this task. For example -
You may create a new procedure which can merge the data for these two procedures and you would have to call one proc only from code.
Call one procedure and retain the list of users and pass user ids to seconds procedure to fetch corresponding roles.
Share output of procedures and attributes of ApplicationUser class if you are looking for more help.
So far I managed to use Insert command to create a new record inside a table called "Students". This is the code i used:
int ID = int.Parse( TextBox1.Text);
string name = TextBox2.Text;
string gender = TextBox3.Text;
int marks = int.Parse(TextBox4.Text);
string CS = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
using (SqlConnection con = new SqlConnection(CS))
{
//create data adapter
SqlDataAdapter adapter = new SqlDataAdapter("select * from students",con);
//create sqlcommand to store execute stored procedure
adapter.InsertCommand = new SqlCommand("spInsertStudent",con);
adapter.InsertCommand.CommandType = CommandType.StoredProcedure;
//create parameter for Return value (#ROWCOUNT)
SqlParameter parameter = adapter.InsertCommand.Parameters.Add("#ROWCOUNT",SqlDbType.Int);
parameter.Direction = ParameterDirection.ReturnValue;
adapter.InsertCommand.Parameters.Add("#ID", SqlDbType.Int, 0, "ID");
adapter.InsertCommand.Parameters.Add("#Name",SqlDbType.NVarChar,50,"Name");
adapter.InsertCommand.Parameters.Add("#Gender",SqlDbType.NVarChar,10,"Gender");
adapter.InsertCommand.Parameters.Add("#TotalMarks",SqlDbType.Int,0,"TotalMarks");
DataSet ds = new DataSet();
//DataTable students = new DataTable();
adapter.Fill(ds,"Students");
DataTable students = ds.Tables["Students"];
DataRow studentRow = students.NewRow();
studentRow["ID"] = ID;
studentRow["Name"] = name;
studentRow["Gender"] = gender;
studentRow["TotalMarks"] = marks;
students.Rows.Add(studentRow);
adapter.Update(ds,"Students");
Now I want to edit a data row. The data will be change if the ID is matched with the ID parameter. This is the stored procedure I'm using:
create procedure updateStudent
#ID int,
#Name varchar(50),
#Gender varchar(10),
#TotalMarks int
AS
BEGIN
update Students set Name = #Name, Gender = #Gender, TotalMarks = #TotalMarks
where ID = #ID
END
and this is the C# code i use in the code behind:
int ID = int.Parse(TextBox1.Text);
string name = TextBox2.Text;
string gender = TextBox3.Text;
int marks = int.Parse(TextBox4.Text);
string CS = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
using (SqlConnection con = new SqlConnection(CS))
{
SqlDataAdapter adapter = new SqlDataAdapter("Select * from Students",con);
DataTable dtStudents = new DataTable();
adapter.Fill(dtStudents);
SqlCommand cmd = new SqlCommand("updateStudent",con);
cmd.Parameters.Add("#ID", SqlDbType.Int, 0, "ID").Value = ID;
cmd.Parameters.Add("#Name", SqlDbType.NVarChar, 50, "Name").Value = name;
cmd.Parameters.Add("#Gender", SqlDbType.NVarChar, 10, "Gender").Value = gender;
cmd.Parameters.Add("#TotalMarks", SqlDbType.Int, 0, "TotalMarks").Value = marks;
adapter.UpdateCommand = cmd;
adapter.Update(dtStudents);
}
But after I clicked the Update button on my web form, there is no error message and the data didn't get updated in my database. What have I did wrong here?
I think you should write classes for executing stored procedures. It will be more easier to read and handle. RunQuery method in such a class like DB
private SqlConnection Connection;
public bool Open()
{
try
{
ConnectionString = "your connection string";
Connection = new SqlConnection(ConnectionString);
Connection.Open();
return true;
}
catch (Exception ex)
{
errorMessage = ex.Message;
return false;
}
}
public bool RunQuery(string ProcedureName, SqlParameter[] Parameters)
{
bool res = false;
try
{
SqlCommand Command = new SqlCommand();
Command.CommandText = ProcedureName;
Command.CommandType = CommandType.StoredProcedure;
Command.Connection = Connection;
Command.Parameters.AddRange(Parameters);
Command.ExecuteNonQuery();
res = true;
}
catch (Exception ex)
{
throw ex;
}
return res;
}
And you can call it
SqlParameter[] param= new SqlParameter[4];
param[0] = new SqlParameter("#ID", ID);
param[1] = new SqlParameter("#Name", name);
param[2] = new SqlParameter("#Gender", gender);
param[3] = new SqlParameter("#TotalMarks", marks);
RunQuery("updateStudent", param);
I'm working on a C# program that needs to use both an SQL Server Connection and a Local Data Base, I can easily retrieve data from both data bases with ExecuteReader(); which means the connection is being performed successfully.
But when I try to use ExecuteNonQuery(); It just throws a System.InvalidOperationException when dealing with the Local Data Base, with no additional info. It works fine when connecting to the SQL Server
Here's the function I'm having trouble with:
public String myFunction(String TLV, String SPName, String BD)
{
if (mdbEnabled.Checked == true)
{
string connectionString = string.Format("Provider={0}; Data Source={1}; Jet OLEDB:Engine Type={2}",
"Microsoft.Jet.OLEDB.4.0", BD, 5);
using (System.Data.OleDb.OleDbConnection conn = new System.Data.OleDb.OleDbConnection(connectionString))
{
try
{
conn.Open();
System.Data.OleDb.OleDbCommand SP = new System.Data.OleDb.OleDbCommand();
SP.Connection = conn;
SP.CommandType = System.Data.CommandType.StoredProcedure;
SP.CommandText = SPName;
System.Data.OleDb.OleDbParameter IN_ERC = new System.Data.OleDb.OleDbParameter();
IN_ERC.ParameterName = "#IN_ERC"; IN_ERC.DbType = System.Data.DbType.Int32; IN_ERC.Direction = System.Data.ParameterDirection.Output; IN_ERC.Value = 0;
System.Data.OleDb.OleDbParameter CH_ASM = new System.Data.OleDb.OleDbParameter();
CH_ASM.ParameterName = "#CH_ASM"; CH_ASM.DbType = System.Data.DbType.String; CH_ASM.Direction = System.Data.ParameterDirection.Output; CH_ASM.Value = 0; CH_ASM.Size = 1000;
System.Data.OleDb.OleDbParameter IN_ASM = new System.Data.OleDb.OleDbParameter();
IN_ASM.ParameterName = "#IN_ASM"; IN_ASM.DbType = System.Data.DbType.Int32; IN_ASM.Direction = System.Data.ParameterDirection.Output; IN_ASM.Value = 0;
System.Data.OleDb.OleDbParameter CH_DSM = new System.Data.OleDb.OleDbParameter();
CH_DSM.ParameterName = "#CH_DSM"; CH_DSM.DbType = System.Data.DbType.String; CH_DSM.Direction = System.Data.ParameterDirection.Input; CH_DSM.Value = TLV;
System.Data.OleDb.OleDbParameter IN_DSM = new System.Data.OleDb.OleDbParameter();
IN_DSM.ParameterName = "#IN_DSM"; IN_DSM.DbType = System.Data.DbType.Int32; IN_DSM.Direction = System.Data.ParameterDirection.Input; IN_DSM.Value = 0;
SP.Parameters.Add(IN_ERC);
SP.Parameters.Add(CH_ASM);
SP.Parameters.Add(IN_ASM);
SP.Parameters.Add(CH_DSM);
SP.Parameters.Add(IN_DSM);
try
{
SP.ExecuteNonQuery();//this always fails
}
catch
{
MessageBox.Show("error en SP.ExecuteNonQuery();");
}
conn.Close();
Console.WriteLine("IN_ERC: " + SP.Parameters["#IN_ERC"].Value);
Console.WriteLine("CH_ASM: " + SP.Parameters["#CH_ASM"].Value);
Console.WriteLine("IN_ASM: " + SP.Parameters["#IN_ASM"].Value);
return SP.Parameters["#CH_ASM"].Value.ToString();
}
catch (Exception err)
{
return null;
}
}
}
else
{
using (SqlConnection conn = new SqlConnection(BD))
{
try
{
conn.Open();
SqlCommand SP = new SqlCommand();
SP.Connection = conn;
SP.CommandType = System.Data.CommandType.StoredProcedure;
SP.CommandText = SPName;
SqlParameter IN_ERC = new SqlParameter();
IN_ERC.ParameterName = "#IN_ERC"; IN_ERC.SqlDbType = System.Data.SqlDbType.Int; IN_ERC.Direction = System.Data.ParameterDirection.Output; IN_ERC.Value = 0;
SqlParameter CH_ASM = new SqlParameter();
CH_ASM.ParameterName = "#CH_ASM"; CH_ASM.SqlDbType = System.Data.SqlDbType.NVarChar; CH_ASM.Direction = System.Data.ParameterDirection.Output; CH_ASM.Value = 0; CH_ASM.Size = 1000;
SqlParameter IN_ASM = new SqlParameter();
IN_ASM.ParameterName = "#IN_ASM"; IN_ASM.SqlDbType = System.Data.SqlDbType.Int; IN_ASM.Direction = System.Data.ParameterDirection.Output; IN_ASM.Value = 0;
SqlParameter CH_DSM = new SqlParameter();
CH_DSM.ParameterName = "#CH_DSM"; CH_DSM.SqlDbType = System.Data.SqlDbType.NVarChar; CH_DSM.Direction = System.Data.ParameterDirection.Input; CH_DSM.Value = TLV;
SqlParameter IN_DSM = new SqlParameter();
IN_DSM.ParameterName = "#IN_DSM"; IN_DSM.SqlDbType = System.Data.SqlDbType.Int; IN_DSM.Direction = System.Data.ParameterDirection.Input; IN_DSM.Value = 0;
SP.Parameters.Add(IN_ERC);
SP.Parameters.Add(CH_ASM);
SP.Parameters.Add(IN_ASM);
SP.Parameters.Add(CH_DSM);
SP.Parameters.Add(IN_DSM);
try
{
SP.ExecuteNonQuery();//this always works
}
catch
{
MessageBox.Show("error en SP.ExecuteNonQuery();");
}
conn.Close();
Console.WriteLine("IN_ERC: " + SP.Parameters["#IN_ERC"].Value);
Console.WriteLine("CH_ASM: " + SP.Parameters["#CH_ASM"].Value);
Console.WriteLine("IN_ASM: " + SP.Parameters["#IN_ASM"].Value);
return SP.Parameters["#CH_ASM"].Value.ToString();
}
catch (Exception err)
{
return null;
}
}
}
}
I call the function with the following parameters:
someString = myFunction(OPN_ASM, "OPN_ASM", BD);
the BD variable is set depending on the mdbEnabled.Checked property value, it could either be:
C:\Users\Angcrad\Documents\Visual Studio 2015\Projects\myDB.mdb
if mdbEnabled.Checked==true
or
Data Source=ANGCRAD\SQLEXPRESS;Initial Catalog=myDB;Integrated Security=True
if mdbEnabled.Checked==false
The "myDB.mdb" file was exported from the myDB Data Base on the SQL Server, so both Data Bases have the same elements. Hope you can help me tracking down the error, thanks in advance
I am trying to understand how Transactions work in c# using the TransactionScope object. I have an understanding about them in SQL server but I don't know how to verify this in c#. For example I want to check if I set the IsolationLevel to ReadUnCommitted, how can I verify this behavior in my code?
Currently this is my simple code, What I want to test is while my first Update command is executing and not committed/rolled back how can I verify that other transactions would be able to read the data it affects? Can anybody help me with a code example?
Here is my code:
public void TransferAmount(Account a)
{
bool debit = false;
bool credit= true;
var option = new TransactionOptions();
option.IsolationLevel = System.Transactions.IsolationLevel.ReadUnCommitted;
try
{
using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.Required, option))
{
using (IDbCommand cmd = Idbconnection.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "usp_Update_Debit";
IDataParameter param = cmd.CreateParameter();
param.ParameterName = "#mDebitAmount";
param.Value = a.Amount;
cmd.Parameters.Add(param);
Idbconnection.Open();
debit = cmd.ExecuteNonQuery() == 1;
}
using (IDbCommand cmd = Idbconnection.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "usp_Update_Credit";
IDataParameter param = cmd.CreateParameter();
param.ParameterName = "#mCreditAmount";
param.Value = a.Amount;
cmd.Parameters.Add(param);
credit = cmd.ExecuteNonQuery() == 1;
}
if (debit == credit)
transactionScope.Complete();
}
}
catch (Exception ex)
{
System.ServiceModel.Web.WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.OK;
throw new FaultException(new FaultReason(new FaultReasonText(ex.Message)));
}
}
I can't figure out why my second parameter (NotifyDateParameter) for my SqlCommand isn't working properly. It does not give an error, but it appears as null in my SQL Server database. The first parameter (StringParameter) appears just as intended. I could use some of your expertise right about now.
try
{
{
string connstr = #"Server=.\SQLEXPRESS;Database=ImageDB;Trusted_Connection=True;";
SqlConnection conn = new SqlConnection(connstr);
conn.Open();
string query;
byte[] fileData = null;
using (var binaryReader = new BinaryReader(Request.Files[upload].InputStream))
{
fileData = binaryReader.ReadBytes(Request.Files[upload].ContentLength);
}
query = "insert into Images(ImageData, NotifyDate) values(#ImageData, #NotifyDate)";
SqlParameter StringParameter = new SqlParameter();
StringParameter.SqlDbType = SqlDbType.VarBinary;
StringParameter.ParameterName = "ImageData";
StringParameter.Value = fileData;
DateTime today = DateTime.Now;
DateTime notifyDate = today.AddDays(1);
//string notifyDateString = notifyDate.ToString();
SqlParameter NotifyDateParameter = new SqlParameter();
NotifyDateParameter.SqlDbType = SqlDbType.DateTime;
NotifyDateParameter.ParameterName = "NotifyDate";
NotifyDateParameter.Value = notifyDate;
SqlCommand cmd = new SqlCommand(query, conn);
cmd.Parameters.Add(StringParameter);
cmd.Parameters.Add(NotifyDateParameter);
cmd.ExecuteNonQuery();
cmd.Dispose();
conn.Close();
conn.Dispose();
}
}
catch (Exception e)
{
string exceptionCause = String.Format("An error occurred: '{0}'", e);
System.IO.File.WriteAllText(#"C:\Users\Nathan\Documents\Visual Studio 2013\Projects\MVCImageUpload\uploads\exception.txt", exceptionCause);
}
Well for starters do try 2 things
Replace NotifyDateParameter.ParameterName = "NotifyDate"; with NotifyDateParameter.ParameterName = "#NotifyDate"; // #added to parameter name.
Check if parameter type is SqlDbType.DateTime or SqlDbType.Date