Есть метод он получает данные из базы, сохраняет их в Datatable и еще я через linq делаю отбор нужного мне количества строк. Но возникает ошибка, делать еще один метод как о не эффективно. Где я не прав.
public Task <DataTable> GetDataFromBase(string _connectionString, string qwery,int? _stringout)
{
Task<DataTable> rezulTable = null;
string connectionString = _connectionString;
try
{
using (SqlConnection connection = new SqlConnection(connectionString))
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
}
catch (Exception e)
{
MessageBox.Show("Ошибка соединения "+e);
throw;
}
var dt = new DataTable();
//получаем результат запроса в DataTable...
using (var adapter = new System.Data.SqlClient.SqlDataAdapter(qwery, connectionString))
{
adapter.Fill(dt);
}
// выбираем количество записей
if (_stringout!=null&&_stringout!=0)// проверяем, что строка не пустая, и не равна 0
{
int countRows=(int)_stringout;
var t = dt.AsEnumerable().Take(countRows);
// вот тут ошибка
rezulTable = t.CopyToDataTable();
}
else
{
rezulTable=dt;
}
return rezulTable;
}
У вас в коде определена переменная rezulTable
типа Task<DataTable>
. А далее вы пытаетесь присвоить ей значение типа DataTable
:
var dt = new DataTable();
...
rezulTable = t.CopyToDataTable();
...
rezulTable = dt;
Чтобы ошибка исчезла можно использовать метод Task.FromResult:
rezulTable = Task.FromResult(t.CopyToDataTable());
...
rezulTable = Task.FromResult(dt);
Однако, в данном случае это не имеет большого смысла, т. к. ваш код принципиально синхронный. Нужно просто возвращать DataTable
, изменив сигнатуру метода:
public DataTable GetDataFromBase(...)
{
var resultTable = new DataTable();
...
return resultTable;
}
Вероятно, у вас возникли проблемы с долгим выполнением этого метода (обращение к БД, загрузка данных), из-за чего, например, подмерзает GUI.
Что можно предпринять?
Первый вариант: запустить внутри метода отдельный поток (задачу) и вернуть её.
public Task<DataTable> GetDataFromBase(...)
{
return Task.Run(() =>
{
Task<DataTable> resultTable = null;
...
return resultTable;
});
}
После чего вызывать этот метод следует с async
:
await GetDataFromBase(...);
Но такой способ не рекомендуется: Task.Run Etiquette. (Хотя здесь автор статьи сам использует такой способ - как после этого верить людям?..) Оставьте метод синхронным, а Task.Run
используйте там, где вызываете этот метод.
Другой вариант. Сделаем метод действительно асинхронным. Дело в том, что запуск отдельного потока/задачи следут использовать только для CPU-bound нагрузки, т. е. когда именно процессор занят длительными вычислениями. А у вас идёт IO-bound нагрузка: долго выполняются запросы к БД.
Обший шаблон метода будет выглядеть примерно так:
public async Task<DataTable> GetDataFromBaseAsync(string connectionString, string query)
{
using (var connection = new SqlConnection(connectionString))
{
await connection.OpenAsync();
using (var cmd = new SqlCommand(query, connection))
using (var reader = await cmd.ExecuteReaderAsync().ConfigureAwait(false))
{
var resultTable = new DataTable();
// здесь должен быть код создания колонок в DataTable
// ...
while (await reader.ReadAsync().ConfigureAwait(false))
{
var dataRow = resultTable.NewRow();
for (int i = 0; i < resultTable.Columns.Count; i++)
{
dataRow[i] = reader[i];
}
resultTable.Rows.Add(dataRow);
}
return resultTable;
}
}
}
И вот ещё что. Вы выбираете заданное количество строк уже на клиенте (с помощью параметра _stringout
) - это неэффективно. Это нужно делать непосредственно в sql-запросе (используя ключевое слово TOP
или LIMIT
в зависимости от диалекта).
Примечание: у nullable-типов есть свойства HasValue и Value - научитесь их использовать.
Перед написанием ответа я поискал решения асинхронного заполнения дататейбла. Я разочарован. Часто предлагается использовать Task.Run
. Иногда асинхронно создаётся DataReader
, а далее загрузка данных выполняется простым вызовом dataTable.Load(reader)
- то есть синхронно. И такие ответы приняты и заплюсованы. Моя в печали...
Нормальное решение находится по этой ссылке (её уже приводили в комментариях).
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Какие существуют виды рекламных бордов и как выбрать подходящий?
Я не думаю что сложно, моя цель сделать этот файл "портативным", или что-то в этом смысле, можно ли как то его встроить в выходной исполняемый...
Пытаюсь разобраться с UNet, но что-то не до конца понимаюЯ проверяю, клиент ли игрок, и если да, то запускаю клиентскую версию функции, описанной...
В приложении есть экраны, унаследованные от ContentPageЕсть ли какие-то способы представить эти экраны в виде изображений либо PDF-файлов или страниц?...