Хочу из своей WinForms программы писать лог ошибок в базу.
Проблема: не могу написать компактный и красивый код, потому что проверки разных условий приводят к длинным IF — ам.
Но вообще советы приму с благодарностью.
public static class WriteLog {
private static SqlConnection cn;
public static void WriteLog(Exception ex=null) {
cn = CheckSqlConn(cn); // Проверяет, если коннекшн нулевой или не открытый - делает правильный коннекшнtry
{
string sql = @"insert into [LogTable] ([Dt], [Source], [Message], [StackTrace], ) values (@Dt, @Source, @Message, @StackTrace)";
SqlCommand sCmd1 = new SqlCommand(sql, cn);
sCmd1.Parameters.Add(new SqlParameter("@dt", DateTime.Now));
sCmd1.Parameters.Add(new SqlParameter("@Source", ex.Source));
sCmd1.Parameters.Add(new SqlParameter("@Message", ex.Message));
sCmd1.Parameters.Add(new SqlParameter("@StackTrace", ex.StackTrace));
sCmd1.ExecuteScalar();
}
catch (Exception ex2)
{
// Ну не шмогла...
}
}
}
2) Второй подход к сняряду — учитываем, что exception может быть null, и отдельные его поля могут быть null
получается что то вроде
public static void WriteLog(Exception ex=null) {
cn = CheckSqlConn(cn); // Проверяет, если коннекшн нулевой или не открытый - делает правильный коннекшнtry {
string sql = @"insert into [LogTable] ([Dt], [Source], [Message], [StackTrace], ) values (@Dt, @Source, @Message, @StackTrace)";
SqlCommand sCmd1 = new SqlCommand(sql, cn);
sCmd1.Parameters.Add(new SqlParameter("@dt", DateTime.Now));
if (ex != null) {
sCmd1.Parameters.Add(new SqlParameter("@Source", ex.Source ?? String.Empty));
sCmd1.Parameters.Add(new SqlParameter("@Message", ex.Message ?? String.Empty));
sCmd1.Parameters.Add(new SqlParameter("@StackTrace", ex.StackTrace ?? String.Empty));
}
else {
sCmd1.Parameters.Add(new SqlParameter("@Source", String.Empty));
sCmd1.Parameters.Add(new SqlParameter("@Message", String.Empty));
sCmd1.Parameters.Add(new SqlParameter("@StackTrace", String.Empty));
}
sCmd1.ExecuteScalar();
}
catch (Exception ex2) {
// Ну не шмогла...
}
}
3) Теперь вспоминаю, что строки могут быть слишком длинными для нашей таблицы, и тут уже получается совсем некрасиво:
public static void WriteLog(Exception ex=null) {
cn = CheckSqlConn(cn); // Проверяет, если коннекшн нулевой или не открытый - делает правильный коннекшнtry {
string sql = @"insert into [LogTable] ([Dt], [Source], [Message], [StackTrace], ) values (@Dt, @Source, @Message, @StackTrace)";
SqlCommand sCmd1 = new SqlCommand(sql, cn);
sCmd1.Parameters.Add(new SqlParameter("@dt", DateTime.Now));
if (ex != null) {
string s1 = ex.Source ?? String.Empty ;
if (s1.Length > 255)
s1 = s1.Substring(0, 255);
sCmd1.Parameters.Add(new SqlParameter("@Source", s1 ));
string s2 = ex.Message ?? String.Empty;
if (s2.Length > 255)
s2 = s2.Substring(0, 255);
sCmd1.Parameters.Add(new SqlParameter("@Message", s2 ));
string s3 = ex.StackTrace ?? String.Empty;
if (s3.Length > 3000)
s2 = s2.Substring(0, 3000);
sCmd1.Parameters.Add(new SqlParameter("@StackTrace", s3));
}
else {
sCmd1.Parameters.Add(new SqlParameter("@Source", String.Empty));
sCmd1.Parameters.Add(new SqlParameter("@Message", String.Empty));
sCmd1.Parameters.Add(new SqlParameter("@StackTrace", String.Empty));
}
sCmd1.ExecuteScalar();
}
catch (Exception ex2) {
// Ну не шмогла...
}
}
— и вот эта конструкция из четырех строк и одной переменной только для того, чтобы проверить, что строка не null и не слишком длинная — меня совсем не радует...
То есть если есть более правильный путь — можно мне его рассказать?
Я понимаю, что есть готовые фреймворки для записи логов, но хочется научиться писать ПРАВИЛЬНЫЙ код...
Re: Запись логов в базу. Как это написать коротко и правильно?
Здравствуйте, SteeLHeaD, Вы писали:
SLH>3) Теперь вспоминаю, что строки могут быть слишком длинными для нашей таблицы, и тут уже получается совсем некрасиво:
SLH>
SLH>- и вот эта конструкция из четырех строк и одной переменной только для того, чтобы проверить, что строка не null и не слишком длинная — меня совсем не радует... SLH>То есть если есть более правильный путь — можно мне его рассказать? SLH>Я понимаю, что есть готовые фреймворки для записи логов, но хочется научиться писать ПРАВИЛЬНЫЙ код...
Попробуйте вынести общий функционал в отдельный приватный метод. Вот так допустим:
Здравствуйте, SteeLHeaD, Вы писали:
SLH>Хочу из своей WinForms программы писать лог ошибок в базу. SLH>То есть если есть более правильный путь — можно мне его рассказать?
Все банально и просто: id (время + уникальное чего-то, чтобы не было дупликатов) + blob (сериализованный exception + extra).
Такая запись всегда создастся (т.к. ид и блоб можно создать).
Фильтр по дате есть, остальное фильтровать при десериализации (более медленно, но кого это заботит).
---
ПроГLамеры объединяйтесь..
Re[2]: Запись логов в базу. Как это написать коротко и правильно?
Здравствуйте, abibok, Вы писали:
A>Могут быть проблемы с десериализацией и версионностью.
В каком месте? Юзаю бинари и xml сериализацию без проблем, в блобе должно быть поле/свойство Version, десериализовать, проверять версию, разруливать если старая. Естествено при изменении версии блоба поддерживать совместимость снизу-вверх.
Насчет сериализации, в бинари есть [OptionalField] решает при добавлении новых полей. В xml все проще, но нужно быть осторожным с enum (никогда не убивать старые значения в enum).
Дополнительный бонус, это то, что блобы сложно редактировать — защищенность данных от изменения.
Минусы — это скорость фильтра по полям/свойствам блоба (т.к. нужно все блобы десериализовать).
---
ПроГLамеры объединяйтесь..
Re: Запись логов в базу. Как это написать коротко и правильно?
Здравствуйте, SteeLHeaD, Вы писали: SLH> [StackTrace] [varchar](3000) NULL)
А если не влезет? Обидно будет изучать stacktrace, который вдруг неожиданно обрывается. 3000 для stacktrace не так уж много. varchar(8000) облегчают проблему, varchar(max) решают кардинально.
SLH>- и вот эта конструкция из четырех строк и одной переменной только для того, чтобы проверить, что строка не null и не слишком длинная — меня совсем не радует...
Постоянно повторяется что-то — выделяй метод.
SLH>То есть если есть более правильный путь — можно мне его рассказать? SLH>Я понимаю, что есть готовые фреймворки для записи логов, но хочется научиться писать ПРАВИЛЬНЫЙ код...
Есть мнение, что писать правильный код — это использовать правильные фреймворки там, где они хорошо подходят и решают задачу лучше самописных изобретений.
Здравствуйте, abibok, Вы писали:
S>>Все банально и просто: id (время + уникальное чего-то, чтобы не было дупликатов) + blob (сериализованный exception + extra).
A>Могут быть проблемы с десериализацией и версионностью.
проблемы с версионностью решаются просто. в бинарном представлении записывается размер структуры и номер версии. при выходе следующей версии -- размер увеличивается. старые версии читают только те данные, которые они могут прочитать, отбрасывая остальные.
в принципе, достаточно одного размера без указания версии. но версия позволит располагать данные более компактно. любое представление данных в каком-то смысле является бинарным, даже если оно текстовое. скажем, версия 1.0 понимала только десятичные числа. в версии 2.0 добавили хекс, а в версии 3.0 еще и уникод поддержали. что может сделать версия 1.0 с файлом в уникоде, в котором числа записаны хексом?
ЗЫ. известный мне софтвер, пишущий логи в базу, удаляет старые логи при смене мажорных версий.
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.