#c# #linq
#c# #linq
Вопрос:
Я создаю приложение WinForm, при нажатии этой кнопки я собираю таблицы данных из двух баз данных Mysql и Sqlite database. Я получаю ошибку приведения при приведении запроса Linq к IEnumerable для преобразования значений запроса в DataTable для отображения в представлении DataGrid.
private void button1_Click(object sender, EventArgs e)
{
var obj = new table1TableAdapter(); //Mysql Table Adapter
var obj2 = new Table1TableAdapter(); // Sqlite Table Adapter
var ds = new DataSet();
ds.Tables.Add(obj.GetData());
ds.Tables.Add(obj2.GetData());
var tab1 = ds.Tables[0];
var tab2 = ds.Tables[1];
var query = from o in tab1.AsEnumerable()
join od in tab2.AsEnumerable()
on o.Field<string>("Name") equals od.Field<string>("Name")
select new
{
Name = o.Field<string>("Name"),
Rollno = od.Field<Int64>("rollno"),
Book = o.Field<string>("Book")
};
var q2 = (IEnumerable<DataRow>)query; //Unable to cast object of type <JoinIterator>
DataTable orderTable = q2.CopyToDataTable();
dataGridView1.DataSource = orderTable;
}
Комментарии:
1. Это не поток данных, и вы не можете волшебным образом превратить его в
DataRow
Ответ №1:
Глядя на ваш код, я бы сказал, зачем вообще приводить его к IEnumerable<DataRow>
? Просто привяжите запрос к вашему GridView.
dataGridView1.DataSource = query.ToList();
Ответ №2:
Это потому, что возвращаемый вами объект запроса не имеет никакого отношения к DataRow
. query
это будет IEnumerable<SomeAnonymousType> . Как ожидается преобразование в DataRow
?
Вам нужно было бы изменить свой оператор, чтобы создать поток данных:
select new DataRow(/* Whatever Params */) { /* More Params */ };
Тогда это изначально IEnumerable<DataRow>
и не нуждается в приведении.
Ответ №3:
Поскольку ваш запрос создает IEnumerable, вы не смогли бы привести его к потоку данных. Я бы также не советовал использовать select new DataRow(/* Любые параметры /) { / Больше параметров * / }; поскольку это не было бы истинным объектом DataRow и было бы плохой практикой.
Я бы справился с этим таким образом. Даже если это небольшой проект, в вашем обработчике Button_Click не должно быть такого большого количества кода.
Сначала создайте объект-контейнер, назовите его DTO или ViewModel. Я предлагаю позже.
public class BookViewModel
{
public string Name { get; set; }
public Int64 Rollno { get; set; }
public string Book { get; set; }
}
Затем создайте новый класс, который будет выполнять ваши SQL-запросы. Это отделит вашу логику доступа к данным от вашей логики формы.
public class BookService
{
public IList<BookViewModel> GetBookViewModel()
{
var obj = new table1TableAdapter(); //Mysql Table Adapter
var obj2 = new Table1TableAdapter(); // Sqlite Table Adapter
var ds = new DataSet();
ds.Tables.Add(obj.GetData());
ds.Tables.Add(obj2.GetData());
var tab1 = ds.Tables[0];
var tab2 = ds.Tables[1];
var query = from o in tab1.AsEnumerable()
join od in tab2.AsEnumerable()
on o.Field<string>("Name") equals od.Field<string>("Name")
select new BookViewModel
{
Name = o.Field<string>("Name"),
Rollno = od.Field<Int64>("rollno"),
Book = o.Field<string>("Book")
};
return query.ToList();
}
}
Наконец, привяжите список к вашему дисплею.
private void button1_Click(object sender, EventArgs e)
{
BookService bookService = new BookService();
dataGridView1.DataSource = bookService.GetBookViewModel();
}
Теперь, когда вы вернетесь, чтобы внести изменения в свой код, вы легко сможете модифицировать свою логику отображения и без необходимости читать весь ваш смешанный код.
Пример:
private void button1_Click(object sender, EventArgs e)
{
BookService bookService = new BookService();
IList<BookViewModel> books = bookService.GetBookViewModel();
if (books.Count == 0)
{
Label1.Text = "Sorry no books were found";
}
dataGridView1.DataSource = books;
}
Ответ №4:
Во-первых, вы не сможете выполнить приведение к IEnumerable, потому что сам ваш запрос не генерирует потоки данных
select new
{
Name = o.Field<string>("Name"),
Rollno = od.Field<Int64>("rollno"),
Book = o.Field<string>("Book")
};
создает анонимный тип.
Сначала вам пришлось бы каким-то образом изменить это на DataRow, а затем преобразовать его в IEnumerable.
Ответ №5:
Я использую следующую инструкцию, и это работает для меня
UC070_WizardStepFilesDataSet.AllDossierDetailResultsRow[] searchrows =
(from a in _wizardStepPreviewDataSet.AllDossierDetailResults
where a.WingsSetNbr == row.WingsSetNbr amp;amp; !a.BookCode.StartsWith("V")
select a).ToArray<UC070_WizardStepFilesDataSet.AllDossierDetailResultsRow>();