SQL Server primary key error - asp.net

I am designing a web-based logistics system using ASP.NET and SQL Server.
In one of my classes when I try to insert data to database, there is a violation of primary key error, but data inserts successfully into the table. I can not find out where the problem is. Can anyone see what I am doing wrong?
public int fillShipmentDetail()
{
int success = 0;
string connectionString = ConfigurationManager.ConnectionStrings["LGDB"].ToString();
SqlConnection sqlCon = new SqlConnection(connectionString);
SqlCommand sqlCom = new SqlCommand("fillShipmentDetails", sqlCon);
sqlCom.CommandType = CommandType.StoredProcedure;
sqlCon.Open();
sqlCom.Parameters.AddWithValue("shipOrderID", ShipOrderID);
sqlCom.Parameters.AddWithValue("totalWeight", TotalWeight);
sqlCom.Parameters.AddWithValue("weightIsMetric", WeightUnit);
sqlCom.Parameters.AddWithValue("weightIsImperial", VolumeUnit);
sqlCom.Parameters.AddWithValue("volume", Volume);
sqlCom.Parameters.AddWithValue("quantity", Quantity);
sqlCom.Parameters.AddWithValue("value", Value);
sqlCom.Parameters.AddWithValue("description", GoodsDescription);
success = sqlCom.ExecuteNonQuery();
if (success == 1)
{
success = 1;
}
else
{
success = 0;
}
sqlCon.Close();
return success;
}
aspx.cs page
Classes.ShipmentDetails fillShipmentDetails = new Classes.ShipmentDetails(
getLastShipOrder, _weight, _checkMetricImperial_weight, _checkMetricImperial_volume,
_volume, _quantity, _value, txtGoodsDescription.Text);
int success3 = fillShipmentDetails.fillShipmentDetail();
As you can see in the below picture the record shipOrderID 7192 is already inserted into the table.
I have deleted all three tables , and insert new data. although data inserts successfully but error happens again.
this screenshot shows everything clearly , by every new insertion into database there is a primary key error on last table , as you can see there is not any duplicate key and data inserted successfully.

looks like fillShipmentDetails.fillShipmentDetail() is getting fired twice. Put a Breakpoint in the code and check

shipOrderId already exists in your table.
You need to give it a new unique value. The reason why the table updates is because the shipOrderId already exists, so you can create a new Shipping Order with the Id, however that order is not referring to the correct shipOrderId

Related

How to handle violating primary key constraints in asp.net?

I have a login page, users have ID's and ID is the primary key in the table. I also have an admin account, and admin can create users. But when i create a user account with an existing ID, the web page crashes. I want to handle this situation and give a warning indicating that this ID exists and cannot be created. Here is my code:
public void CreateStudent(int ID, String status, String email, String firstName, String lastName, String password, String level, String program)
{
SqlConnection con = new SqlConnection(GetConnectionString());
string query1 = "insert into StudentTable(Name,Surname,ID,email,level,program,status,password,Type) values(#firstName,#lastName,#ID,#email,#level,#program,#status,#password,'Student')";
SqlCommand command = new SqlCommand(query1,con);
command.Parameters.AddWithValue("#firstName", firstName);
command.Parameters.AddWithValue("#lastName", lastName);
command.Parameters.AddWithValue("#ID", ID);
command.Parameters.AddWithValue("#email", email);
command.Parameters.AddWithValue("#level", level);
command.Parameters.AddWithValue("#program", program);
command.Parameters.AddWithValue("#status", status);
command.Parameters.AddWithValue("#password", password);
int result;
con.Open();
result = command.ExecuteNonQuery();
con.Close();
}
Can anyone help me with this? Thanls
There are multiple ways. You could catch an Exception and display an error message. That will also help in other error scenario's, like a lost connection.
However, if it's a situation you expect to occur during normal operation, you should handle the situation without an Exception. One way to do that is to have your insert only insert a row with a new id:
insert YourTable
(id, col1, col2, ...)
select #id
, #col1
, #col2
, ...
where not exists
(
select *
from YourTable
where id = #id
)
Pass parameters to your query like:
command.Parameters.AddWithValue("#id", 42);
command.Parameters.AddWithValue("#col1", "value1");
command.Parameters.AddWithValue("#col2", "value2");
Now ExecuteNonQuery() returns the number of affected rows. You can use that to check if the insert actually added a new row to the table:
var result = command.ExecuteNonQuery();
if (result == 1)
{
lblResult.Text = "New row inserted!";
lblResult.Color = Color.Green;
}
else
{
lblResult.Text = "Failed to insert new row.";
lblResult.Color = Color.Red;
}
Rather than tying to handle the error that comes back from attempting to add a user with the same ID, it would be better to check for the user's existence first and only create the new account if you can. Though you still need to handle the exception to cater for the case where two people try to create the same record.
So you'd have the following SQL:
select * from StudentTable where ID = #newID
and if this found a record you could report the error. If it doesn't find anything then you can go ahead and create the new record.
Though if you are using the ID as the primary key it would be better to have that as an Identity column on the table and have it auto-increment when you create a new row. You'd still have to check to see if the student already exists - use the e-mail as the human readable uniqueness condition.
If you add uniqueness constraint on the e-mail column then you'll be able to trap the case of two people trying to create the same record.
I have made the e-mail attribute as a primary key and then checked the database whether same e-mail exists and that worked

ASP.NET page can Insert a date to an Access database, but not Update

I have an ASP.NET page that needs to push a little data to an MS Access 2003 database. The process requires a Select on one record, Inserting one new record and Updating one record. I am connecting to the Access database via an OleDbConnection connection. So far, the Select and Insert functions are working exactly as expected (so I know my connection is good). The Update, however, fails to update any rows. The function to update the record looks like this:
public static int UpdateDeviceDates(int deviceId, DateTime nextTestDate)
{
var conn = DbConnect.AccessConnection();
var sqlString = WebConfigurationManager.AppSettings["UpdateDeviceDates"];
using (var cmd = new OleDbCommand(sqlString, conn))
{
cmd.Parameters.AddWithValue("#DeviceID", deviceId);
cmd.Parameters.AddWithValue("#NextTestDate", nextTestDate);
cmd.CommandType = CommandType.Text;
conn.Open();
var result = cmd.ExecuteNonQuery();
return result;
}
}
The sqlString pulled back from the web.config file looks like this:
UPDATE tblDevice
SET tblDevice.NextTestDate = #nextTestDate,
tblDevice.FirstNoticeDate = Null,
tblDevice.SecondNoticeDate = Null
WHERE DeviceID=#deviceId;
This query works fine if you paste it into a new Access query window and hit run, so I know the syntax is correct. I have done quite a bit of testing and figured out that it is the #nextTestDate field that is causing it to fail. When I took that out of the SQL string, it updated the record as expected. This is disconcerting, because the date I pass through to the Insert function works just fine.
I have looked around quite a bit and the closest I found to an answer was "Can't update date in aspx to a MS-ACCESS table". The main answer there was to change the parameter to a ShortDateString. I tried that to no effect. It was also suggested to bracket the date in #, since that is what Access does in its own queries. Unfortunately, that didn't work either.
I don't know why either of these should have been necessary, because the date comes through in exactly the same format as in the Insert statement and that works fine. I'm at my wits end here because the only thing I've found to make that query work is to remove the date parameter (which would defeat the main purpose of the query).
In your query, the parameters are in a different order, the order must match:
cmd.Parameters.AddWithValue("#NextTestDate", nextTestDate);
cmd.Parameters.AddWithValue("#DeviceID", deviceId);
To match:
UPDATE tblDevice
SET tblDevice.NextTestDate = #nextTestDate, <--- Param 1
tblDevice.FirstNoticeDate = Null,
tblDevice.SecondNoticeDate = Null
WHERE DeviceID=#deviceId; <--- Param 2

Return value in stored proceedure

I am working in asp.net and SQL Server 2005.
I want to know how to return a value from stored procedure or how can we know if a query has been successfully executed in a stored procedure. For example I am inserting some data into a SQL Server database, I want to check if it is inserted correctly or not by using a return value.Here is the code
stored procedure..
ALTER PROCEDURE [dbo].[practice]
-- Add the parameters for the stored procedure here
#thename varchar(50),
#thedate datetime,
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
insert into tblpractice (name,date) values (#thename,#thedate)
END
codebehind..
string name=txtname.Text.Trim();
DateTime date = Convert.ToDateTime(txtdate.Text);
try
{
SqlCommand cmd = new SqlCommand("practice", lcon);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#thename", name);
cmd.Parameters.AddWithValue("#thedate", date);
lcon.Open();
cmd.ExecuteNonQuery();
}
catch
{
throw;
}
finally
{
if (lcon != null)
{
lcon.Close();
}
}
using output parameters you can get values from store procedure. Here is a good example
Stored procedure output parameter asp.net c#
Another example
http://www.c-sharpcorner.com/UploadFile/rohatash/get-out-parameter-from-a-stored-procedure-in-Asp-Net/
Well, simmilar to C#/java sql server can have try catch blocks
here is the link:
http://msdn.microsoft.com/en-us/library/ms175976.aspx
You can preform error handling (oracle have this better solved), or you can relativly easy do IF block to solve your problem with a procedure. F.E. if you return some number (that have to be >0) you can preform check on it, and return -1 or what ever if your select within procedure didnt return any entry.
Those are most common ways to solve your kind of problems.
In your case, you can query DB once more for an entry with values you allready have in procedure and return 0/1 if select count(*) FROM table where .... returns value
ExecuteNonQuery returns an int which is the number of rows affected by the query. In your example, if the stored proc executes successfully, one record will be inserted, so ExecuteNonQuery should return 1.
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executenonquery.aspx
Also you should use using when you're dealing with IDisposable objects e.g.
using (var lcon = new SqlConnection(connectionString))
{
using (var cmd = new SqlCommand("practice", lcon))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#thename", name);
cmd.Parameters.AddWithValue("#thedate", date);
lcon.Open();
return cmd.ExecuteNonQuery();
}
}
This is the equivalent of try catch finally block i.e. it will close your connection whether there is an error or not.

MySQL Data Access Layer: How do you store your queries?

I've been building this project as the solo dev for a while, and while I'm comfortable in the front end and middle tier, I don't really think I'm doing the database the way I should be, and the reason why is because I simply don't really know of any other way. The way I'm currently getting data is by testing out queries in my MySQL workbench and copying and pasting the SQL as a string literal into a method that makes a call to the DB, pulls the data and hydrates my objects.
This hasn't really been a problem until recently, when I had to create a monster of a query and it got me thinking that maybe there's a better way to do this. I don't have a formal DAL separated out, so I know there's room for improvement there, but I was curious about what the correct way would be to store SQL strings. I assume there is a tool somewhere built into VS10 where I can manipulate and work with SQL as SQL instead of as a string.
You should be doing this in stored procedures. That will basically format and store your query. You set parameters that are passed in from your code, then read out the results.
Example:
The C# method:
private void SetNote()
{
const string sql = "sp_SelectControllerNoteByID";
using (var conn = MocSystem.GetMocDbConnection())
{
using (var comm = new SqlCommand(sql, conn))
{
comm.CommandType = CommandType.StoredProcedure;
comm.Parameters.Add(new SqlParameter("#ControllerNoteID", ControllerNoteId));
try
{
conn.Open();
using (var rdr = comm.ExecuteReader())
{
while (rdr.Read())
{
CommentText = rdr["NoteText"].ToString();
_commentor = new User(new Guid(rdr["NoteAuthor"].ToString()));
CommentDate = (DateTime)rdr["NoteDate"];
MocRequestId = (int)rdr["MocRequestID"];
}
}
}
catch (Exception ex)
{
HasError = true;
ErrorMessage += "\nThere was a problem building the note: " + ex.Message;
}
}
}
}
The stored procedure on the DBMS (sql server in this example):
ALTER proc [dbo].[sp_SelectControllerNoteByID]
#ControllerNoteID int
AS
SELECT
ControllerNoteID,
NoteText,
NoteDate,
NoteAuthor,
MocRequestID
FROM
ControllerNotes
WHERE
ControllerNoteID = #ControllerNoteID
So here we call the stored procedure which in this case is just a simple select statement, then we read it out into an object via ADO. Now, this way, you can modify your query without recompiling. Unless you add parameters, in which case you'll have to update those in your code as well.

How to delete in linq to sql?

I am very new to linq to sql and I am not sure how to actually delete a record.
So I been looking at this tutorial
http://weblogs.asp.net/scottgu/archive/2007/05/19/using-linq-to-sql-part-1.aspx
So for Update they have
NorthwindDataContext db = new NorthwindDataContext();
Product product = db.Products.Single(p => p.ProductName == "Toy 1");
product.UnitPrice == 99;
product.UnitsInStock = 5;
db.SubmitChanges();
For delete they have
NorthwindDataContext db = new NorthwindDataContext();
var toyProducts = from p in db.Producsts
where p.ProductName.Contains("Toy")
select p;
db.Products.RemoveAll(toyProducts);
db.SubmitChanges();
So do I have to query every time, to get the record in order to delete that record? Like I can sort of see doing this with update since you need to give it a record which to update first and then make the changes so I understand the querying part but not with delete.
Like can't you just send in what you want to delete and it goes and deletes it? why do you have to first get it and then tell it to be deleted?
Is that not 2 hits on the database?
Also I have foreign key relationship that I am trying to get to work. So I have this
public ViewResult(string param1, string param2)
{
Table A = new Table A
A.Field1 = param1;
A.Field2 = param2;
Delete(A);
}
private void Delete(Table A)
{
DbContext.A.DeleteAllOnsubmit(A.TableB);
DbContext.A.DeleteAllOnSubmit(A.TableC);
DbContext.A.DeleteOnSubmit(A);
}
So this fails it comes up with this message "Cannot remove an entity that has not been attached."
So I can see why the first 2 lines would fail in the delete method, since I made a new object and their is nothing in the object that has any information about TableB and TableC.
I however can't see why the last line still fails even if the 2 other lines where not there.
Like how I thought it would work it would take my Table A class object that I passed in and look through the table for that information contained in it. It does not seem to be the case though.
So do I first have to take the information out and then do a query to get it and then delete it, like in the example?
Also what is the difference between removeAll() and say DeleteAllOnSubmit().
Like I said I am new to linq to sql and have not been able to sit down and read a book on it due to time constraints. Once I have more time I will read through a book probably.
Thanks
You have several questions in your one question, but I will start with the simplest, about attaching, if you already have the primary key. If you don't have the primary key then I have always just done a fetch then a delete, but, whenever I do a fetch I tend to store the primary key for updates and deletes.
It will delete off of the primary key, but if you have that then just attach as I do below and call delete. I don't pass around the object needed by DLINQ as I want to be able to change it if I want, so I pass in a different User object and just pull the PK from the business class and put it into the DAO class.
var db = new MeatRequestDataContext();
if (input.UserID > 0)
{
entity = new User()
{
UserID = input.UserID
};
db.Users.Attach(entity);
db.Users.DeleteOnSubmit(entity);
}
this is a simple way to delete row from table by linq query.may be it helps .
var summary_delete = database.summeries.Find(id);
var delete = database.summeries.Remove(summary_delete);
database.SaveChanges();
reference : http://mvc4asp.blogspot.in/2013/09/how-to-delete-table-row-in-sql-database.html
Inserted_LINQDataContext db = new Inserted_LINQDataContext();
Item itm = new Item();
int ID = Convert.ToInt32(TextBox1.Text);
var DeleteID = from d in db.Items
where d.id == ID
select d;
db.Items.DeleteAllOnSubmit(DeleteID);
db.SubmitChanges();
Label2.Text = "Record deleted Successfully.";
TextBox1.Text = "";
where Item is Table name, Linserted_LINQDataContext is your Linq DB name, id is the Column name in Item table. Items is the alias name of Item table in linq.
SupportDataDataContext Retrive = new SupportDataDataContext();
// SupportDataDataContext delete = new SupportDataDataContext();
Topic res = Retrive.GetTable<Topic>().Single(t => t.ID == topicID);
if (res != null)
{
Retrive.Topics.DeleteOnSubmit(res);
Retrive.SubmitChanges(ConflictMode.ContinueOnConflict);
}
I know the question is old but this may be useful to someone:
"YourDataContext" dc = new "yourDataContext";
"YourTable" element = dc."YourTable".First(a => a.Id == 12345);
dc."YourTable".DeleteOnSubmit(element);
dc.SubmitChanges();

Resources