отображение прогресса при выполнении запроса
собственно есть метод, в котором выполняется запрос для "перегонки" файлов с одной базы в другую. Файлов много, программа подвисает и хочется чтобы отображался прогресс выполнения.
Такой метод:
private void TransferFiles()
{
using (SqlConnection conn = new SqlConnection(ConnectionString.Value))
{
try
{
conn.Open();
string fullPath = System.Reflection.Assembly.GetAssembly(typeof(Form1)).Location; // Получаем полное местоположение exe файла сборки
string theDirectory = Path.GetDirectoryName(fullPath); // Получаем папку в котором он находится
DataTable dt = new DataTable();
string queryOpen = String.Format("select top {7} t1.id, t1.{0}, t2.{1} " +
"from {2}.dbo.{3} t1 " +
"left join {4}.dbo.{5} t2 on t1.id = t2.{6}",
ConnectionString.DoVarchar, colNameImageCmb.Text, ConnectionString.InitialCatalog, ConnectionString.TableNameText,
initialCatalogTxb.Text, tableNameCmb.Text, fieldCommunicationCmb.Text, numericNumberOfLines.Value);
if (!String.IsNullOrEmpty(tableNameCmb.Text) && !String.IsNullOrEmpty(colNameImageCmb.Text) && !String.IsNullOrEmpty(fieldCommunicationCmb.Text))
{
SqlCommand command = new SqlCommand(queryOpen, conn);
SqlDataReader reader = command.ExecuteReader();
dt.Load(reader);
reader.Close();
foreach (var item in dt.Select())
{
int fileId = (int)item["id"];
string fileName = (string)item[ConnectionString.DoVarchar];
byte[] fileContent = (byte[])item[colNameImageCmb.Text];
using (FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate))
{
fs.Write(fileContent, 0, fileContent.Length);
}
string queryLoad = String.Format("UPDATE {0} SET \"{1}\" = (SELECT * FROM OPENROWSET(BULK '{4}\\{2}', SINGLE_BLOB) AS x), " +
"{5} = (GetDate()) where \"id\" = {3}",
ConnectionString.TableNameText, ConnectionString.Filestream, fileName, fileId, theDirectory, ConnectionString.Datetime);
command = new SqlCommand(queryLoad, conn);
command.ExecuteNonQuery();
}
}
else
MessageBox.Show("Выберите все поля!");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
добавил прогресс и backgroundworker
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i <= 100; i++)
{
Thread.Sleep(10);
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.ReportProgress(i);
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
circularProgressBar1.Value = e.ProgressPercentage;
progressLbl.Text = e.ProgressPercentage.ToString() + "%";
if (progressLbl.Text == "100%")
{
MessageBox.Show("Копирование успешно завершено!");
}
}
вылетает ошибка и обрывается выполнение запроса
но прогресс выполняется до 100%. Подскажите где ошибаюсь.
Ответы (1 шт):
Автор решения: Bulson
→ Ссылка
Надо бы использовать async/await. Вот небольшой пример как это делается.
public partial class FormMain : Form
{
private const string _conString = @"Data Source=(localdb)\MSSQLLocalDB;" +
"Initial Catalog=AdventureWorks2016;Integrated Security=True;" +
"Connect Timeout=60;Encrypt=False;TrustServerCertificate=False;" +
"ApplicationIntent=ReadWrite;MultiSubnetFailover=False";
public FormMain()
{
InitializeComponent();
_buttonSelectFile.Click += ButtonSelectFile_Click;
_buttonSave.Click += ButtonSave_Click;
}
private void ButtonSelectFile_Click(object sender, EventArgs e)
{
if (_saveFileDialog.ShowDialog() != DialogResult.OK)
return;
_textBoxFile.Text = _saveFileDialog.FileName;
}
private async void ButtonSave_Click(object sender, EventArgs e)
{
var file = _textBoxFile.Text;
if (String.IsNullOrEmpty(file))
return;
//кнопки
_buttonSave.Enabled = false;
_buttonSelectFile.Enabled = false;
//колбек отображения процесса записи в файл
IProgress<int> progress = new Progress<int>(value =>
{
_progressBar.Value = value;
_labelProc.Text = $"{value}%";
_labelProc.Update();
});
try
{
await SaveTableAsync(progress, file);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
//кнопки
_buttonSave.Enabled = true;
_buttonSelectFile.Enabled = true;
}
}
private async Task SaveTableAsync(IProgress<int> progress, string file)
{
//двусоставный запрос к БД
var request = @"SELECT COUNT(AddressID)
FROM[AdventureWorks2016].[Person].[Address];
SELECT AddressLine1
FROM[AdventureWorks2016].[Person].[Address]";
using (var con = new SqlConnection(_conString))
using (var cmd = con.CreateCommand())
{
cmd.CommandText = request;
await con.OpenAsync();
using (var reader = await cmd.ExecuteReaderAsync())
{
//получаем количество записей в таблице
int countRecords = 0;
if (reader.HasRows)
{
await reader.ReadAsync();
countRecords = reader.GetInt32(0);
}
//если есть данные по второй части запроса
if (await reader.NextResultAsync())
{
//открываем файл на запись
using (var fs = File.OpenWrite(file))
{
//текущая запись (строка) в таблице
int currentRecord = 0;
//пока есть записи в таблице
while (await reader.ReadAsync())
{
//получаем столбец
var column = reader.GetString(0);
var bytes = Encoding.UTF8.GetBytes(column);
//пишем в файл
await fs.WriteAsync(bytes, 0, bytes.Length);
//вычисляем процент записанных записей
var percent = ++currentRecord * 100 / countRecords;
//обновляем прогрессбар и лейбл
progress?.Report(percent);
}
}
}
}
}
}
}
Пример целиком здесь.

