Рассылка закрыта
При закрытии подписчики были переданы в рассылку "BloggLand и Я | Блоггландия" на которую и рекомендуем вам подписаться.
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
В двадцать четвёртом выпуске рассылки '.Net Собеседник' вы можете прочесть обзор новых компонент и продуктов,
Информационный Канал Subscribe.Ru |
.Net Собеседник #24
Содержание- От автора
- Обзор новостей
- Статья выпуска - Вредоносные SQL-строки
- Время кода - Принудительно собираем мусор в .NET#
- Форумы .Net на www.sql.ru
От автора
Здравствуйте, коллеги!
Обзор новостей
-
Отложен выход SQL Server 2005
- Microsoft решила перенести выпуск SQL Server 2005 с первой половины 2005 года на конец лета того же года.
-
Edit and Continue для C# в Visual Studio 2005
- В ответ на просьбы разработчиков, Microsoft решила распространить особенность "Edit and Continue", ранее доступную только в VB.NET и C++, и на проекты, написанные на C#. Edit and Continue – особенность дебаггера, которая позволяет остановить приложение под дебаггером, отредактировать код и продолжить выполнение без полной перекомпиляции проекта.
-
Вышла книга
"Visual Studio .NET Tips and Tricks"
- Книга "Visual Studio .NET Tips and Tricks" объясняет, как эффективно пользоваться Visual Studio .NET 2002, 2003 и 2005 Beta 1.
-
toolsfactory
выпускает Doc-O-Matic 4
- RENO, Nevada, OCTOBER 2004, toolsfactory объявилао выходе Doc-O-Matic 4. Doc-O-Matic 4 – мощная система документирования исходных кодов для ASP.NET, VB.NET, C/C++, C++.NET, C#, JavaScript, JSP и Java. Doc-O-Matic создаёт полностью кросс-линкованные системы документации, включая Source Code Documentation, Online Help и User Manuals в формате PDF, HTML, HTML Help 1.x, Help 2.0, Windows Help, RTF и XML. В четвёртой версии есть такие особенности, как графические классы иерархий и поддержка модулей.
-
Как
выбрать компонент меню для ASP.NET
- Есть много различных компонент меню, но Component Art предлагает вам действительно толковое меню, в котором есть всё, что только можно себе представить, а стоит - всего $250. Есть ещё один толковый набор – в набор компонент Pro.Net Components входит меню, которое стоит всего 40 баксов. Так что меню от Component Art можно использовать для крутых проектов, а компонент от Pro.Net – для более простых проектов.
-
telerik выпустил
r.a.d.tabstrip v1.0
- telerik r.a.d.tabstrip – гибкий компонент для построения интерфейсов с закладками в приложениях ASP.NET. Используя преимущества Visual Studio .Net Design Mode, можно построить любой mng pfrkfljr - основанные на CSS текстовые закладки, полностью графическое с простыми или перекрывающимися изображениями, прокручивающееся, вертикальное, выровненное, или многоуровневое, также поддерживаются темы .NET 2.0.
-
DbNetLink объявила о выходе
DbNetSpell V1.0
- DbNetSpell.NET – компонент, полностью инкапсулирующий DHTML, который добавляет многоязычную, профессиональную проверку орфографии к вашим веб-страницам. DbNetSpell.NET прост в использовании и инсталляции, легко конфигурируется. Примеры смотрите на веб-сайте, тамже – полнофункциональная версия с ограничением по времени использования.
Статья выпуска
Вредоносные SQL-строки
ЯЗЫК: C#
АВТОР: Fons Sonnemans
Код к статье :
SqlInsert.zip
ПЕРЕВОД: Чужа В.Ф ака hDrummer
Вступление
Знаете ли вы о том, что злоумышленник может повредить данные в вашей БД путём использования вредоносных вставок в строки SQL-запросов? Для предотвращения таких SQL-инъекций можно использовать коллекцию параметров при построении строк SQL-запросов. Однако, я разработал более усовершенствованный метод для создания и безопасного выполнения запросов на языке SQL с использованием пользовательского ввода. В этой статье я опишу использование объектов вместо строк при создании и выполнении SQL-запросов. Эти объекты также будут ответственны за специфический для разных RDBMS синтаксис SQL-запросов – они позволят вам писать код, независимый от той RDBMS, которую вы будете использовать.
SQL-инъекция
В большинстве приложений SQL-запрос, выполняемый SQL Server’ом,
создаётся с использованием строки (или класса StringBuilder) и выполняется с
использованием объекта SqlCommand. SQL-строка может содержать в 2 и более
SQL-запроса (разделённых точкой с запятой) – все они будут исполнены SQL
Server’ом.
private void buttonOK_Click(object sender, System.EventArgs e) { InsertTitle(textBoxId.Text, textBoxTitle.Text, comboType.Text, numberBoxPubId.Value, numberBoxPrice.Value, numberBoxAdvance.Value, numberBoxYTDSales.Value, textBoxNotes.Text, datePickerPubDate.Value); } private void InsertTitle(string id, string title, string type, int pubId, double price, double advance, int ytd_sales, string notes, DateTime pubdate) { StringBuilder sql = new StringBuilder("insert into titles "); sql.Append("(title_id, title, type, pub_id, price, advance, "); sql.Append("ytd_sales, notes, pubdate)"); sql.Append(" values ("); sql.Append("'").Append(id).Append("' ,"); sql.Append("'").Append(title).Append("' ,"); sql.Append("'").Append(type).Append("' ,"); sql.Append(pubId).Append(" ,"); sql.Append(price).Append(" ,"); sql.Append(advance).Append(" ,"); sql.Append("'").Append(notes).Append("' ,"); sql.Append(string.Format("{0:MM/dd/yyyy})", pubdate)); SqlCommand c = new SqlCommand(sql.ToString(), MyConnection); c.ExecuteNonQuery(); } |
В этом примере строка SQL создаётся путём простого соединения разных строк. При
построении допускается, что некоторые поля являются наборами чисел и символов
(т.е. строковыми) и должны быть взяты в одинарные кавычки. Поскольку SQL
принимает одиночную кавычку за разделитель строки, всё, что нужно хакеру, так
это вставить одну лишнюю кавычку в поле ввода, за которой должен следовать
любой код на SQL. Всё вместе может выглядеть таким образом:
', null); delete from titles --
Тогда метод InsertTitle() сгенерирует такой запрос на SQL:
insert into titles (title_id, title, type, pub_id, price, advance,
[ytd_sales], [notes], [pubdate]) values ('FS1234', 'dummy', 'business', 1, 1,
1, 1, '', null); delete from titles --, 22/04/2000)
Решение
Для предотвращения SQL-инъекций можно использовать коллекцию параметров при построении SQL-запросов. Не важно, каким был пользовательский ввод, введённая строка будет считаться именно строкой.
private void InsertTitle(string id, string title, string type,
int pubId, double price, double advance, int ytd_sales, string notes, DateTime pubdate) { StringBuilder sql = new StringBuilder("insert into titles "); sql.Append("(title_id, title, type, pub_id, price, advance, "); sql.Append("ytd_sales, notes, pubdate)"); sql.Append(" values (@par0, @par1, @par2, @par3, @par4, @par5, "); sql.Append("@par6, @par7, @par8)"); SqlCommand c = new SqlCommand(sql.ToString(), MyConnection); c.Parameters.Add(new SqlParameter("par0", id)); c.Parameters.Add(new SqlParameter("par1", title)); c.Parameters.Add(new SqlParameter("par2", type)); c.Parameters.Add(new SqlParameter("par3", pubId)); c.Parameters.Add(new SqlParameter("par4", price)); c.Parameters.Add(new SqlParameter("par5", advance)); c.Parameters.Add(new SqlParameter("par6", ytd_sales)); c.Parameters.Add(new SqlParameter("par7", notes)); c.Parameters.Add(new SqlParameter("par8", pubdate)); c.ExecuteNonQuery(); } |
Для того, чтобы указать в строке параметр, вы должны поместить перед ним префикс (и, опционально, суффикс после него). Например, маркером может быть "@" (SqlServer), ":" (Oracle) или "%". Можно использовать неименованные параметры, если ваша СУБД не поддерживает именованные. Неименованный параметр указывается знаком вопроса (?), который вы вставляете в любое место запроса, там, где необходима вставка какого-то буквального значения.
Классы InsertStatement
Для того, чтобы облегчить использование параметров, необходимо использовать объекты, а не строки SQL, для построения SQL-запросов. Классы InsertStatement используются для построения IDbCommand. Они создают коллекции CommandText и Parameters. На данный момент у меня есть четыре их реализации – для SqlServer, MS Access, MySql и Oracle. Это также дало мне возможность поддержки специфичного для каждой RDBMS синтаксиса для: ключевых слов, параметров, имён таблиц и столбцов, псевдонимов и внешних объединений.
private void
InsertTitle(string id, string title, string type,
int pubId, double price, double advance, int ytd_sales, string notes, DateTime pubdate) { SqlInsertStatement i = new SqlInsertStatement(); i.TableName = "titles"; i.Values.Add("title_id", new Constant(id)); i.Values.Add("title", new Constant(title)); i.Values.Add("type", new Constant(type)); i.Values.Add("pub_id", new Constant(pubId)); i.Values.Add("price", new Constant(price)); i.Values.Add("advance", new Constant(advance)); i.Values.Add("ytd_sales", new Constant(ytd_sales)); i.Values.Add("notes", new Constant(notes)); i.Values.Add("pubdate", new Constant(pubdate)); SqlCommand c = (SqlCommand)i.CreateCommand(); c.Connection = MyConnection; c.ExecuteNonQuery(); } SqlInsertStatement создаст следующий CommandText для System.Data.SqlClient.SqlCommand: insert into [titles] ([title_id], [title], [type], [pub_id], [price], [advance], [ytd_sales], [notes], [pubdate]) values (@par0, @par1, @par2, @par3, @par4, @par5, @par6, @par7, @par8) AccesInsertStatement создаст такой CommandText для System.Data.OleDb.OleDbCommand: insert into [titles] ([title_id], [title], [type], [pub_id], [price], [advance], [ytd_sales], [notes], [pubdate]) values (?, ?, ?, ?, ?, ?, ?, ?, ?) MySqlInsertStatement создаст такой CommandText для Microsoft.Data.Odbc.OdbcCommand: insert into titles (title_id, title, type, pub_id, price, advance, ytd_sales, notes, pubdate) values (?, ?, ?, ?, ?, ?, ?, ?, ?) OracleInsertStatement - такой CommandText для System.Data.OracleClient.OracleCommand: INSERT INTO titles (title_id, title, type, pub_id, price, advance, ytd_sales, notes, pubdate) VALUES (:par0, :par1, :par2, :par3, :par4, :par5, :par6, :par7, :par8) |
InsertStatement и ValuesClause используют массивы токенов для хранения всей необходимой информации. Метод CreateCommand() использует CommandBuilder для создания CommandText и Parameters. Эти CommandBuilder’ы итеративно проходят по массивам и транслируют каждый токен (ключевое слово, литерал, константу, выражение etc) в специфическую для каждой СУБД реализацию.
Классы Select, Update и Delete
Тот же подход можно использовать для операций Select, Update и Delete. Они
немного сложнее, но овчинка стоит выделки, особенно в случае создания вами
СУБД-независимых компонент. Я пришёл в итоге к такой модели (схемы можно
посмотреть здесь http://www.reflectionit.nl/SqlInsert.aspx
).
SelectStatementBase s = new SqlSelectStatement();
s.Select.AddAstrix(); s.From.Add("sales", "s"); s.From.Add(new Join("stores", "s.stor_id", "stores.stor_id", JoinTypes.Left)); s.Where.And(new ConditionLike("title", new Constant("%book%"))); s.OrderBy.Add("ord_date", true); s.OrderBy.Add("qty"); |
Модели для Update и Delete можно посмотреть здесь http://www.reflectionit.nl/SqlInsert.aspx .
Дополнительная информация
- http://www.mcpmag.com/backissues/features/article.asp?EditorialsID=324
- http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetch12.asp
- http://www.devx.com/codemag/Article/10290
Выводы
Написание выражений SQL с использованием объектов, сделало мою
жизнь проще. Надеюсь, что вы используете мои классы, использующие параметры,
для защиты от SQL-инъекций.
В архиве вы можете найти исходный код классов Insert на C# и проект-пример.
Время кода
Принудительно собираем мусор в .NET
ЯЗЫК: C#
АВТОР:
Tom Archer
Код к статье :
Демонстрационный код к статье
ПЕРЕВОД: Чужа В.Ф ака hDrummer
Вступление
Бывают случаи, когда нужно принудить сборщик мусора (GC) в .NET пройтись по
всем неиспользуемым объектам и очистить от них память. Достигается это с
помощью метода GC.Collect. При вызове GC.Collect, GC вызовет finalizer для
каждого объекта в отдельном потоке, ещё один метод, о котором надо помнить -
GC.WaitForPendingFinalizers. Этот синхронный метод не вернёт результат, пока
GC.Collect не закончит работу.
using System;
namespace GCCollect { class Account { public Account(string accountNumber) { this.accountNumber = accountNumber; Console.WriteLine("Account::Acount - c'tor"); } ~Account() { Console.WriteLine("Account::~Acount - d'tor"); } protected string accountNumber; override public string ToString() { return accountNumber; } }; class Class1 { [STAThread] static void Main(string[] args) { CreateAccount("111006116"); GC.Collect(); GC.WaitForPendingFinalizers(); Console.WriteLine("Application ending"); } public static void CreateAccount(string accountNumber) { Console.WriteLine("CreateAccount - instantiate Account object"); Account account = new Account(accountNumber); Console.WriteLine("CreateAccount - created account number {0}", account); } } } |
Если вы откомпилируете и запустите этот пример, то получите следующий
результат:
CreateAccount - instantiate Account object
Account::Acount - c'tor
CreateAccount - created account number 111006116
Account::~Acount - d'tor
Application ending
Заметьте, что:
- Я создал объект Account не в методе Main, поскольку, если б я сделал это в методе Main, а затем вызвал GC.Collect в этом же методе, то объект Account технически был бы ещё проассоциирован с исполняемым кодом и ещё не подлежал бы сборке.
- Хотя я использовал для примера работу метода GC.Collect с одним объектом, но нужно помнить, что метод GC.Collect не был разработан с целью контролирования уничтожения специфического объекта, но с целью принудительно выполнить уборку всех неиспользуемых объектов. Также нужно помнить о том, что это очень дорогостоящая операция – она должна исполняться только в случае действительной необходимости форсировать сборку мусора.
- Для ситуаций, в которых вам необходимо реализовать финализацию конкретного объекта, вы должны реализовать шаблон Dispose, что будет описано в отдельной статье.
{К содержанию}
Форумы .Net на SQL.RU - вопросы оставшиеся без ответа
Связка DataList vs ArrayListОшибка "Сбой при удаленном вызове процедуры"
как сделать cab проект
Неточности ADO для структур таблиц некоторых БД Oracle?
Ошибка в недрах ADO.NET
Firebird Compact Framework Data Provider + Smart Device
Программное создание отчета Crystal из .NET
Вычисляемый столбец не вычисляется после Fill
Фигня с COM Interop
сохранение мультивыделения после перезаполнения датасета
На этом двадцать четвёртый выпуск .Net Собеседника закончен.
До следующего номера.
Чужа Виталий Ф. aka hDrummer,
hdrummer@sql.ru - жду ваши предложения, вопросы и замечания.
http://subscribe.ru/
http://subscribe.ru/feedback/ |
Подписан адрес: Код этой рассылки: comp.soft.prog.dotnetgrains |
Отписаться |
В избранное | ||