C# Sql Data not saving - sql

I have a few tables in a c# application I'm currently working on and for 4/5 of the tables everything saves perfectly fine no issues. For the 5th table everything seems good until I reload the program again (without modifying the code or working with a seperate install so that the data doesn't go away) The 4/5 tables are fine but the 5th doesn't have any records in it after it has been restarted (but it did the last time it was running). Below is some code excerpts. I have tried a few different solutions online including creating a string to run the sql commands on the database manually and creating the row directly as opposed to the below implementation which uses a generic data row.
//From main window
private void newInvoice_Click(object sender, EventArgs e)
{
PosDatabaseDataSet.InvoicesRow newInvoice = posDatabaseDataSet1.Invoices.NewInvoicesRow();
Invoices iForm = new Invoices(newInvoice, posDatabaseDataSet1, true);
}
//Invoices Table save [Works] (from Invoices.cs)
private void saveInvoice_Click(object sender, EventArgs e)
{
iRecord.Date = Convert.ToDateTime(this.dateField.Text);
iRecord.InvoiceNo = Convert.ToInt32(this.invoiceNumField.Text);
iRecord.Subtotal = (float) Convert.ToDouble(this.subtotalField.Text);
iRecord.Tax1 = (float)Convert.ToDouble(this.hstField.Text);
iRecord.Total = (float)Convert.ToDouble(this.totalField.Text);
iRecord.BillTo = this.billToField.Text;
invoicesBindingSource.EndEdit();
if (newRecord)
{
dSet.Invoices.Rows.Add(iRecord);
invoicesTableAdapter.Adapter.Update(dSet.Invoices);
}
else
{
string connString = Properties.Settings.Default.PosDatabaseConnectionString;
string queryString = "UPDATE dbo.Invoices set ";
queryString += "Date='" + iRecord.Date+"'";
queryString += ", Subtotal=" + iRecord.Subtotal;
queryString += ", Tax1=" + iRecord.Tax1.ToString("N2");
queryString += ", Total=" + iRecord.Total;
queryString += " WHERE InvoiceNo=" + iRecord.InvoiceNo;
using (SqlConnection dbConn = new SqlConnection(connString))
{
SqlCommand command = new SqlCommand(queryString, dbConn);
dbConn.Open();
SqlDataReader r = command.ExecuteReader();
dbConn.Close();
}
}
dSet.Invoices.AcceptChanges();
}
//Invoice Items save [works until restart] (also from Invoices.cs)
private void addLine_Click(object sender, EventArgs e)
{
DataRow iRow = dSet.Tables["InvoiceItems"].NewRow();
iRow["Cost"] = (float)Convert.ToDouble(this.costField.Text);
iRow["Description"] = this.descriptionField.Text;
iRow["InvoiceNo"] = Convert.ToInt32(this.invoiceNumField.Text);
iRow["JobId"] = Convert.ToInt32(this.jobIdField.Text);
iRow["Qty"] = Convert.ToInt32(this.quantityField.Text);
iRow["SalesPerson"] = Convert.ToInt32(this.salesPersonField.Text);
iRow["SKU"] = Convert.ToInt32(this.skuField.Text);
dSet.Tables["InvoiceItems"].Rows.Add(iRow);
invoiceItemsTableAdapter.Adapter.Update(dSet,"InvoiceItems");
PosDatabaseDataSet.InvoiceItemsDataTable dTable = (PosDatabaseDataSet.InvoiceItemsDataTable)dSet.InvoiceItems.Copy();
DataRow[] d = dTable.Select("InvoiceNo=" + invNo.ToString());
invoiceItemsView.DataSource = d;
}
Thanks in advance for any insight.
UPDATE: October 17, 2011. I am still unable to get this working is there any more ideas out there?

you must execute your Sql Command in order to persis the changes you made.
using (SqlConnection dbConn = new SqlConnection(connString))
{
dbConn.Open();
SqlCommand command = new SqlCommand(queryString, dbConn);
command.ExecuteNonQuery();
dbConn.Close();
}
The ExecuteReader method is intended (as the name says) to read the data from a SQL table. You need to use a different method as you can see above.

We need some more info first, you haven't shown the case where your code fails.
Common mistakes on this kind of code is calling DataSet.AcceptChanges() before actually committing the changes to the database.
Second is a conflict between databound data through the binding source vs edits to the dataset directly.
Lets see the appropriate code and we can try and help.
Set a breakpoint after teh call to invoiceItemsTableAdapter and check the InvoiceItems table for the row you have added. Release the breakpoint and then close your app. Check the database again. I would say that another table may be forcibly overwriting the invoice item table.

Related

How to check whether table column of the binary type has a value?

The Download command is showing in front of all the rows, I want to show it to only those rows having PDF file attached in the database.
protected void gvupdationsummary_SelectedIndexChanged(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(st);
con.Open();
SqlCommand com = new SqlCommand("select [name],[data] from [Pragati].[dbo].[Pragati_Status_Updations] where Pragati_no=#Pragati_no", con);
com.Parameters.AddWithValue("Pragati_no", gvupdationsummary.SelectedRow.Cells[3].Text);
SqlDataReader dr = com.ExecuteReader();
if (dr.Read())
{
Response.Clear();
Response.Buffer = true;
//Response.ContentType = dr["type"].ToString();
Response.AddHeader("content-disposition", "attachment;filename=" + dr["name"].ToString());
Response.Charset = "";
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.BinaryWrite((byte[])dr["data"]);
Response.End();
}
else
{
// ...
}
}
The code that you show seems to do the actual PDF download already. There is nothing you can do there to prevent the showing of a download button or link.
Instead you need to change the SQL query that provides data for gvupdationsummary, and add a column such as HasPDF there, like this:
SELECT /* your columns */ ,
CAST(CASE WHEN [data] IS NULL THEN 0 ELSE 1 END AS BIT) AS HasPDF
FROM ....
WHERE ....
Then in your grid rendering code you can use the boolean value of HasPDF to decide if the Download button should be shown.
Using this approach you don't needlessly transfer all PDF binary data from your database to your application, every time the grid is being rendered.
You can use SQLDataReader's IsDBNull method to see whether the column contains non-existent or missing values.
ind idx = dr.GetOrdinal("data");
if (!dr.IsDBNull(idx))
{
// set download link on to response.
}
else
{
}

Store date and time in sql server 2012 using c#

i want to store date and time in SQL Server 2012 using asp.net but generate some error "Conversion failed when converting date and/or time from character string."
protected void btn Submit_Click(object sender, EventArgs e)
{
lbldate.Text = Convert.ToDateTime(this.txtdate.Text).ToString("dd/MM/yyyy");
lbltime.Text = Convert.ToDateTime(this.txttime.Text).ToLongTimeString();
TimeSpan time = new TimeSpan();
time.ToString();
SqlConnection con = new SqlConnection(#"Data Source=DESKTOP-O6SE533;Initial Catalog=Datertime;Integrated Security=True;Connect Timeout=15;Encrypt=False;TrustServerCertificate=False");
SqlCommand cmd = new SqlCommand("insert date,time into DateTimedemo values('" +txtdate.Text + "','"+txttime.Text+"')", con);
con.Open();
int r = cmd.ExecuteNonQuery();
if (r > 0)
{
Response.Write("success");
}
else
{
Response.Write("failed");
}
}
Use parameterized SQL instead of building the SQL dynamically. This avoids SQL injection attacks and string formatting differences, as well as making the code clearer.
Additionally, I believe both "date" and "time" are keywords in T-SQL, so you should put them in square brackets when using them as field names.
You should attempt to perform as few string conversions as possible. Without knowing exactly what your web page looks like it's hard to know exactly how you want to parse the text, but assuming that Convert.ToDateTime is working for you (sounds worryingly culture-dependent to me) you'd have code like this:
protected void btn Submit_Click(object sender, EventArgs e)
{
// TODO: Ideally use a date/time picker etc.
DateTime date = Convert.ToDateTime(txtdate.Text);
DateTime time = Convert.ToDateTime(txttime.Text);
// You'd probably want to get the connection string dynamically, or at least have
// it in a shared constant somewhere.
using (var con = new SqlConnection(connectionString))
{
string sql = "insert [date], [time] into DateTimeDemo values (#date, #time)";
using (var cmd = new SqlCommand(sql))
{
cmd.Parameters.Add("#date", SqlDbType.Date).Value = date;
cmd.Parameters.Add("#time", SqlDbType.Time).Value = time.TimeOfDay;
int rows = cmd.ExecuteNonQuery();
string message = rows > 0 ? "success" : "failed";
Response.Write(message);
}
}
}
I've guessed at what SQL types you're using. If these are meant to represent a combined date and time, you should at least consider using a single field of type DateTime2 instead of separate fields.

Partial replace on SQL image data column

This question is related to another one I posted earlier.
To recap, I need to fix an issue with an ancient legacy app where people messed up data storage by re-installing the software the wrong way.
The application stores data by saving a record in an SQL DB. Each record holds a reference to a file on disk of which the filename auto-increments.
By re-installing the app the filename auto-increment was re-set so the DB now holds multiple unrelated records which reference the same filename and I have to directories with files which I obviously cannot merge because of these identical filenames. The files hold no reference to the DB data so the only course of action that remains is to filter the DB records on date created and try to rename "EXED" to "IXED" or something like that.
The DB is relatively simple with one table containing a column that holds data of type "Image".
An example content of this image data is as follows:
0x3200001000000000000000200B0000000EFF00000300000031340000000070EC0100002C50000004000000C90000005D010000040000007955B63F4D01000004000000F879883E4F01000004000000BC95563E98010000040000009A99993F4A01000004000000000000004B01000004000000000000009101000004000000000000004E01000004000000721C83425101000004000000D841493F5E01000004000000898828414101000004000000F2D2BD3F4201000004000000FCA9B13F40010000040000007574204244010000040000000000204345010000040000007DD950414601000004000000000000004701000004000000000000009201000004000000000000008701000004000000D2DF13426A0100000400000000005C42740100000400000046B68F40500100000400000018E97A3F7901000004000000FB50CF3C7A01000004000000E645703F99010000040000000000E0404C010000040000008716593F8601000004000000000006439A0100000400000000008040700100000400000063D887449E01000004000000493CBA3E9C0100000400000069699D429B01000004000000DD60CA3F9D0100000400000035DE3C44B4010000040000008B5C744433000000040000003D0ABB4134000000040000000AFF7C44350000000400000093CB3942750400000400000054A69F41BA010000040000002635C64173040000040000008367C24100000080690100002B5000003101000032000010000000000000002009000000000000000100000000000000F00000000000000080080100000100000010000000540100000100000021F0AA42270000000200000010000000540100000200000021F0AA42280000000300000010000000540100000300000059C9E6432900000004000000100000005401000004000000637888442A00000005000000100000005401000005000000DFEF87442B00000006000000100000005401000006000000000000002C00000007000000100000005401000007000000000000002D00000008000000100000005401000008000000000000002D000000090000001000000054010000090000002F353D442D0000000A00000010000000540100000A00000035DE3C44340000000B00000010000000540100000B0000008B5C7444240000009D50000010000000CDCCCC3E2C513B41F65D5F3F2C51BB419E50000010000000CCBA2C3FE17C8C411553B13F83F32142000000403700000000FE0000090000004558454434386262002D50000008000000447973706E6F65008E5000000E00000056454C442052414D502033363000000000F000000000
The data is apparently Hex which mostly encodes meaningless crap but also holds the name of physical files (towards the end of the data field) in the filesystem that is linked to the SQL records:
??#7???????????EXED48bb?-P??????Dyspnoe??P??????VELD RAMP 360
I'm interested in the EXED part.
There is no clear regularity in the offset at which the filename appears and the filename is of variable length (so I do not know beforehand how long the substring will be).
I can call up all records with SQL like this:
SELECT COUNT(*) as "Number of EXED Files after critical date"
FROM [ZAN].[dbo].[zanu]
WHERE udata is not null
and SUBSTRING(udata, 1 , 2147483647) like '%EXED%'
and [udatum] > 0
and CONVERT(date,[udatum]) > CONVERT(date,'20100629')
What I would like to do now is know how to replace this EXED substring by something else (e.g. IXID).
I'm unfamiliar with SQL and Googling so far has yielded very little information on my options here.
I also have no other info on the original code that generated this data/the data format/encoding/whatever...
It's a mess really.
Any help is welcome!
An update on this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Threading;
namespace ZANLinq
{
class Program
{
static void Main(string[] args)
{
try
{
DataContext zanDB = new DataContext(#"Data Source=.\,1433;database=ZAN;Integrated Security=true");
string strSQL = #"SELECT
Idnr,
Udatum,
Uzeit,
Unr,
Uart,
Ubediener,
Uzugriff,
Ugr,
Uflags,
Usize,
Udata
FROM Zanu
WHERE (Udata IS NOT null and SubString(Udata, 1 , 2147483647) LIKE '%EXED%')
AND (Idnr = ' 2')";
var zanQuery = zanDB.ExecuteQuery<Zanu>(strSQL);
List<Zanu> list = zanQuery.ToList<Zanu>();
foreach (Zanu zanTofix in list)
{
string strOriginal = ASCIIEncoding.ASCII.GetString(zanTofix.Udata);
string strFixed = strOriginal.Replace("EXED", "IXED");
zanTofix.Udata = ASCIIEncoding.ASCII.GetBytes(strFixed);
}
zanDB.SubmitChanges();
//Console.WriteLine(zanResults.Count<Zanu>().ToString());
}
catch (SqlException e)
{
Console.WriteLine(e.Message);
}
}
}
}
It finds the records I'm interested in, I can easily manipulate the data but the commit doesnt work. I'm stumped, there are no exceptions, no indication the code is wrong.
Anybody have ideas?
UPDATE:
I think the above does not work because my table appears to have a composite PK (I cannot change this):
Since I could not debug this (no info anywhere, no exceptions, just a silent fail of the submitchanges()) I decided to use another approach and abandon Linq2SQL altogether:
try
{
SqlConnection thisConnection = new SqlConnection(#"Network Library=DBMSSOCN;Data Source=.\,1433;database=ZAN;Integrated Security=SSPI");
DataSet zanDataSet = new DataSet();
SqlDataAdapter zanDa;
SqlCommandBuilder zanCmdBuilder;
thisConnection.Open();
//Initialize the SqlDataAdapter object by specifying a Select command
//that retrieves data from the sample table.
zanDa = new SqlDataAdapter(#"SELECT
Idnr,
Udatum,
Uzeit,
Unr,
Uart,
Ubediener,
Uzugriff,
Ugr,
Uflags,
Usize,
Udata
FROM Zanu
WHERE (Udata IS NOT null and SubString(Udata, 1 , 2147483647) LIKE '%IXED%')
AND (Idnr = ' 2')
AND (Uzeit = '13:21')", thisConnection);
//Initialize the SqlCommandBuilder object to automatically generate and initialize
//the UpdateCommand, InsertCommand, and DeleteCommand properties of the SqlDataAdapter.
zanCmdBuilder = new SqlCommandBuilder(zanDa);
//Populate the DataSet by running the Fill method of the SqlDataAdapter.
zanDa.Fill(zanDataSet, "Zanu");
Console.WriteLine("Records that will be affected: " + zanDataSet.Tables["Zanu"].Rows.Count.ToString());
foreach (DataRow record in zanDataSet.Tables["Zanu"].Rows)
{
string strOriginal = ASCIIEncoding.ASCII.GetString((byte[])record["Udata"]);
string strFixed = strOriginal.Replace("IXED", "EXED");
record["Udata"] = ASCIIEncoding.ASCII.GetBytes(strFixed);
//string strPostMod = ASCIIEncoding.ASCII.GetString((byte[])record["Udata"]);
}
zanDa.Update(zanDataSet, "Zanu");
thisConnection.Close();
Console.ReadLine();
}
catch (SqlException e)
{
Console.WriteLine(e.Message);
}
This seems to work but any input on why the Linq does not work and whether or not my second solution is efficient/optimal or not is still very much appreciated.

UPDATE Query : Incorrect Syntax (Edited)

I have a button which saves the contents edited in datagridview in my UI design. Here is the code for that Button_Save:
public void btnUpdate_Click(object sender, EventArgs e)
{
foreach (DataGridViewRow row in dataGridView1.Rows)
{
System.Data.SqlClient.SqlConnection sqlConnection1 =
new System.Data.SqlClient.SqlConnection("server=Test; Integrated Security=true; Database=Test;");
System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand();
var sql = new StringBuilder();
sql.AppendLine("UPDATE dbo.JobStatus");
sql.AppendLine("Set ShipTrackingNumber = #ShipTrackingNumber");
sql.AppendLine(", ShipMethodTransmitted = #ShipMethodTransmitted");
sql.AppendLine(", DateShipTransmitProcessed = #DateShipTransmitProcessed");
sql.AppendLine(", ShipmentProcessedBy = #ShipmentProcessedBy");
sql.AppendLine(", Critical = #Critical");
sql.AppendLine(", ShipTransmitStatus = #ShipTransmitStatus");
sql.AppendLine("Where jobtableId = #jobTableId");
cmd.Connection = sqlConnection1;
cmd.CommandText = sql.ToString();
cmd.Parameters.AddWithValue("#TrackingNumber", row.Cells[7].FormattedValue);
cmd.Parameters.AddWithValue("#ShipMethodTransmitted", row.Cells[8].FormattedValue);
cmd.Parameters.AddWithValue("#DateShipTransmitProcessed", row.Cells[9].FormattedValue);
cmd.Parameters.AddWithValue("#ShipmentProcessedBy", row.Cells[10].FormattedValue);
cmd.Parameters.AddWithValue("#Critical", row.Cells[11].FormattedValue);
cmd.Parameters.AddWithValue("#ShipTransmitStatus", row.Cells[13].FormattedValue);
cmd.Parameters.AddWithValue("#jobTableId", row.Cells[5].FormattedValue);
sqlConnection1.Open();
cmd.ExecuteNonQuery();
sqlConnection1.Close();
What I am getting error is that: "Must declare the scalar variable "#ShipTrackingNumber".
I dont want to put ShipTrackingNumber from the code. Instead I want to fetch it from the UI.
What I am doing wrong here?
Well, there's no entry in cmd.Parameters for "#ShipTrackingNumber". What do you mean by "fetch it from the UI"? You could just write a line to add an entry for this parameter:
cmd.Parameters.AddWithValue("#ShipTrackingNumber", GetShipTrackingNumberFromUI());
And then implement GetShipTrackingNumberFromUI() to get the value you want.
It looks like this line is supposed to be something along these lines, but you need to change "#TrackingNumber" to "#ShipTrackingNumber":
cmd.Parameters.AddWithValue("#TrackingNumber", row.Cells[7].FormattedValue);
To answer your direct question, add the parameter with its value taken from the UI. Let's say it's a checkbox named CheckBox1:
cmd.Parameters.AddWithValue("#ShipTrackingNumber", CheckBox1.Checked);
You need to replace this line:
cmd.Parameters.AddWithValue("#TrackingNumber", row.Cells[7].FormattedValue);
with this line:
cmd.Parameters.AddWithValue("#ShipTrackingNumber", row.Cells[7].FormattedValue);

SQL exception was unhandled in c#

When I want to debug this code it gives error on objConnection.Open():
sqlExeption was Unhandled and say(A
network-related or instance-specific
error occurred while establishing a
connection to SQL Server. The server
was not found or was not accessible.
Verify that the instance name is
correct and that SQL Server is
configured to allow remote
connections. (provider: Named Pipes
Provider, error: 40 - Could not open a
connection to SQL Server))
SqlConnection objConnection = new SqlConnection(
"server=localhost;database=pubs;" +
"user id=sa;password=");
SqlDataAdapter objDataAdapter = new SqlDataAdapter();
DataSet objDataSet = new DataSet();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// Set the SelectCommand properties...
objDataAdapter.SelectCommand = new SqlCommand();
objDataAdapter.SelectCommand.Connection =
objConnection;
objDataAdapter.SelectCommand.CommandText =
"SELECT au_lname, au_fname, title, price " +
"FROM authors " +
"JOIN titleauthor ON authors.au_id = " +
"titleauthor.au_id " +
"JOIN titles ON titleauthor.title_id = " +
"titles.title_id " +
"ORDER BY au_lname, au_fname";
objDataAdapter.SelectCommand.CommandType =
CommandType.Text;
// Open the database connection...
**objConnection.Open();**
// Fill the DataSet object with data...
objDataAdapter.Fill(objDataSet, "authors");
// Close the database connection...
objConnection.Close();
// Set the DataGridView properties
// to bind it to our data...
grdAuthorTitles.AutoGenerateColumns = true;
grdAuthorTitles.DataSource = objDataSet;
grdAuthorTitles.DataMember = "authors";
// Clean up
objDataAdapter = null;
objConnection = null;
}
This error typically occurs when your server name is wrong or the sql server is not on.
localhost and (local) are treated differently for sql server. You might want to try (local).
Here's a list of connection strings to help you out.
If you are using sql express then you might want to change it from localhost to .\sqlexpress.
To check that your SQL Server is on be sure the services for it are on. You can do this in services and also in the Configuration Manager.
First of all, with the SqlDataAdapter, you don't need to specifically open and close the SqlConnection yourself - the adapter will do that for you.
Secondly, I'd strongly recommend putting all your ADO.NET code into using(.....) { .... } blocks as a best practise.
Furthermore, on your local PC, typically you don't need to specify a specific user for your database, but you can use the built-in Windows authentication directly (integrated security=SSPI) in your SQL connection string.
And as a last thing: if you don't need multiple tables in your DataSet, it's easier and better to use DataTable instead - less overhead, less performance penalties. No need to specify table names as data members and so forth. Just plain easier.
Try this code:
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
using(SqlConnection objConnection = new SqlConnection("server=(local);database=pubs;integrated security=SSPI;"))
{
SqlDataAdapter objDataAdapter = new SqlDataAdapter();
// Set the SelectCommand properties...
objDataAdapter.SelectCommand = new SqlCommand();
objDataAdapter.SelectCommand.Connection = objConnection;
objDataAdapter.SelectCommand.CommandText =
"SELECT au_lname, au_fname, title, price FROM authors " +
"JOIN titleauthor ON authors.au_id = titleauthor.au_id " +
"JOIN titles ON titleauthor.title_id = titles.title_id " +
"ORDER BY au_lname, au_fname";
DataTable tblData = new DataTable();
// Fill the DataSet object with data...
objDataAdapter.Fill(tblData);
// Set the DataGridView properties
// to bind it to our data...
grdAuthorTitles.AutoGenerateColumns = true;
grdAuthorTitles.DataSource = tblData;
}
}
That way, disposal of the referenced classes will be handled automatically for you.