2011-09-28 84 views
3

我有兩個表ordersorderdetails了MySqlDataReader:DataTable.Fill(讀取器)拋出ConstraintException

表訂單(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 o.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。 Propably因爲

reader.GetSchemaTable() 

有orderno一個IsUnique=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) 

回答

5

我想通了,那

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); 
+0

感謝分享伴侶!像魅力一樣工作。 – kuklei

0

MySQL允許在唯一索引多個空值。這會導致填充上的ConstraintException。如何解決:在'table.Constraints'列表中找到此約束並將其刪除或僅清除所有約束。

+0

多個空值不是問題。 'table.Load()'方法在Orderno上創建一個Contraint,因爲reader.GetSchemaTable()對於Orderno列具有'IsUnique' = true,對於Join查詢是錯誤的。 –

+0

嘗試清除FillError事件的約束。 – Devart

+0

我也這麼想過。但是,如果我使用接受FillError委託的重載,它不會觸發。不知道爲什麼,因爲那是我應該期待的。 –

2

有簡單骯髒的方式如何解決它 - 環繞列的查詢與獨特contraint concat函數:

var commandText = "SELECT CONCAT(o.orderno, ''), od.item, od.qty ..."; 
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(); 
+0

看起來也不錯。請記住這一點。謝謝 –

2

今天我同樣的錯誤,並希望share.My問題是一個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); 
相關問題