MySqlDataReader: DataTable.Fill(reader) throws ConstraintException
我有两个表
表订单(PK = id,orderno上的UNIQUE索引)
1 2 3 | |id|orderno| | 1|1000 | | 2|1001 | |
表顺序详细信息(PK = ID)
1 2 3 | |id|orderid|item|qty| | 1| 1|ABC | 3| | 2| 1|XYZ | 4| |
现在我想用以下查询数据:
1 2 | SELECT o.orderno, od.item, od.qty FROM orders o |
内部联接订单详细信息od ON o.orderno = od.order
返回:
1 2 3 | |orderno|item|qty| |1000 |ABC | 3| |1000 |XYZ | 4| |
但是,如果我使用以下代码将结果加载到DataTable中,它将失败:
1 2 3 4 5 6 7 8 | 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 |
问题是
1 | table.Constraints[0] |
是orderno列上的
1 | reader.GetSchemaTable() |
对orderno有一个
更糟糕的是,这也无济于事:
1 2 3 | table.BeginLoadData(); // msdn docs claim that this should disable constraints table.Load(reader); table.EndLoadData(); |
任何想法如何解决这一问题?
堆栈跟踪:
1 2 3 4 5 6 7 8 9 10 11 12 | 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) |
我遇到了同样的问题,但是通过使用以下文章中的解决方法进行了修复:http://bugs.mysql.com/bug.php?id=65065(底部):
1 2 3 4 5 6 7 8 |
我才知道
1 | table.Fill(reader) |
如果我已经添加了列,则不会创建约束。
因此,我使用了一个不错的扩展方法来解决此问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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); } |
用法:
1 | table.Fill(reader, true); |
今天我遇到了同样的错误,想分享。我的问题是一个LONGTEXT类型的列。如果我在查询中包含LONGTEXT列并尝试加载数据集而不指定列名,则会引发异常。根据SchlaWiener的代码,我将代码重写如下,现在一切都很好。
1 2 3 4 5 6 7 | MySqlDataReader resultSet = cmd.ExecuteReader(); dt.Columns.Clear(); for (int i = 0; i < resultSet.FieldCount; i++) { dt.Columns.Add(resultSet.GetName(i)); } dt.Load(resultSet); |
有一个简单的肮脏方法如何解决它-使用concat函数在具有唯一约束的查询中包围列:
1 | var commandText ="SELECT CONCAT(o.orderno, ''), od.item, od.qty ..."; |
我在查询中遇到了类似的问题,当使用MYSQL Reader加载Datatable()时,它会生成错误NON-NULL,UNIQUE或FOREIGN-KEY。
最后,我通过更改MySQL Connector.NET版本解决了它。
https://dev.mysql.com/downloads/connector/net/
MySQL在唯一索引中允许多个空值。这将导致ConstraintException填充。解决方法:在" table.Constraints"列表中找到此约束,然后将其删除或清除所有约束。