How can I prevent inserting duplicate data into a SQL Server table? - c#

I have a series of data that need to be written into SQL, what should I do to check the data in SQL to prevent same data inserted into table?
Example data to be inserted:
David
James
John
If the 4th data is John again, I want the system to skip the duplicate record (John).
So far I have:
SqlConnection myCnn = new SqlConnection(cnn);
String _state = "Insert into CamNo1(platename, date, camID, path, filename) OUTPUT INSERTED.platename values(#msg, getdate(), #camID, #path, #filename)";
SqlCommand _Query = new SqlCommand(_state, myCnn);
_Query.Parameters.AddWithValue("#msg", msg);
_Query.Parameters.AddWithValue("#camID", camID);
_Query.Parameters.AddWithValue("#path", imageFile);
_Query.Parameters.AddWithValue("#filename", name);
try
{
myCnn.Open();
string checkname = (string)_Query.ExecuteScalar();
myCnn.Close();
getcheckname = checkname;
Console.WriteLine("OK");
}
catch (Exception)
{
}
i got the string value checkname that is last inserted, what should i do check the data?

First, you can prevent a duplicate from ever occurring in the table by using a unique index or constraint. An index/constraint can work in concert with the suggestions below. If you only use a unique index and not one of the below solutions, inserting a duplicate record will throw an error and you will need to handle that on the other end.
Additionally, I would probably insert the data via a stored procedure that checks to see if the row already exists. To do that, you can use either a MERGE statement, as shown in this pseudo code:
create procedure MyProcedure
(
#Name nvarchar(100),
...
)
as
merge MyTable
using
(
select #Name,...
) as source (Name, ...)
on MyTable.Name = source.Name
when not matched then
insert (Name,...) values (source.Name,...)
when matched then
update set Name = #Name,...
or, you could check for the records existence and insert or update manually:
create procedure MyProcedure
(
#Name nvarchar(100),
...
)
as
if not exists (select * from MyTable where Name = #Name)
begin
insert into MyTable (Name,...) values (#Name,...)
end
else
begin
update MyTable
set ...
where Name = #Name
end

If you do not want duplicate data, you should consider enforcing that at the DB level with a UNIQUE CONSTRAINT or a UNIQUE INDEX
SQL Server 2008 also has a MERGE statement you could use to check for matched records. This could be helpful if you want to update an existing record.

If you want to prevent duplicate data from being inserted, you could use a unique index or unique constraint on those fields.
If you want to just run a hard insert statement, but have it do nothing if a value exists, something like this should work. I tested this on a local database I have:
declare #subject as varchar(100);
set #subject = 'hello'
insert into Subjects ([name])
select #subject
where not exists (select 1 from Subjects where [name] = #Subject)

Try This Easy way
{
DataSet ds = New DataSet();
SqlConnection myCnn = New SqlConnection(cnn);
myCnn.Open();
SqlCommand _Query = New SqlCommand("Select *FROM CamNo1 where platename='" + Console.ReadLine + "' ", myCnn);
SqlDataAdapter sda = New SqlDataAdapter(_Query);
sda.Fill(ds);
Int i = ds.Tables[0].Rows.Count;
If (i > 0) Then
{
MessageBox.Show("platename" + Console.WriteLine + "Already Exists ");
ds.Clear();
}
Else
{
SqlConnection myCnn = New SqlConnection(cnn);
String _state = "Insert into CamNo1(platename, date, camID, path, filename) OUTPUT INSERTED.platename values(#msg, getdate(), #camID, #path, #filename)";
SqlCommand _Query = New SqlCommand(_state, myCnn);
_Query.Parameters.AddWithValue("#msg", msg);
_Query.Parameters.AddWithValue("#camID", camID);
_Query.Parameters.AddWithValue("#path", i`enter code here`mageFile`);
_Query.Parameters.AddWithValue("#filename", Name);
Try
{
myCnn.Open();
String checkname = (String)_Query.ExecuteScalar();
myCnn.Close();
getcheckname = checkname;
Console.WriteLine("OK");
}
Catch (Exception)
{
}
}
}

Related

How to get the autoincremented ID inserted row using SQLiteCommand object

I have a SQLite Connection Object and a command object. I insert a row in my table using the ExecuteNonQuery function. How do I get the value of the autoincrement column (ID) from this?
Code for creating database:
creationQuery = "CREATE TABLE IF NOT EXISTS MyTable ( ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT ,MyCol1 NVARCHAR, MyCol2 NVARCHAR)";
My code for inserting values in the DB:
public void InsertIntoDB(string[] vals){
// Global connection objects (This is in an API so every time a new instance of these are created)
connObj = CreateConnection();
cmdObj = connObj.CreateCommand();
cmdObj.CommandText = "INSERT INTO MyTable ('MyCol1',MyCol2) VALUES( '" + vals[0] + "','" + vals[1] + "')";
int id = -1;
try{
cmdObj.ExecuteNonQuery();
id = (int)cmdObj.Parameters["id"].Value; // tried "#id" as well
}catch(Exception ex){
throw ex;
}
}
This code is inserting correctly. But throws an exception ( System.ArgumentOutOfRangeException) in the line where I'm trying to get the ID. Whats going on/ How do i solve this?
EDIT 1: Inside the try block, I added code to just run another query "Select max(ID) from MyTable":
try
{
cmdObj.ExecuteNonQuery();
cmdObj.CommandText = "Select Max(id) from MyTable";
SQLiteDataReader myReader = cmdObj.ExecuteReader();
while (myReader.Read())
{
id = (int)myReader["id"];
}
Console.WriteLine(id);
}
This code throws the same Exception.
select last_insert_rowid();
And you will need to execute it as a scalar query.
string sql = #"select last_insert_rowid()";
long lastId = (long)command.ExecuteScalar(sql); // Need to type-cast since `ExecuteScalar` returns an object.

Where In Clause error on The server support a maximum of 2100 parameters only

I'm currently trying to try catch the insert SQL query from my simple C# application, but when i'm trying to insert the data into database with user id which is added into userIDList parameter, the error came out saying that
The incoming request has too many parameters. The server supports a
maximum of 2100 parameters.
The userIDList sometimes will contains like 60 arrays above then the error will popped out.
My SQL CommandText will contain of
"SELECT * FROM TIME_ATTENDANCE_REPORT WHERE TRXDATETIME = #Date AND USERID IN (001,002,003,004,....)
So i think if more then certain number then the error popped out
Here are my sample code :
List<string> userIDList = new List<string>();
using (SqlCommand sqlDBComm = new SqlCommand())
{
openConnection();
SqlDataReader sqlDBReader;
sqlDBReader = null;
sqlDBComm.CommandText = "SELECT * FROM TIME_ATTENDANCE_REPORT WHERE TRXDATETIME = #Date AND USERID IN (" + string.Join(",", userIDList) + ") ORDER BY USERID ASC ";
sqlDBComm.Parameters.Add("#Date", SqlDbType.DateTime);
sqlDBComm.Parameters["#Date"].Value = GetDateFrom;
sqlDBComm.Connection = sqlDB;
sqlDBComm.CommandType = CommandType.Text;
try
{
sqlDBReader = sqlDBComm.ExecuteReader();
t.Load(sqlDBReader);
sqlDBReader.Close();
if (t.Rows.Count > 0)
{
status = "Update";
}
else
{
status = "Insert";
}
}
catch (Exception errMsg)
{
MessageBox.Show("Error Code: " + errMsg.ToString());
}
finally
{
sqlDBReader.Close();
closeConnection();
}
}
Any other solution can resolve this?
Thanks
There are many ways to solve this problem.
Instead of sending a list of IDs as seperate parameters, you can send a single #IDList parameter as a single comma separated string and let it parsed into IDs at the server side. Here is a function that I use for this (borrowed and modified from Jeff Moden's code):
CREATE FUNCTION [dbo].[iSplitter] (#Parameter VARCHAR(MAX))
RETURNS #splitResult TABLE (number INT, [value] INT)
AS
BEGIN
SET #Parameter = ','+#Parameter +',';
WITH cteTally AS
(
SELECT TOP (LEN(#Parameter))
ROW_NUMBER() OVER (ORDER BY t1.Object_ID) AS N
FROM Master.sys.All_Columns t1
CROSS JOIN Master.sys.All_Columns t2
)
INSERT #splitResult
SELECT ROW_NUMBER() OVER (ORDER BY N) AS Number,
SUBSTRING(#Parameter,N+1,CHARINDEX(',',#Parameter,N+1)-N-1) AS [Value]
FROM cteTally
WHERE N < LEN(#Parameter) AND SUBSTRING(#Parameter,N,1) = ','
RETURN
END
With this function created once, I do it like:
sqlDBComm.CommandText = #"SELECT * FROM TIME_ATTENDANCE_REPORT tar
inner Join dbo.iSplitter(#UserIdList) ul on tar.USERID = ul.[value]
WHERE TRXDATETIME = #Date
ORDER BY USERID ASC ";
sqlDBComm.Parameters.AddWithValue("#UserIdList",string.Join(",", userIDList));
This works very well for 5-6K integer ids but times out if used with 20-30K or more IDs. Then I created another alternative as a CLR procedure, and that one parses the list server side in less than a second. But I think this one is sufficient for your needs.
Another way is to send the IDs as an XML parameter and parse server side again.
Yet another way is to send a table parameter.
PS: Here is a link that shows sample code for other ways. The site is in Turkish but the codes are crystal clear in C#, separate per approach.
EDIT: XML sample using Northwind Orders table:
void Main()
{
int[] IDList = { 10265,10266,10267,10268,10269,10270,10271,10272,10273,10274,10275, 10320, 10400 };
var idsAsXML = new XElement("IDS",
from i in IDList
select new XElement("Row", new XAttribute("Id", i)));
string sql = #"
DECLARE #hDoc int;
DECLARE #tbl TABLE (Id int);
exec sp_xml_preparedocument #hDoc OUTPUT, #XML;
INSERT #tbl
SELECT *
FROM OPENXML(#hDoc, #Nodename, 1) WITH (Id int);
EXEC sp_xml_removedocument #hDoc;
select * from Orders o
where exists (select * from #tbl t where t.Id = o.OrderId) ";
DataTable tbl = new DataTable();
using (SqlConnection con = new SqlConnection(#"server=.\SQLExpress;Trusted_Connection=yes;Database=Northwind"))
{
SqlCommand cmd = new SqlCommand(sql, con);
cmd.Parameters.AddWithValue("#XML", idsAsXML.ToString());
cmd.Parameters.AddWithValue("#NodeName", "/IDS/Row");
con.Open();
tbl.Load(cmd.ExecuteReader());
con.Close();
}
//tbl.Dump(); // linqPad luxury
}
You can create a Table-Valued-Parameter and pass it as a parameter. It requires you to create a new type in your database, and will enable you to pass an array to the query and let the database treat it as a table. If this is something you do a lot, it could come in handy.
I no longer have access to the project where I implemented this but everything is available in the blog post. The code below is not tested, but I hope it can get you in the right direction.
1. Create a new type in your database:
CREATE TYPE integer_list_tbltype AS TABLE (n int NOT NULL PRIMARY KEY)
2. Pass it as parameter:
sqlDBComm.Parameters.Add("#userIds", SqlDbType.Structured)
sqlDBComm.Parameters["#userIds"].Direction = ParameterDirection.Input
sqlDBComm.Parameters["#userIds"].TypeName = "integer_list_tbltype"
sqlDBComm.Parameters["#userIds"].Value = CreateDataTable(userIDList)
3. Method for creating the parameter:
private static DataTable CreateDataTable(IEnumerable<int> ids) {
DataTable table = new DataTable();
table.Columns.Add("n", typeof(int));
foreach (int id in ids) {
table.Rows.Add(id);
}
return table;
}
4. Use it in your SQL:
... AND USERID IN (SELECT n FROM #userIds)
CreateDataTable from here:
How to pass table value parameters to stored procedure from .net code
Rest from here:
http://www.sommarskog.se/arrays-in-sql-2008.html#introduction

MS Access - C# - Retrieve the latest inserted guid

Is there a way to retrieve the latest inserted guid in access with C#?
I tried this: Created a table Cars with a field Id of type autonumber, replicationID and a field Name varchar(250).
var command = myConnection.CreateCommand();
command.Connection.Open();
command.CommandText = "INSERT INTO Cars(Name) VALUES ('Pagani')";
command.ExecuteNonQuery();
command = context.Database.Connection.CreateCommand();
command.CommandText = "SELECT ##Identity";
Console.WriteLine(command.ExecuteScalar());
command.Connection.Close();
The issue which I am getting is:
Console.WriteLine(command.ExecuteScalar());
always shows 0
EDIT
To create the table you can use this statement over the C# OleDb connection (I think that from MS Access query does not work)
CREATE TABLE [Cars] (
[Id] guid not null DEFAULT GenGUID(),
[Name] text null
);
ALTER TABLE [Cars] ADD CONSTRAINT [PK_Cars_6515ede4] PRIMARY KEY ([Id])
I know this is not exactly what you are asking for, but let me suggest an alternative solution which might solve your underlying problem.
Create the GUID in C# and pass it to your insert:
var newGuid = Guid.NewGuid();
var command = myConnection.CreateCommand();
command.Connection.Open();
command.CommandText = "INSERT INTO Cars(Id, Name) VALUES (?, 'Pagani')";
command.Parameters.AddWithValue("#Id", newGuid); // Note: OleDb ignores the parameter name.
command.ExecuteNonQuery();
Console.WriteLine(newGuid);
GUIDs are unique. It really doesn't matter whether it is generated by your application or by the Access database driver.
This option is in all respects superior to reading the GUID afterwards:
You only need one database access.
It's less code.
It's easier.
And you can still omit the GUID in your INSERT in cases where you don't need to know the GUID - no need to change existing code.
If SELECT ##IDENTITY does not work for "ReplicationID" AutoNumber fields then the most likely way to retrieve such a value for a new record is to use an Access DAO Recordset insert, like this:
// required COM reference:
// Microsoft Office 14.0 Access Database Engine Object Library
var dbe = new Microsoft.Office.Interop.Access.Dao.DBEngine();
Microsoft.Office.Interop.Access.Dao.Database db = dbe.OpenDatabase(
#"C:\Users\Public\Database1.accdb");
Microsoft.Office.Interop.Access.Dao.Recordset rst = db.OpenRecordset(
"SELECT [Id], [Name] FROM [Cars] WHERE FALSE",
Microsoft.Office.Interop.Access.Dao.RecordsetTypeEnum.dbOpenDynaset);
rst.AddNew();
// new records are immediately assigned an AutoNumber value ...
string newReplId = rst.Fields["Id"].Value; // ... so retrieve it
// the returned string is of the form
// {guid {1D741E80-6847-4CB2-9D96-35F460AEFB19}}
// so remove the leading and trailing decorators
newReplId = newReplId.Substring(7, newReplId.Length - 9);
// add other field values as needed
rst.Fields["Name"].Value = "Pagani";
// commit the new record
rst.Update();
db.Close();
Console.WriteLine("New record added with [Id] = {0}", newReplId);
which produces
New record added with [Id] = 1D741E80-6847-4CB2-9D96-35F460AEFB19
You can try like this using the OUTPUT :
INSERT INTO myTable(myGUID)
OUTPUT INSERTED.myGUID
VALUES(GenGUID())
You can try like this:
string str1 = "INSERT INTO Cars(Name) VALUES ('Pagani')";
string str2 = "Select ##Identity";
int ID;
using (OleDbConnection conn = new OleDbConnection(connect))
{
using (OleDbCommand cmd = new OleDbCommand(str1, conn))
{
conn.Open();
cmd.ExecuteNonQuery();
cmd.CommandText = str2;
ID = (int)cmd.ExecuteScalar();
}
}

Return ID if record exist, else Insert and return ID

I have the below C# code to check if the record does not exist, insert and return id. But also I need if the record exists, it return the value. What change should I make to C# and SQL part for this to happen? Database is sQL server. Do I still have to use ExecuteScalar() for this?
con.Open();
// Insert ClinRefFileTypeMaster
string command1 = string.Format(
"if NOT exists (select * from [ClinRefFileTypeMaster] where [ClinRefTypeName] = '{0}') Insert into [ClinRefFileTypeMaster] ([ClinRefTypeName]) output INSERTED.[ClinRefTypeID] VALUES('{0}')",
dataToParse[i][0]
);
SqlCommand ClinRefFileTypeMaster = new SqlCommand(command1, con);
// check if there is an value
object checkValue = ClinRefFileTypeMaster.ExecuteScalar();
if (checkValue != null)
ClinRefFileTypeId = (int)checkValue;
A stored procedure to do all the stuff for you would look something like.....
CREATE PROCEDURE usp_Get_ClinRefTypeID
#ClinRefTypeName VARCHAR(100),
#ClinRefTypeID INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #NewID TABLE(ClinRefTypeID INT);
SELECT #ClinRefTypeID = [ClinRefTypeID]
FROM [ClinRefFileTypeMaster]
where [ClinRefTypeName] = #ClinRefTypeName;
IF (#ClinRefTypeID IS NULL)
BEGIN
INSERT INTO [ClinRefFileTypeMaster] ([ClinRefTypeName])
OUTPUT inserted.[ClinRefTypeID] INTO #NewID(ClinRefTypeID)
VALUES(#ClinRefTypeName)
SELECT #ClinRefTypeID = [ClinRefTypeID] FROM #NewID
END
END
And your C# code would look something like.....
con.Open();
// Insert ClinRefFileTypeMaster
SqlCommand cmd = new SqlCommand("usp_Get_ClinRefTypeID", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ClinRefTypeID", SqlDbType.Int).Direction = ParameterDirection.Output;
cmd.Parameters.Add(new SqlParameter("#ClinRefTypeName", dataToParse));
// get the value back from the output parameter
cmd.ExecuteNonQuery();
int ClinRefTypeName = Convert.ToInt32(cmd.Parameters["#ClinRefTypeID"].Value);
There are many ways to achieve this. 1) You can do it all in inline Sql 2) you can do it all in stored proc. 3) You can do it all in code but split the code as this code is frankly doing too much. In general I would avoid insert/query in the same method.
Also try to use SqlParameters instead of building the query as string concat.
I would propose something like this which makes the code a bit more readable
public int InsertAndRetrieveClientRefId(string clientRefTypeName)
{
int id = GetIdIfRecordExists(clientRefTypeName);
if (id == 0)
{
// insert logic here
id = GetIdIfRecordExists(clientRefTypeName);
}
return id;
}
public int GetIdIfRecordExists(string clientRefTypeName)
{
int id = 0;
string command = "select id from ClinRefFileTypeMaster where ClinRefTypeName = #ClinRefTypeName";
SqlParameter nameParameter = new SqlParameter("#ClinRefTypeName", System.Data.SqlDbType.NVarChar, 10) { Value = clientRefTypeName };
using (SqlConnection connection = new SqlConnection("ConnectionString"))
{
using (SqlCommand cmd = new SqlCommand(command))
{
cmd.Parameters.Add(newParameter);
connection.Open();
cmd.Connection = connection;
int.TryParse(cmd.ExecuteScalar().ToString(), out id);
}
}
return id;
}
do all this in database i.e in store procedure
if not exists (select 1 from [ClinRefFileTypeMaster] where [ClinRefTypeName] =#name)
begin
Insert into [ClinRefFileTypeMaster] ([ClinRefTypeName]) values (#name)
end
else
begin
select (as desired) from ClinRefFileTypeMaster where where [ClinRefTypeName] =#name
end
this will either insert new record or it will select already inserted information
Youll need to add an IF EXISTS clause to the SQL statement as well, checking for the same conditions, and providing logic to return a value.
It seems using ExecuteReader would be better if you need it to return the value from the database.
2¢
I personally would split the logic into two queries and run the If statement within c# checking if the value is in the database, then updating the database else returning a value from the database
conn.open()
int CheckDb;
String Command1 = "select * from [ClinRefFileTypeMaster] where [ClinRefTypeName] = #ClinRefFileTypeId";
using (SqlCommand ClinRefFileTypeMaster = new SqlCommand(command1, con);
{
cmd.Parameters.AddWithValue("#ClinRefFileTypeId", {0});
CheckDb = (int)ClinRefFileTypeMaster.ExecuteScalar();
}
If (CheckDb != 0)
//Logic for returning the value from the database
Else
//Here you can request user check data or insert the value into the database.
if you want to perform Instert operation, I think its better you call a stored procedure and write your query in the procedure. It will be safer.
SqlCommand command = new SqlCommand("procedureName",con);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue(“#value1”, txtValue1.Text);
command.Parameters.AddWithValue(“#value2”, Value2);
int value = command.ExecuteScalar();
IF EXISTS (SELECT 1 FROM Table WHERE FieldValue='')
BEGIN
SELECT TableID FROM Table WHERE FieldValue=''
END
ELSE
BEGIN
INSERT INTO TABLE(FieldValue) VALUES('')
SELECT SCOPE_IDENTITY() AS TableID
END
If you want to pass the querystring, you can call select query and if it returns null perform a insert opeartion and use scope_Identity() to get the ID
INSERT INTO YourTable(val1, val2, val3 ...)
VALUES(#val1, #val2, #val3...);
SELECT SCOPE_IDENTITY();

Checking a table for an existing record before a new record is inserted

I have a details view that I am using to fill a table with values. It is now inserting values correctly but I needed to now check to see if the user is trying to enter a new record that would interfere with the previous records.
If A user enters a new event that falls on 2012-12-12 but that same user has already entered a record for 2012-12-12 then i would like an error to be thrown and the record not able to be inserted.
Just checking for a unique record of the time wont work because a different user can create an even 2012-12-12 and it will be acceptable. Only the same user cannot create the same events dates. So I know I need to check two of the fields in the table but I was unsure of how to do this checking in my code.
For example:
user 1 new event 2012-12-12 ----- ok
user 2 new event 2012-12-12 ----- ok
user 3 new event 2012-12-12 ----- ok
user 2 new event 2012-12-12 ----- should throw an error and not allow that record to be created.
user 3 new event 2012-10-12 ----- ok
EDITED
Currently I am using this to update the table:
public void UpdateForm(Int64 requestid,
Decimal empid,
String leave,
DateTime startdate,
DateTime enddate,
String starttime,
String endtime,
String standby,
String status,
String rsn,
String remarks,
String approver,
String with,
String reqleave,
String FIRSTNAME,
String LASTNAME)
{
var CurrUser = "a03 ";
Account.Login uusr = new Account.Login();
CurrUser = uusr.User.Identity.Name.ToString().ToUpper();
var sql = "update TIME.request set empid=#empid, leave=#leave, with=#with, startdate=#startdate, reqleave=#reqleave, enddate=#enddate, starttime=#starttime, endtime=#endtime, standby=#standby, status=#status, rsn=#rsn, remarks=#remarks, approver=#approver where requestid = #requestid";
using (iDB2Connection conn = new iDB2Connection(GetConnectionString()))
{
conn.Open();
using (iDB2Command cmd = new iDB2Command(sql, conn))
{
cmd.DeriveParameters();
cmd.Parameters["#requestid"].Value = requestid;
cmd.Parameters["#empid"].Value = empid;
cmd.Parameters["#leave"].Value = leave;
cmd.Parameters["#startdate"].Value = startdate;
cmd.Parameters["#enddate"].Value = enddate;
cmd.Parameters["#starttime"].Value = starttime;
cmd.Parameters["#endtime"].Value = endtime;
cmd.Parameters["#standby"].Value = standby;
cmd.Parameters["#status"].Value = status;
cmd.Parameters["#rsn"].Value = rsn;
cmd.Parameters["#remarks"].Value = remarks;
cmd.Parameters["#approver"].Value = approver;
cmd.Parameters["#reqleave"].Value = reqleave;
cmd.Parameters["#with"].Value = with;
cmd.ExecuteNonQuery();
}
}
}
create a unique Constraint on the columns
Click here for examples
ALTER TABLE <table_name>
ADD CONSTRAINT <constraint name> UNIQUE (user,date)
Edit:
as per your comment, please try this:
ALTER TABLE TIME.request
ADD CONSTRAINT uc_request UNIQUE (empid, startdate, enddate)
Create a stored procedure and have an output parameter, check if the item your inserting exists:
if exists(select 1 from table where user = #user and eventtime = #eventtime)
begin
set #output = 'event already exists'
end
else
begin
--Prevent DBNull output, see comments
set #output = ''
--Insert into table
end
Add an output parameter to the procedure through C#
var output = new SqlParameter() { Direction = ParameterDirection.Output, ParameterName = "#Output" };
var cmd = new SqlCommand("procname", connection)
cmd.Parameters.Add(output);
//Add other params
cmd.ExecuteNonQuery();
if (!string.IsNullOrEmpty(output.Value))
//Handle the error
throw new Exception("Already exists");
A stored procedure in SQL is what you are looking for with the relevant parameters following the above, comment if there is something you don't understand.
EDIT: How to create and call a procedure
CREATE PROCEDURE [dbo].[Prefix_SomeProcName]
--Parameters you need from the front end
#User varchar(50),
#EventTime datetime,
#Output varchar(100) output
--Created by: Your name
--Created date: Todays date
--Description: To do some stuff
AS
--Do your stuff here
if exists(select 1 from table where user = #user and eventtime = #eventtime)
begin
set #output = 'event already exists'
end
else
begin
--Prevent DBNull output, see comments
set #output = ''
--Insert into table
end
Then you need a to import System.Data.SqlClient and do the following.
using(SqlConnection con = New SqlConnection("ConnectionString")
{
SqlCommand cmd = new SqlCommand("Prefix_SomeProcName", con);
cmd.CommandType = CommandType.StoredProcedure;
var output = new SqlParameter() { Direction = ParameterDirection.Output, ParameterName = "#Output" };
//Add your other parameters
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DatatTable dt = New DataTable();
sda.Fill(dt);
}
The DataTable will now have the contents of the procedure if there is a select statement in it. Also, after the Fill() command you can access output.Value as mentioned in the above code.
If this behaviour is epxected and you don't want the overhead of trapping the exception, you can check for existence in the same action as the isnert:
insert into myTable(...)
select ...
where not exists (select 1 from myTable where....)
This will work in Sql Server, but not with MySql.

Categories

Resources