在插入新记录之前,我正在验证记录的存在性。但是,代码不会跳入insert块。在Reader.Close之后跳转到finally block
我怀疑我一定是做错了什么,因为没有例外,而且每次RecordsInfacted=-1
{
// 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();
}
Reader.RecordsImpect
不可靠,最终不是为了这个目的;如果你想测试是否存在,那么...“对代码更改最少”的方法是增加计数器来计算行数:
int records = 0;
while (reader.Read()) records++;
if (records == 0) {...}
或者更懒惰:
bool any = reader.Read();
if (any) {...}
但是:那是不必要的嘈杂;您可以从...
中选择count(1),但即使这样也是一个额外的往返行程。一个不错的想法可能是单个SQL操作(在同一批处理中执行存在和插入):
if not exists (
select id from [dbo].[trade_events]
where instrument =@instrument and datetime>@datetime and eventname=@eventname
)
begin
insert into ...
end
但即使这仍然是一个竞争条件,除非您有合适的事务隔离。
如果您查看RecordsImpect
的文档,就可以清楚地看到为什么您会得到-1:
更改、插入或删除的行数;如果没有行受影响或语句失败,则为0;和-1表示SELECT语句。
可以使用HasRows
属性:
using(SqlDataReader reader = command.ExecuteReader())
{
if (reader.HasRows)
{
// insert
}
}