I am validating existance of a record before it inserts new record in. However the code does not jump into insert block. it jumps to finally block after reader.close
i suspect i must be doing something wrong as there is no exceptions and the recordsaffected =-1 every time
{
// check if data exists before inserting
command.Connection = connection;
command.CommandType = CommandType.Text;
command.CommandText = " SELECT id from [dbo].[trade_events] where instrument =@instrument and datetime>@datetime and eventname=@eventname";
command.Parameters.AddWithValue("@datetime", dt);
command.Parameters.AddWithValue("@instrument", instrument);
command.Parameters.AddWithValue("@eventname", eventname);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read()) ;
reader.Close();
if (reader.RecordsAffected <= 0)
{
// <== insert data now
command.CommandText = " INSERT INTO [dbo].[trade_events] ([datetime] ,[instrument],[source],[eventname],[eventdetails],[state],[account],[connection]) " +
"values(@datetime, @instrument,@source, @eventname,@eventdetails,@state,@account,@connection)";
// command.CommandText = "UPDATE [dbo].[Alerts] SET [datetimealertrecieved] = @timerecieved where instrument=@instrument and alertType =@alerttype and datetimealertrecieved is null" ;
command.Parameters.AddWithValue("@datetime", dt);
command.Parameters.AddWithValue("@instrument", instrument);
command.Parameters.AddWithValue("@source", source);
command.Parameters.AddWithValue("@eventname", eventname);
command.Parameters.AddWithValue("@eventdetails", eventdetails);
command.Parameters.AddWithValue("@state", state);
command.Parameters.AddWithValue("@account", account);
command.Parameters.AddWithValue("@connection", dataconnection);
connection.Open();
int recordsAffected = command.ExecuteNonQuery();
}
}
catch (SqlException ex)
{
// error here
var notice = airbrake.BuildNotice(ex);
var response = airbrake.NotifyAsync(notice).Result;
notice = airbrake.BuildNotice(command.CommandText);
response = airbrake.NotifyAsync(notice).Result;
}
finally
{
connection.Close();
}
If you look at the documentation of RecordsAffected
it's clear why you get -1:
The number of rows changed, inserted, or deleted; 0 if no rows were affected or the statement failed; and -1 for SELECT statements .
You can use the HasRows
property:
using(SqlDataReader reader = command.ExecuteReader())
{
if (reader.HasRows)
{
// insert
}
}
You have to clear previous parameters before adding the new ones:
var cont=false;
while (reader.Read())
{
....your code
cont=true ;
}
reader.Close();
if (cont)
{
command.Parameters.Clear();
command.Parameters.AddWithValue("@datetime", dt);
command.Parameters.AddWithValue("@instrument", instrument);
command.Parameters.AddWithValue("@source", source);
command.Parameters.AddWithValue("@eventname", eventname);
.....
}
reader.RecordsAffected
isn't reliable, and isn't intended for this, ultimately; if you're trying to test for existence, well... the "least changes to the code" way would be to increment a counter to count the rows :
int records = 0;
while (reader.Read()) records++;
if (records == 0) {...}
or perhaps the more lazy:
bool any = reader.Read();
if (any) {...}
but: that's unnecessarily noisy; you could select count(1) from...
, but even that is an extra round trip. An OK-ish idea might be the single SQL operation (that does the existence and insert in the same batch):
if not exists (
select id from [dbo].[trade_events]
where instrument =@instrument and datetime>@datetime and eventname=@eventname
)
begin
insert into ...
end
but even this is still a race condition, unless you have suitable transactional isolation.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.