Bizonozubr
@Bizonozubr
IT специалист в не IT сфере

Почему теряется user_type_id со временем?

Декомпилировал ПО от подрядчика, чтобы посмотреть на следующий баг. В определенный момент в базу пишется неверная дата, точнее идет перестановка дня и месяца местами.
функция WriteOperMess
// Token: 0x060000A7 RID: 167 RVA: 0x0000544C File Offset: 0x0000364C
public void WriteOperMess(int MessKod, string Message)
{
	try
	{
		int num = 0;
		int num2 = 1;
		SqlDb sqlDb = new SqlDb();
		sqlDb.Open();
		sqlDb.GetFieldType("PLCMESSAGE", "DTIME");
		sqlDb.CreateDbCommand("SELECT TOP(1) ID, isAck, Priority FROM Message Where Sysid = 250 AND Mess = " + MessKod + " ORDER BY ID DESC");
		sqlDb.ExecuteReader();
		while (sqlDb.Reader.Read())
		{
			num = Convert.ToInt32(sqlDb.Reader["isAck"]);
			num2 = Convert.ToInt32(sqlDb.Reader["Priority"]);
		}
		sqlDb.Reader.Close();
		sqlDb.CreateDbCommand("INSERT INTO PLCMessage (IDmess, Place, DTime, dTimeAck, SysID, SysNum, Mess, Message, IsAck, Priority, Value) VALUES (@IDmess, @Place, @DTime, @dTimeAck, @SysID, @SysNum, @Mess, @Message, @IsAck, @Priority, @Value)");
		sqlDb.Command.Parameters.Add("@IDmess", SqlDbType.Int).Value = -1;
		sqlDb.Command.Parameters.Add("@Place", SqlDbType.VarChar).Value = Environment.MachineName;
		if (sqlDb.UseDateTimeInPlcMessage)
		{
			DateTime dateTime = DateTime.Now;
			dateTime = dateTime.AddMilliseconds((double)(-(double)dateTime.Millisecond));
			sqlDb.Command.Parameters.Add("@DTime", SqlDbType.DateTime2).Value = dateTime;
		}
		else
		{
			string text;
			if (DateTime.Now.Second <= 9)
			{
				text = "0" + Convert.ToString(DateTime.Now.Second);
			}
			else
			{
				text = Convert.ToString(DateTime.Now.Second);
			}
			string text2;
			if (DateTime.Now.Minute <= 9)
			{
				text2 = "0" + Convert.ToString(DateTime.Now.Minute);
			}
			else
			{
				text2 = Convert.ToString(DateTime.Now.Minute);
			}
			string text3;
			if (DateTime.Now.Hour <= 9)
			{
				text3 = "0" + Convert.ToString(DateTime.Now.Hour);
			}
			else
			{
				text3 = Convert.ToString(DateTime.Now.Hour);
			}
			string text4 = Convert.ToString(DateTime.Now.Date);
			string value = string.Concat(new string[]
			{
				text4.Substring(0, 10),
				" ",
				text3,
				":",
				text2,
				":",
				text
			});
			sqlDb.Command.Parameters.Add("@DTime", SqlDbType.VarChar).Value = value;
		}
		sqlDb.Command.Parameters.Add("@dTimeAck", SqlDbType.VarChar).Value = ((num == 1) ? "Квитировать" : "");
		sqlDb.Command.Parameters.Add("@SysID", SqlDbType.Int).Value = 250;
		sqlDb.Command.Parameters.Add("@SysNum", SqlDbType.Int).Value = 1;
		sqlDb.Command.Parameters.Add("@Mess", SqlDbType.Int).Value = MessKod;
		sqlDb.Command.Parameters.Add("@Message", SqlDbType.VarChar).Value = Message;
		sqlDb.Command.Parameters.Add("@IsAck", SqlDbType.Int).Value = num;
		sqlDb.Command.Parameters.Add("@Priority", SqlDbType.Int).Value = num2;
		sqlDb.Command.Parameters.Add("@Value", SqlDbType.VarChar).Value = "";
		sqlDb.Command.ExecuteNonQuery();
		sqlDb.Close();
	}
	catch (Exception exception)
	{
		Log.WriteLogToFile(exception);
	}
}


Получается, если флаг UseDateTimeInPlcMessage не в True, тогда выполняется невполне корректный код, который из-за языковых настроек системы дает разные результаты.
Поэтому возник вопрос в формировании флага UseDateTimeInPlcMessage - как он возникает.
За это отвечает функция SqlDb.FieldType GetFieldType:
public SqlDb.FieldType GetFieldType(string table = "PLCMESSAGE", string field = "DTIME")
{
	SqlDb.FieldType fieldType = SqlDb.FieldType.Nvarchar;
	if (this.SqlConnected())
	{
		try
		{
			this.CreateDbCommand(string.Concat(new string[]
			{
				"SELECT C.NAME 'COLUMN_NAME', C.IS_NULLABLE, C.USER_TYPE_ID, T.NAME 'TYPE_NAME' FROM SYS.COLUMNS C LEFT JOIN SYS.TYPES T ON T.USER_TYPE_ID = C.USER_TYPE_ID WHERE C.OBJECT_ID = OBJECT_ID('",
				table,
				"') AND C.NAME = '",
				field,
				"'"
			}));
			this.ExecuteReader();
			if (this.Reader.HasRows && this.Reader.Read())
			{
				fieldType = (SqlDb.FieldType)Convert.ToInt32(this.Reader["USER_TYPE_ID"].ToString());
			}
			this.Reader.Close();
		}
		catch (Exception)
		{
		}
	}
	this.UseDateTimeInPlcMessage = (fieldType == SqlDb.FieldType.Datetime || fieldType == SqlDb.FieldType.Datetime2);
	return fieldType;
}


Судя по коду, может быть условие когда нет коннекта с базой, но тогда бы и сообщение бы не записалось тоже (а оно в базу записывается).
Вопрос - почему результат ExecuteReader из fieldType может быть нулевым? База как была запущена, так и есть, приложение не перезапускается, Net Framework как стоял и стоит.

Понятно, что для отыскания бага придется править данную библиотеку (чтобы вообще посмотреть, заходит ли в данный if), но может можно понять, почему в такое состояние переходит система/база данных?
  • Вопрос задан
  • 68 просмотров
Пригласить эксперта
Ответы на вопрос 1
tsklab
@tsklab Куратор тега SQL Server
Здесь отвечаю на вопросы.
Сделать триггер на таблице, в котором исправлять дату.
Покажите в каком виде @DTime идёт в базу.
Или там используется текущее? Тогда просто в триггере меняйте дату на GETDATE().
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы