Рассылка закрыта
При закрытии подписчики были переданы в рассылку "BloggLand и Я | Блоггландия" на которую и рекомендуем вам подписаться.
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
№43 рассылки '.Net Собеседник':
Информационный Канал Subscribe.Ru |
.Net Собеседник #43
Содержание- От автора
- Обзор новостей
- Загрузка/скачивание изображений на/с SQL Server
- Время кода - Запускаем нити с параметрами на C#
- Форумы .Net на www.sql.ru
От автора
Здравствуйте, коллеги!
Также не за горами выпуск третьего номера журнала Алгоритм, это будет последний выпуск полностью выложенный в Сеть. Следующие номера будут выложены в Сеть в урезанном виде.
По-прежнему регулярно обновляется мой блог.
На этом всё- желаю интересного чтения.
Обзор новостей
-
Вышел Portable.NET
0.7.0
- Portable.NET – набор инструментов, разработанный для построения и запуска веб-сервисов и приложений .NET.
-
Вышли Genuine Channels
v.2.5.0
- GenuineChannels.com объявили о выходе версии 2.5 .NET пакета работы с удалёнными клиентами, находящимися за NAT, файерволлами и прокси-серверами. Используя пакет Genuine Channels, клиенты могут определить, что сервер перестартовал, задействовать расширенные настройки при хостинге, использовать сжатие, шифрование и поддержку SSPI, а также использовать упрощённую разработку событий и многоадресную передачу IP-пакетов.
-
Вышла экстремально
оптимизированная математическая библиотека Extreme Optimization Mathematics
Library для .NET v1.1
- Extreme Optimization выпустила версию 1.1 библиотеки Extreme Optimization Mathematics Library для .NET. Новая версия поддерживает кубические сплайны, линейную интерполяцию, модифицированные функции Бесселя и т.п.
-
Вышел конвертор VB.Net на
C# 1.3
- В новой версии 1.3 улучшена аккуратность конвертации, онлайновая помощь, появилась версия для командной строки для пакетных конвертаций. Конвертор от VBConversions VB.Net на C# может конвертировать индивидуальные проекты, фрагменты кода и даже группы проектов в случае необходимости массовой конвертации.
-
Вышла Dingo 1.1.3
- В Dingo 1.1.3 были устранены несколько ошибок, а также улучшена поддержка xs:group и groupAttribute. В этом выпуске добавлен новый исполняемый файл Jingo, который может генерировать код на Java. Это значит, что Dingo теперь поддерживает C# и Java.
-
Используйте MSFT Office для разработки и распространения отчётов
- SoftArtisans выпустила 3 версию OfficeWriter .NET приложения для Excel и Word, обладающую улучшенной поддержкой Reporting Services. Пользователи могут создавать и распространять свои отчёты – используя сводные таблицы, VBA, макросы, формулы – не имея на машине Microsoft Office.
-
Реализуем автоподстройку ширины в таблице
- Автоподстройка ширины – полезная вещь, если вы работаете с таблицами, набор методов и свойств элемента управления TX Text Control содержит всё, что необходимо для реализации такой функциональности. Я закончил полнофункциональный пример, который покажет вам как можно реализовать with автоподстройку ширины с помощью ЭУ TX Text Control.NET.
-
Импорт данных из листа Excel
- Иногда возникает необходимость слияния данных из различных источников, включая данные из листов Microsoft Excel в один документ. Я предлагаю вам взглянуть на приложение, которое импортирует данные из Microsoft Excel в таблицу TX Text Control.
-
Вышел
Aspose.Word 2.5
- Aspose.Word - компонент для создания отчётов в формате Word, который позволяет вам читать и писать документы Word без использования Microsoft Word.
-
Разработчикам нравится Spices.NET
- Spices.NET, среда для построения современных графических интерфейсов пользователя для разработчиков на платформе .NET получила престижную награду MSD2D People’s Choice 2005 Award в категории инструменты кодирования, которая считается аналогом Оскара в индустрии.
-
Вышел
ExcelLite 1.4
- Легко создавать, конвертировать, читать и писать файлы в формате Microsoft Excel (как XLS, так и CSV), используя этот, на 100% управляемый, компонент.
Статья номера
Загрузка/скачивание изображений на/с SQL Server
ЯЗЫК: C#
Автор статьи: Alexandru Ghiondea
ПЕРЕВОД: Чужа В.Ф. ака hDrummer
КОД К СТАТЬЕ:
Демо проект 19КБ,
Скрипт к БД 1КБ
Вступление
Для того, чтобы снабдить ваше приложение классными картинками, вы можете использовать как минимум два способа. Один из них – можно сохранять картинки в папку, а затем записывать пути к ним в базу данных (БД). Другой – записывать весь файл, вместе с именем, в БД. У каждого способа есть свои плюсы и минусы:
- Можно случайно удалить файл, если он будет храниться в папке. Если такое происходит, то в БД или вашем конфигурационном файле будет храниться неправильная ссылка. Однако, пространство на жестком диске дешевеет и вы можете хранить на диске много файлов.
- Если же хранить файлы в БД, то можно использовать настройки безопасности, используемые в ней. Также не будет неправильных ссылок. Однако, нужно помнить о том, что пространство в хранилищах БД намного более дорого.
Приложение
Задача загрузки файла в БД достаточно проста. При создании таблицы на сервере необходимо использовать определенный тип данных. Этот тип должен уметь хранить большие объёмы двоичных данных. При использовании Microsoft SQL Server этот тип данных называется image. Чтобы узнать больше, см. BLOB (Binary Large OBject) – там есть определение, а в Books Online есть подробное описание. Клиент должен получить данные из файла в двоичном формате – в виде массива байт – и вызвать процедуру на сервере с параметром-массивом.
Процедуры SQL Server’a
Здесь будем считать, что у нас есть БД Pictures на сервере, в которой есть таблица Pictures. Структура этой таблицы такова:
Имя поля | Тип поля |
kFileName | Long |
Picture | Image |
FileName | Varchar(250) |
У меня также есть хранимые процедуры (ХП) для загрузки, скачивания и лов. Они приведены ниже.
Для закачки файла UploadFile:
CREATE PROCEDURE [dbo].[UploadFile] ( @Picture image, @FileName varchar(250), @kFileName bigint output ) AS insert into Pictures(Picture, FileName) values (@Picture,@FileName) select @kFileName = SCOPE_IDENTITY() GO |
Для скачивания файла DownloadFile:
CREATE PROCEDURE [dbo].[DownloadFile] ( @kFileName bigint, @FileName varchar(250) output ) AS select Picture, FileName from Pictures where kFileName=@kFileName GO |
Для получения списка закачанных файлов getUploadedFiles:
CREATE PROCEDURE [dbo].[getUploadedFiles]AS Select ltrim(str(kFileName)) + " - " + FileName as Name from Pictures GO |
Класс на C# - с комментариями
using System; using System.IO; using System.Data; using System.Text; using System.Data.SqlClient; //Autor: Ghiondea Alexandru //Date: 08 october 2004 // Описание: Содержит методы для закачки и скачки файлов // с MS SQL Server // namespace PicturesInSQLServer { /// /// Этот класс управляет закачкой и скачкой файлов /// public class TransferPictures { /// /// Получаем список закачанных файлов в dataSet /// /// /// public void GetUploadedFiles(ref DataSet ds, string table) { // // Переменные для соединения с сервером. // SqlConnection conn =null; SqlCommand cmd = null; SqlDataAdapter da = null; // ---------------------------------------------- try { // // Если таблица уже существует, то очищаем её, иначе – //добавляем новую. // if (ds.Tables.Contains(table)) ds.Tables[table].Clear(); else ds.Tables.Add(table); // ---------------------------------------------- // // Создаём соединение к БД и инициализируем команду // conn = new SqlConnection(ConnectionString()); cmd = new SqlCommand("getUploadedFiles",conn); cmd.CommandType = CommandType.StoredProcedure; // ---------------------------------------------- da = new SqlDataAdapter(cmd); // // Открываем соединение и заполняем dataset // conn.Open(); da.Fill(ds,table); conn.Close(); // ---------------------------------------------- } catch(Exception e) { // // Если происходит ошибка, то мы присваиваем null результату // и отображаем ошибку пользователю // с информацией о StackTrace для целей отладки. // Console.WriteLine(e.Message + " - " + e.StackTrace); } } /// /// Загружаем файл на сервер. /// /// public long UploadFile(string FileName) { if (!File.Exists(FileName)) { return -1; } FileStream fs=null; try { #region Reading file fs = new FileStream(FileName,FileMode.Open); // // Размер закачиваемого файла // FileInfo fi = new FileInfo(FileName); long temp = fi.Length; int lung = Convert.ToInt32(temp); // ------------------------------------------ // // Считываем содержимое файла в массив байт. // byte[] picture=new byte[lung]; fs.Read(picture,0,lung); fs.Close(); // ------------------------------------------ #endregion long result = uploadFileToDatabase(picture,fi.Name); return result; } catch(Exception e) { Console.WriteLine(e.Message + " - " + e.StackTrace); return -1; } } /// /// Обёртка для скачки файла из БД. /// /// /// /// { byte[] result =downloadFileFromDatabase(kFileName, ref fileName); return result; } /// /// Возвращает строку соединения для соединения с БД /// /// public static string ConnectionString() { // // Считаем, что БД на той же машине, где запущена программа // Для подсоединения к удаленному серверу впишите в // 'Data Source' имя этого сервера return "Connect Timeout=600;Integrated Security=SSPI;" + "Persist Security Info=False;Initial Catalog=Pictures;" + "Packet Size=4096;Data Source=" + System.Environment.MachineName.Trim(); } /// /// Загрузка файла на SQL Server. /// /// /// /// /// при возникновении ошибки. private long uploadFileToDatabase(byte[] picture, string fileName) { SqlConnection conn = null; SqlCommand cmd =null; SqlParameter kFileName =null; SqlParameter FileName =null; SqlParameter pic =null; // По умолчанию мы считаем, что произошла ошибка. Иначе //меняем значение на уникальное id файла long result=-1; try { // // Соединяемся с БД. // conn = new SqlConnection(ConnectionString()); cmd = new SqlCommand("UploadFile",conn); // Предполагаем, что есть ХП с именем UploadFile cmd.CommandType = System.Data.CommandType.StoredProcedure; // ---------------------------------------------- // Инициализируем параметры и присваиваем значения // перед отсылкой их на сервер // kFileName = new SqlParameter("@kFileName", System.Data.SqlDbType.BigInt,8); kFileName.Direction = ParameterDirection.Output; // Этот параметр не имеет размера, поскольку // мы его не знаем. pic = new SqlParameter("@picture",SqlDbType.Image); pic.Value = picture; FileName = new SqlParameter("@FileName",SqlDbType.VarChar,250); FileName.Value = fileName; // ---------------------------------------------- // Добавляем параметры. // Помните, что порядок добавления // ОЧЕНЬ важен! cmd.Parameters.Add(pic); cmd.Parameters.Add(FileName); cmd.Parameters.Add(kFileName); // ---------------------------------------------- // Oткрываем соединение и выполняем команды. // conn.Open(); cmd.ExecuteNonQuery(); conn.Close(); // ---------------------------------------------- // В результате получаем уникальный идентификатор созданный ///в БД. // result = (long)kFileName.Value; // ---------------------------------------------- // Убираем объекты из памяти. // conn.Dispose(); cmd.Dispose(); // ---------------------------------------------- } catch(Exception e) { Console.WriteLine(e.Message + " - " + e.StackTrace); result = -1; // ---------------------------------------------- } return result; } /// /// Скачиваем файл из БД // согласно уникальному id в БД. /// /// /// /// private byte[] downloadFileFromDatabase(long kFile, ref string FileName) { SqlConnection conn =null; SqlCommand cmd = null; SqlParameter kFileName = null; SqlParameter fileName = null; SqlDataReader dr=null; byte[] result=null; try { conn = new SqlConnection(ConnectionString()); cmd = new SqlCommand("DownloadFile",conn); cmd.CommandType = System.Data.CommandType.StoredProcedure; // ---------------------------------------------- // Инициализируем параметры для отсылки на сервер // kFileName= new SqlParameter("@kFileName",System.Data.SqlDbType.BigInt,8); kFileName.Value = kFile; fileName = new SqlParameter("@FileName",SqlDbType.VarChar,250); fileName.Direction = ParameterDirection.Output; // ---------------------------------------------- // Добавляем параметры к БД. // Помните, что порядок добавления очень важен! cmd.Parameters.Add(kFileName); cmd.Parameters.Add(fileName); // ---------------------------------------------- // Используем dataReader для считывания одной записи и //возвращения значения в виде поля image conn.Open(); dr = cmd.ExecuteReader(); dr.Read(); // // Приводим значение // к типу byte[] // result = (byte[])dr.GetValue(0); // // Также возвращаем значение имени файла, ассоциированное с //массивом байт. FileName = (string)dr.GetValue(1); // // Закрываем datareader и соединение // dr.Close(); conn.Close(); // // И снова зачем-то вызываем методы Dispose ;) // conn.Dispose(); cmd.Dispose(); // ------------------------------------------ } catch(Exception e) { Console.WriteLine(e.Message + " - " + e.StackTrace); result = null; } return result; } } } |
Простое приложение
Я также написал небольшое приложение для демонстрации использования этих методов. Приложение загружает файл на сервер и отображает список файл на сервере. щёлкнув два раза на имени файла в списке, мы производим скачивание файла и отображаем его в специальном окне. Ниже – некоторые интересные фрагменты кода:
private void UploadedFiles_DoubleClick(object
sender, System.EventArgs e) { // Ищем уникальный id файла. DataRowView drv = (DataRowView) UploadedFiles.SelectedItem; string selectedText = drv.Row["Name"].ToString(); long id=-1; id = long.Parse(selectedText.Substring(0,selectedText.IndexOf(" - ",0)).Trim()); string filename=null; TransferPictures up = new TransferPictures(); byte[] result = up.DownloadFile(id,ref filename); up = null; try { // // Мы не можем напрямую присвоить массив байт image. // Мы используем MemoryStream, объект, который создаёт файл //в памяти // a потом мы передаём его для отображения // MemoryStream ms= new MemoryStream(result,0,result.Length); Image im = Image.FromStream(ms); Picture.Image = im; } catch(Exception ee) { MessageBox.Show("Произошла ошибка.\n" + ee.Message); } } private void UploadFile_Click(object sender, System.EventArgs e) { // // Получаем файл для загрузки на сервер // OpenFileDialog ofd = new OpenFileDialog(); ofd.ShowDialog(); if (ofd.FileName=="" || !File.Exists(ofd.FileName)) { // // Если с запрошенным файлом не всё в порядке // return; } TransferPictures up = new TransferPictures(); long id =up.UploadFile(ofd.FileName); string msg=null; if (id >0) { msg = "Загрузка успешна"; LoadInformationFromDataBase(); } else { msg = "Произошла ошибка"; } MessageBox.Show(msg); } private void LoadInformationFromDataBase() { TransferPictures up = new TransferPictures(); up.GetUploadedFiles(ref ds,"Pictures"); UploadedFiles.DataSource = ds.Tables["Pictures"]; UploadedFiles.DisplayMember = "Name"; } private void frmMain_Load(object sender, System.EventArgs e) { LoadInformationFromDataBase(); } |
Выводы
Итак, выбор техники хранения файла за вами. Я попробовал показать вам, как хранить их в БД. Удачного кодирования!
Время кода
Запускаем нити с параметрами на C#
ЯЗЫК: C#
Автор статьи: ?
ПЕРЕВОД: Чужа В.Ф. ака hDrummer
Вступление
В новостных группах по языку C# многие люди спрашивают, каким образом можно передать параметры в новую нить. Другими словами, если новая нить нуждается в специфической информации для запуска (как это обычно бывает), как поместить такую информацию в эту нить? Делегат ThreadStart не принимает параметров. Т.е. информацию нужно сохранить где-то еще. Обычно это приводит к созданию нового объекта класса и использованию его для хранения этой информации. Например, нам нужна программа, которая будет получать и обрабатывать содержимое нескольких URL, причём должна она делать это в фоновом режиме. Для этого можно написать такой код:
public class
UrlFetcher { private string url public UrlFetcher (string url) { this.url = url; } public void Fetch() { // здесь используем url } } //[... в другом классе ...] UrlFetcher fetcher = new UrlFetcher (myUrl); new Thread (new ThreadStart (fetcher.Fetch)).Start(); |
Иногда вам необходимо просто вызвать метод в некотором классе (возможно в том, который сейчас выполняется) со специфичным параметром. В этом случае, вы можете использовать вложенный класс, чьё предназначение – всего лишь выполнить этот вызов, состояние хранится в этом же классе, а делегат, стартовавший нить, всего лишь вызывает «настоящий» метод с соответствующим параметром.
Используем ThreadPool
При запуске новой нити вы всегда должны помнить о том, что, возможно, более
выгодно будет использовать ThreadPool, который обработает нити для вас и
поместит их в очередь, если пул полон. ThreadPool – прекрасный выбор для тех
задач, которые часто выполняются и занимают мало времени – просто потому, что
не приходится пересоздавать и уничтожать нити.
// этот метод можно использовать в коде где угодно public void Fetch (string url) { this.url = url; } // этот метод можно использовать в качестве делегата для WaitCallback для помещения в очередь пула private void Fetch(object url) { Fetch ((string) url); } // а вызывается он так: ThreadPool.QueueUserWorkItem (new WaitCallback (Fetch), myUrl); |
Асинхронный вызов делегата
Альтернативой (которая тоже неявно использует пул нитей) является асинхронный вызов делегата. У него есть преимущество в том, что можно передать больше одного параметра в метод делегата, а также в том, что их можно проверить на соответствие типов во время компиляции. Это возможно благодаря компилятору C#, добавляющего пару методов к типу делегата: BeginInvoke и EndInvoke. Метод BeginInvoke всегда принимает те параметры, которые принимает делегат, вместе с параметром AsyncCallback и параметром типа object в качестве состояния. Он возвращает ссылку IAsyncResult. При вызове BeginInvoke, сущность помещается в рабочую очередь пула нитей и в то время как она выполняется, вызывается делегат со специфическими параметрами. Когда делегат завершает работу, вызывается параметр делегата AsyncCallback, возвращающий ссылку на IAsyncResult. Ссылка может быть использована для нахождения оригинального параметра состояния, самого делегата, значения, возвращенного после операции через делегат и т.п. Заметьте, что для отыскания оригинального делегата вам нужно привести ссылку типа IAsyncResult к AsyncResult. Я не уверен почему именно так спроектирован каркас .Net, но если вы не хотите использовать приведение типов, тогда можно использовать делегат как свой собственный параметр состояния. Метод EndInvoke берёт только IAsyncResult, и возвращает тот же тип, что и сам делегат. Вот и полный пример:
using System; using System.Threading; using System.Runtime.Remoting.Messaging; class AsyncTest { delegate string UrlFetcher(string url); public static void Main() { UrlFetcher u = new UrlFetcher (Fetch); u.BeginInvoke ("some url", new AsyncCallback (AfterFetch), "this is state"); // Просто покажем что происходит при // вызове fetch for (int i= 0;i < 10; i++) { Console.WriteLine ("Счётчик нитей: {0}", i); Thread.Sleep(1000); } } static string Fetch (string url) { // Симулируем задержку Thread.Sleep (5000); return "Содержимое url"; } static void AfterFetch (IAsyncResult result) { Console.WriteLine ("Делегат отработал."); Console.WriteLine (" Состояние: {0}", result.AsyncState); AsyncResult async = (AsyncResult) result; UrlFetcher fetcher = (UrlFetcher) async.AsyncDelegate; Console.WriteLine (" Содержимое: {0}", fetcher.EndInvoke(result)); } } |
Вот вывод на экран вышеприведенного кода:
Счётчик нитей: 0 Счётчик нитей: 1 Счётчик нитей: 2 Счётчик нитей: 3 Счётчик нитей: 4 Делегат отработал. Состояние: this is state Содержимое: Coдержимое url Счётчик нитей: 5 Счётчик нитей: 6 Счётчик нитей: 7 Счётчик нитей: 8 Счётчик нитей: 9 |
Смотрите MSDN по операциям BeginRead и EndRead класса System.IO.Stream - там
много примеров того, как работают асинхронные вызовы.
Решения будущего: анонимные методы
Анонимные методы – одно из будущих улучшений C#. Они помогут вам специфицировать блоки кода как методы внутри других методов и использовать эти методы как делегаты. Вы можете получить доступ к переменным (включая локальные переменные и параметры «внешнего» метода) внутри анонимного метода. Например, использование анонимного метода для обработки URL с использованием нормального делегата ThreadStart:
ThreadStart starter = new ThreadStart() { Fetch (myUrl); }; new Thread(starter).Start(); |
Всё это можно выполнить за один шаг, создав сразу нить и делегат одной строкой кода, но я думаю что вышеприведенный код более читаем. Вот похожий код использующий WaitCallback и помещающий задание в очередь пула ThreadPool:
WaitCallback callback = new WaitCallback (state) { Fetch ((string)state); }; ThreadPool.QueueUserWorkItem (callback, myUrl); |
Заметьте, как выполнено объявление. Подход, конечно, может измениться в финальной реализации. Больше узнать об анонимных методах можно на странице Microsoft C# - будущие особенности языка.
{К содержанию}
Форумы .Net - вопросы оставшиеся без ответа
Donwload
Visual Studio
Поиск
Прога
говорит что у InteropServices закончилась лицензия
Массив
в хранимую процедуру Oracle
varbinary
Почему
не подключается ado.net
Display
related data (many-to-many)
OWC
PivotTable
На этом сорок третий выпуск .Net Собеседника закончен.
До следующего номера.
Чужа Виталий Ф. aka hDrummer, MCAD, MCDBA, MCP
hdrummer ухо gmail точка ru - жду ваши предложения и замечания.
Subscribe.Ru
Поддержка подписчиков Другие рассылки этой тематики Другие рассылки этого автора |
Подписан адрес:
Код этой рассылки: comp.soft.prog.dotnetgrains |
Отписаться
Вспомнить пароль |
В избранное | ||