ahmed_sa Ответов: 2

Конкретные приведение является недопустимым в LINQ-запрос для сравнения двух таблиц


Проблема

Отображение ошибки в запросе linq "конкретное приведение недопустимо"

at System.Data.DataRowExtensions.UnboxT`1.ValueField(значение объекта)
в System.Data.DataRowExtensions.Поле[Т](Строкаданных строки, строка, столбец columnname)


LinqQuery выдает ошибку

var query1 = (from x in table1.AsEnumerable()
                          join y in table2.AsEnumerable() on x.Field<int>("UnitCode") equals y.Field<int>("UnitCode")
                          where y.Field<decimal>("CurrentMeterReading") > x.Field<decimal>("CurrentMeterReading")
                          select new { UnitCode = x.Field<int>("UnitCode"), CurrentReading = x.Field<decimal>("CurrentMeterReading") }).ToList();



Подробности

Когда make debug первая таблица данных tableReadingExcelsheet извлекает данные из листа excel .

второй datatable readingfromInvoiceTablesql извлекает данные из таблицы wahinvoice в sql .

Мне нужно получить список строк в листе excel, которые имеют текущее чтение меньше, чем

currentreading в таблице wahinvoice для того же UnitCode затем отображается в datagridview .


private void button2_Click(object sender, EventArgs e)
        {
            DataTable tableReadingExcelsheet = new DataTable();
            tableReadingExcelsheet.Columns.AddRange(new DataColumn[] { new DataColumn("UnitCode", typeof(int)), new DataColumn("CurrentMeterReading", typeof(decimal)) });
            tableReadingExcelsheet = ShowdataFromExcel();
            DataTable readingfromInvoiceTablesql = new DataTable();
            readingfromInvoiceTablesql.Columns.AddRange(new DataColumn[] { new DataColumn("Serial", typeof(int)), new DataColumn("UnitCode", typeof(int)), new DataColumn("CurrentMeterReading", typeof(decimal)) });
            readingfromInvoiceTablesql = GetCurrentReadingUnitCodesql();
            var query1 = (from x in tableReadingExcelsheet.AsEnumerable()
                          join y in readingfromInvoiceTablesql.AsEnumerable() on x.Field<int>("UnitCode") equals y.Field<int>("UnitCode")
                          where y.Field<decimal>("CurrentMeterReading") > x.Field<decimal>("CurrentMeterReading")
                          select new { UnitCode = x.Field<int>("UnitCode"), CurrentReading = x.Field<decimal>("CurrentMeterReading") }).ToList();

            dataGridView1.DataSource = query1;
            dataGridView1.Refresh();

        }
//get data from excel success
public System.Data.DataTable ShowdataFromExcel()
        {
            string connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0 Xml;HDR=YES;IMEX=1\";", txtpath.Text);

            OleDbConnection con = new OleDbConnection(connectionString);


            con.Open();

            string str = @"SELECT  [رقم الاستمارة] as [UnitCode],[قراءة العداد]as[CurrentMeterReading] FROM  [Sheet5$] ";
            OleDbCommand com = new OleDbCommand();
            com = new OleDbCommand(str, con);
            OleDbDataAdapter oledbda = new OleDbDataAdapter();
            oledbda = new OleDbDataAdapter(com);
            DataSet ds = new DataSet();
            ds = new DataSet();
            oledbda.Fill(ds, "[Sheet5$]");
            con.Close();
            System.Data.DataTable dt = new System.Data.DataTable();
            dt = ds.Tables["[Sheet5$]"];
            return dt;


        }
//get data from sql wahinvoice success
public System.Data.DataTable GetCurrentReadingUnitCodesql()
        {
            sqlquery = @"select Serial,UnitCode, CurrentMeterReading
from( select Serial,UnitCode, CurrentMeterReading, ROW_NUMBER() OVER(PARTITION BY UnitCode ORDER BY Serial desc) as rn
from WAHInvoice) as a
where rn = 1";


            System.Data.DataTable tbCurrentReading = DataAccess.ExecuteDataTable(sqlquery);
            return tbCurrentReading;
        }

[^]

Что я уже пробовал:

specific cast is not valid in linq query when compare two tables

2 Ответов

Рейтинг:
0

Richard Deeming

Глядя на ваш снимок экрана, CurrentMeterReading поле-это целое число в одной таблице и число с плавающей запятой в другой.

То Field<T> метод расширения не пытается изменить тип исходного поля. Он просто пытается распаковать его в нужный тип. Если исходный тип точно не соответствует запрошенному типу, он завершится ошибкой с ошибкой InvalidCastException.

NB: Код, который у вас есть, который инициализирует столбцы DataTable не обязательный. Затем созданные таблицы немедленно выбрасываются и заменяются таблицами, загруженными из базы данных и файла Excel.

Вам нужно будет отладить свой код, чтобы выяснить, каковы фактические типы полей. В качестве альтернативы используйте Convert.ToDecimal чтобы попытаться изменить тип:

where Convert.ToDecimal(y["CurrentMeterReading"] > Convert.ToDecimal(x["CurrentMeterReading"])
select new { UnitCode = x.Field<int>("UnitCode"), CurrentReading = Convert.ToDecimal(x["CurrentMeterReading"]) })


Maciej Los

5ed!

Рейтинг:
0

Maciej Los

С помощью IMEX=1 in connection string - по общему признанию - позволяет избежать сбоев в процессе извлечения данных для смешанных столбцов данных, но это приводит к тому, что поставщик OledDb обрабатывает данные как текст. Более подробную информацию вы найдете здесь: Строки подключения Microsoft ACE OLEDB 12.0 - ConnectionStrings.com[^]

Я бы удалил эту часть из строки подключения и попробовал ваш код снова. Примечание: не забудьте изменить каждый отдельный столбец в файле Excel с General к определенному типу данных.

Еще один способ обойти это-привести/преобразовать данные в SELECT заявление. Видеть: Функции Преобразования Типов - Доступ[^]:

SELECT CDbl(CurrentMeterReading) AS CurrentMeterReading, CDbl(CurrentMeterReading) AS CurrentMeterReading
FROM [Sheet1$];


Удачи вам!