Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

В двадцать четвёртом выпуске рассылки '.Net Собеседник' вы можете прочесть обзор новых компонент и продуктов,


Информационный Канал Subscribe.Ru

.Net Собеседник #24

Содержание
  1. От автора
  2. Обзор новостей
  3. Статья выпуска - Вредоносные SQL-строки
  4. Время кода - Принудительно собираем мусор в .NET#
  5. Форумы .Net на www.sql.ru

От автора

Здравствуйте, коллеги!

Несколько дней не мог пробиться на http://www.subscribe.ru/ :(((. Поэтому рассылка так и задержалась. Ну ничего, нагоним - событий за это время случилось предостаточно, о чём и читайте в выпуске.

Желаю приятного чтения.

{К содержанию}

Обзор новостей

  1. Отложен выход SQL Server 2005
    Microsoft решила перенести выпуск SQL Server 2005 с первой половины 2005 года на конец лета того же года.
  2. Edit and Continue для C# в Visual Studio 2005
    В ответ на просьбы разработчиков, Microsoft решила распространить особенность "Edit and Continue", ранее доступную только в VB.NET и C++, и на проекты, написанные на C#. Edit and Continue – особенность дебаггера, которая позволяет остановить приложение под дебаггером, отредактировать код и продолжить выполнение без полной перекомпиляции проекта.
  3. Вышла книга "Visual Studio .NET Tips and Tricks"
    Книга "Visual Studio .NET Tips and Tricks" объясняет, как эффективно пользоваться Visual Studio .NET 2002, 2003 и 2005 Beta 1.
  4. 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. В четвёртой версии есть такие особенности, как графические классы иерархий и поддержка модулей.
  5. Как выбрать компонент меню для ASP.NET
    Есть много различных компонент меню, но Component Art предлагает вам действительно толковое меню, в котором есть всё, что только можно себе представить, а стоит - всего $250. Есть ещё один толковый набор – в набор компонент Pro.Net Components входит меню, которое стоит всего 40 баксов. Так что меню от Component Art можно использовать для крутых проектов, а компонент от Pro.Net – для более простых проектов.
  6. 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.
  7. DbNetLink объявила о выходе DbNetSpell V1.0
    DbNetSpell.NET – компонент, полностью инкапсулирующий DHTML, который добавляет многоязычную, профессиональную проверку орфографии к вашим веб-страницам. DbNetSpell.NET прост в использовании и инсталляции, легко конфигурируется. Примеры смотрите на веб-сайте, тамже – полнофункциональная версия с ограничением по времени использования.
BUGs, FIXes and HOW TO's -
  1. Some files in the Dllcache folder may not be updated when you run the Setup program for Microsoft Data Access Components

{К содержанию}

Статья выпуска


Вредоносные 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’ом.

Если вы строите строки SQL не фильтруя пользовательский ввод, то помните, что ваше приложение может быть атаковано злобным хакером (и вообще, пользователям верить нельзя – помните об этом!). Риск состоит в том, что когда вы вставляете пользовательский ввод без проверки, а он потом становится запросом, принимаемым сервером к исполнению, то вполне может оказаться так, что взломщик присоединил команды SQL к вашим, используя escape-последовательности.
Пример: представьте себе форму, запись, отображающаяся в которой, должна быть добавлена в таблицу Titles. Пользователь может набрать значения полей title (name), publisher-ID, price etc. в текстовых полях формы. При нажатии на кнопку OK вызывается метод InsertTitle(), который использует введённые значения как аргументы.

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)

В этом случае произойдёт выполнение команды INSERT, которая, возможно, сгенерирует ошибку, поскольку поле pubdate было установлено в NULL (если БД так запрограммирована). Затем будет исполнена команда DELETE, которая удалит все записи в БД. Ущерб нанесён!

Решение

Для предотвращения 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 имеет для каждого выражения ассоциацию с объектом Clause.
Вот ещё один пример с внешним объединением и ‘like’ в выражении ‘where’:

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 .

Дополнительная информация

Выводы

Написание выражений 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 - жду ваши предложения, вопросы и замечания.


Рассылки Subscribe.Ru
.Net Собеседник - Новости мира Net, C#, ASP.Net

http://subscribe.ru/
http://subscribe.ru/feedback/
Подписан адрес:
Код этой рассылки: comp.soft.prog.dotnetgrains
Отписаться

В избранное