MySqlDataReader: DataTable.Fill(reader) генерирует исключение ConstraintException
У меня две таблицы orders
а также orderdetails
заказы таблицы (PK = id, уникальный индекс по orderno)
|id|orderno|
| 1|1000 |
| 2|1001 |
детализация таблицы (PK = id)
|id|orderid|item|qty|
| 1| 1|ABC | 3|
| 2| 1|XYZ | 4|
Теперь я хочу запросить данные с помощью:
SELECT o.orderno, od.item, od.qty
FROM orders o
ВНУТРЕННЕЕ СОЕДИНЕНИЕ
который возвращает:
|orderno|item|qty|
|1000 |ABC | 3|
|1000 |XYZ | 4|
Однако, если я использую следующий код для загрузки результата в DataTable, он завершается ошибкой:
var connectionString = "Server=localhost;Database=orders;Uid=root;";
var commandText = "SELECT o.orderno, od.item, od.qty" + Environment.NewLine +
"FROM orders o" + Environment.NewLine +
"INNER JOIN orderdetails od ON o.orderno = od.order";
var reader = MySqlHelper.ExecuteReader(connectionString, commandText);
var table = new DataTable("OrdersQuery");
table.Fill(reader); // throws ConstraintException
Проблема в том, что
table.Constraints[0]
это UniqueConstraints
на столбце заказа. Вероятно потому что
reader.GetSchemaTable()
имеет IsUnique=true
запись для orderno (которая истинна в базовой таблице, но не истинна для запроса соединения).
Хуже того, это тоже не помогает:
table.BeginLoadData(); // msdn docs claim that this should disable constraints
table.Load(reader);
table.EndLoadData();
Любые идеи, как это исправить?
Трассировки стека:
System.Data.ConstraintException Was Unhandled.
Message=Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints.
Source=System.Data
StackTrace:
bei System.Data.DataTable.EnableConstraints()
bei System.Data.DataTable.set_EnforceConstraints(Boolean value)
bei System.Data.DataTable.EndLoadData()
bei System.Data.Common.DataAdapter.FillFromReader(DataSet dataset, DataTable datatable, String srcTable, DataReaderContainer dataReader, Int32 startRecord, Int32 maxRecords, DataColumn parentChapterColumn, Object parentChapterValue)
bei System.Data.Common.DataAdapter.Fill(DataTable[] dataTables, IDataReader dataReader, Int32 startRecord, Int32 maxRecords)
bei System.Data.Common.LoadAdapter.FillFromReader(DataTable[] dataTables, IDataReader dataReader, Int32 startRecord, Int32 maxRecords)
bei System.Data.DataTable.Load(IDataReader reader, LoadOption loadOption, FillErrorEventHandler errorHandler)
bei System.Data.DataTable.Load(IDataReader reader)
6 ответов
Я только что понял, что
table.Fill(reader)
не создает ограничение, если я уже добавил столбцы.
Поэтому я исправил это с помощью небольшого метода расширения:
public static void Load(this DataTable table, IDataReader reader, bool createColumns)
{
if (createColumns)
{
table.Columns.Clear();
var schemaTable = reader.GetSchemaTable();
foreach (DataRowView row in schemaTable.DefaultView)
{
var columnName = (string)row["ColumnName"];
var type = (Type)row["DataType"];
table.Columns.Add(columnName, type);
}
}
table.Load(reader);
}
Использование:
table.Fill(reader, true);
У меня была та же проблема, но я исправил ее, используя обходной путь из этого поста: http://bugs.mysql.com/bug.php?id=65065 (внизу):
cmd.CommandText = "SELECT cam.no_serie, t.mnt FROM trx t LEFT JOIN camn cam USING(id_camn) ";
MySqlDataReader dr = cmd.ExecuteReader();
DataSet ds = new DataSet();
DataTable dataTable = new DataTable();
ds.Tables.Add(dataTable);
ds.EnforceConstraints = false;
dataTable.Load(dr);
dr.Close();
Есть простой грязный способ как это исправить - окружить столбец в запросе уникальным ограничением с помощью функции concat:
var commandText = "SELECT CONCAT(o.orderno, ''), od.item, od.qty ...";
У меня была та же ошибка сегодня, и я хочу поделиться. Моя проблема - столбец с типом LONGTEXT. Если я включаю столбец LONGTEXT в свой запрос и пытаюсь загрузить набор данных без указания имен столбцов, исключение выдается. Основываясь на коде SchlaWiener, я переписал код следующим образом, и теперь все в порядке.
MySqlDataReader resultSet = cmd.ExecuteReader();
dt.Columns.Clear();
for (int i = 0; i < resultSet.FieldCount; i++)
{
dt.Columns.Add(resultSet.GetName(i));
}
dt.Load(resultSet);
MySQL допускает множественные нулевые значения в уникальных индексах. Это вызывает ConstraintException при заполнении. Как исправить: найдите это ограничение в списке 'table.Constraints' и удалите его или просто удалите все ограничения.
У меня была похожая проблема с запросами, при загрузке Datatable () с помощью MYSQL Reader он генерировал ошибку NON-NULL, UNIQUE или FOREIGN-KEY.
В конце концов я решил это, изменив версию MySQL Connector.NET.