Return value in stored proceedure - asp.net

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.

Related

Show sqlite database in Delphi XE6 using firedac programmatically

I am new in database using Delphi. Actually I need to display all the tables and their data in a gridview using firedac. Several videos on youtube and docwiki teaches how to access database through visual components i.e. throwing FDConnetion, FDTable, DataSource, etc. on the form.
But I would like to do the same thing programmatically so that I can focus more on coding and separate form from the business logic.
Here is what I have done in C# while accessing MSAccess data:
public void LoadUsersInfo()
{
try {
OleDbConnection Connection = new OleDbConnection();
Connection.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;DataSource=dbCyberNet.accdb;Persist Security Info=False;";
Connection.Open();
OleDbCommand command = new OleDbCommand();
command.Connection = Connection;
String query = "SELECT * FROM tblUsersInfo";
command.CommandText = query;
OleDbDataAdapter adapter = new OleDbDataAdapter(command);
DataTable dt = new DataTable();
adapter.Fill(dt);
dbGrid.DataSource = dt;
}
catch (Exception ex) {
MessageBox.Show("Error occured while loading users information . " + ex.Message.ToString());
}
finally { Connection.Close(); }
}
I would like to do similar in delphi for sqlite database. Here is what I have tried (edited).
procedure TForm1.Button1Click(Sender: TObject);
var
con: TFDConnection;
table: TFDTable;
ds: TDataSource;
begin
con := TFDConnection.Create(nil);
con.LoginPrompt := False;
table := TFDTable.Create(nil);
table.TableName := 'Students';
ds := TDataSource.Create(nil);
ds.DataSet := table;
try
con.Open('DriverID=SQLite;Database=‪studentsDB.sqlite;');
table.Connection := con;
table.Active := True;
con.Connected := True;
DBGrid1.DataSource := ds;
finally
con.Close;
con.Free;
table.Free;
ds.Free;
end;
end;
Whenever I run this code, error dialog appears showing: First chance exception at $759AF097. Exception class ESQLiteNativeException with message '[FireDAC][Phys][SQLite] ERROR: no such table: STUDENTS'. Process Project1.exe (3836)
whereas the same table name exists inside the table and using visual firedac components, I can see the data grid fills easily.
You can do the same as with C#: assign your TFDQuery instance as DataSource of the VCL grid!
Add a TDataSource to the form, set its DataSet property to your TFDQuery, and assign it to your grid.
See the official Delphi documentation and other SO questions.
You can execute your Select query by calling the query's Open method so your code will look like this :-
procedure TStudents.executeQuery;
var
con: TFDConnection;
query: TFDQuery;
begin
con := TFDConnection.Create(nil);
query := TFDQuery.Create(con);
con.LoginPrompt := False;
con.Open('DriverID=SQLite;Database=studentsDB.sqlite;');
query.Connection := con;
query.SQL.Text := 'SELECT * FROM Students';
query.Open;
query.First;
While Not Query.EOF Do
Begin
// Populate your object or do whatever processing you like here.
Query.Next;
End;
end;
You can then programatically create a TDataSource and a Grid and hook those up in code in a similar fashion. You'll need to move the Connection and Query objects out of your object's executeQuery method as they are local variables and will not be accessible to anything outside that method.
Note that Delphi does not garbage collect like C# does, so as it stand, the code leaks memory.
As an aside, your code appears to be an object method and it looks like you're attempting to create a set of business objects that know how to load and save themselves. Rather than roll your own, you might be better served by looking at one of the existing frameworks that exist (tiOPF, InstantObjects, mORMot or TMS Aurelius) to achieve this. These will allow you to concentrate on solving the problem at hand and not worry about the minutae of creating, loading and saving of objects.

SQL Server primary key error

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

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

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.

Maintain transaction from asp.net C# for database while inserting data in two tables

I have two tables in my databse viz.PurchaseOrderMST and SiteTRS. The primary key of PurchaseOrderMST is foreign key in SiteTRS. The case is first data is inserted in PurchaseOrderMST and then SiteTRS using two individual SPs. I want to maintain transaction during insertion on these two tables from the asp.net(C#). If data in the first table is inserted successfully then and only then data in the second tables should be inserted. If insertion fails in second tables, the insertion in the first tables should also rollback.
How can I do this using transaction mechanism of asp.net???
This is not really related to ASP.NET, but generally how transactions work in the .NET framework. With SqlClient, this is how you do it:
using (var connection = new SqlConnection("your connectionstring"))
{
connection.Open();
using (var transaction = connection.BeginTransaction())
{
try
{
using (var command1 = new SqlCommand("SP1Name", connection, transaction))
{
command1.ExecuteNonQuery();
}
using (var command2 = new SqlCommand("SP2Name", connection, transaction))
{
command2.ExecuteNonQuery();
}
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
}
You of course need to add Parameters to the SqlCommand objects before you execute them, and which execute method you use (ExecuteNonQuery(), ExecuteScalar() or ExecuteReader()) depends on whether your stored procedures actually returns any data or not.

Resources