我有两张表orders
和orderdetails
表订单(PK = id,orderno上的UNIQUE索引)
|id|orderno|
| 1|1000 |
| 2|1001 |
表orderdetails(PK = id)
|id|orderid|item|qty|
| 1| 1|ABC | 3|
| 2| 1|XYZ | 4|
现在我想用以下方式查询数据:
SELECT o.orderno, od.item, od.qty
FROM orders o
INNER JOIN orderdetails od ON.orderno = od.order
返回:
|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]
是orderno列上的UniqueConstraints
。可能是因为
reader.GetSchemaTable()
对于orderno有一个IsUnique=true
条目(在基表中为true,但对于连接查询不是true)。
更糟糕的是,这也无济于事:
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)
答案 0 :(得分:8)
我遇到了同样的问题但是通过使用此帖子中的解决方法解决了这个问题: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();
答案 1 :(得分: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);
答案 2 :(得分:2)
如何修复它有简单的脏方法 - 查询中的环绕列具有与concat函数的唯一约束:
var commandText = "SELECT CONCAT(o.orderno, ''), od.item, od.qty ...";
答案 3 :(得分:2)
我今天遇到了同样的错误并希望分享。我的问题是一个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);
答案 4 :(得分:0)
MySQL允许唯一索引中有多个空值。这会导致填充时出现ConstraintException。如何修复:在'table.Constraints'列表中找到此约束并删除它或只清除所有约束。
答案 5 :(得分:0)
我在查询中遇到了类似的问题,当使用MYSQL Reader加载Datatable()时,它会生成错误NON-NULL,UNIQUE或FOREIGN-KEY。
最后,我通过更改MySQL Connector.NET版本解决了它。