65.9K
CodeProject 正在变化。 阅读更多。
Home

使用您的任何 Select 方法填充任何 TableAdapter

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (5投票s)

2009年5月12日

CPOL

4分钟阅读

viewsIcon

82026

downloadIcon

752

避免惱人的表適配器加載錯誤,無法啟用約束。

引言

在這裡,我們將看到如何填充任何 TableAdapter DataTable 並避免可怕的問題

Server Error in '/REDB' Application.

Failed to enable constraints. One or more rows contain values 
       violating non-null, unique, or foreign-key constraints.

背景

首先,讓我們概述一下 TableAdapter。您知道它是什麼以及如何使用它,否則您甚至不會在這裡。

  • 我們知道 TableAdapter 不是 .NET framework 對象。(它是一個 VS Designer 創建的對象,因此請勿嘗試瀏覽 TableAdapter .NET 對象。)
  • 繼承自 System.ComponentModel.Component,**而不是** DataAdapter
  • 封裝了一個 DataAdapter,例如 SQLDataAdapter 等。
  • 封裝了一個 SQLConnection
  • 封裝了一個 SQL CommandCollection
private global::System.Data.SqlClient.SqlDataAdapter _adapter;
private global::System.Data.SqlClient.SqlConnection _connection;
private global::System.Data.SqlClient.SqlCommand[] _commandCollection; 

使用代码

創建一個 Web 項目。為其命名。保存它。創建一個引用古老的 Northwind 資料庫的 DataSet。允許將 DataSet 保存在 App_Code 文件夾中。

使用 Products 表創建一個 ProductsTableAdapter。讓我們使用一個名為 ProductsTableAdapter 的示例 TableAdapter,它屬於我們已經創建的古老的 NorthwindDataSet。(請立即創建它,我會等。)

創建您自定義的 GetFill 方法。將一個命名為 GetProductNames,另一個命名為 FillProductNames

當您嘗試調用在 ProductsTableAdapter 中創建的自定義 Fill 方法之一,而該方法不包含默認 Select 方法的 DataTable 中的所有 DataColumn 時,您將遇到這個有趣的對話框警告消息

SchemaWarning.png

直到您嘗試調用僅返回產品名稱列表的自定義 GetProductNames() 方法,此警告才變得有意義。

當您使用 Sir Wizard 提供的配置和預覽調用此方法時,一切看起來都很棒。所有產品 DataTable 列都顯示為空,除了產品名稱。太棒了!這正是我們想要的。(實際上,我認為大多數人都期望得到一個產品名稱列表,而沒有其他數據列。)

好吧,我們可以暫時接受它。讓我們填入數據,以便至少可以使用產品名稱列表。

大多數人會這樣做

NorthwindDataSetTableAdapters.ProductsTableAdapter Adaptr = 
new ProductsTableAdapter();  
NorthwindDataSet.ProductsDataTable tbl = 
   new NorthwindDataSet.ProductsDataTable();

為了確保萬無一失,我們清除任何可能阻止我們的表填充的表約束。

tbl.Constraints.Clear();

現在,我們調用填充方法

tbl=Adaptr.GetProductNames();
//FILL the table and herein lies the problem. 

可怕的錯誤

Server Error in '/REDB' Application.

Failed to enable constraints. One or more rows contain values 
violating non-null, unique, or foreign-key constraints.

究竟發生了什麼?我們知道它在「預覽數據」中起作用。(您會在聽到我說出顯而易見的事實時尖叫,但首先,簡要分析一下。)

我們是否用 GetProductNames() 調用返回的對象覆蓋了我們的 tbl 對象?沒有,因為該調用在 Fill 方法調用中失敗了。讓我們檢查一下調用堆棧。

Line 9506:  this.Adapter.SelectCommand = this.CommandCollection[1];

Line 9507:  NorthwindDataSet.ProductsDataTable dataTable = 
            new NorthwindDataSet.ProductsDataTable();
Line 9508:  this.Adapter.Fill(dataTable);
Line 9509:  return dataTable;

Line 9510:

我們從未到達返回對象。

另外,請注意 CommandCollection 調用了其集合中的第二個項目(稍後會有更多關於該內容的相關信息)。

我們的 tbl 對象之前被創建為一個新的 ProductsDataTable。我這樣做是有意的。通常,我們會聲明一個新對象並在一行代碼中將其賦值

ProductsDataTable tbl = Adaptr.GetProductNames();

VB

Dim tbl AS ProductsDataTable = Adaptr.GetProductNames()

無論哪種情況,調用都會失敗。

由於我們的 tbl 對象已實例化為一個新的 ProductsDataTable(這是我們開始處理它的唯一方法),讓我們修復最明顯的問題

columns = tbl.Columns; //Get reference to the Columns Collection

foreach (DataColumn dc in columns) {dc.AllowDBNull = true;}

這是您需要做的唯一一件事,因為我們現在將把我們的 tbl 對象傳遞給 **fill** a DataTable 方法,而不是 **get** a DataTable 方法。(我警告過您會討厭它的簡單性。)

Adaptr.FillProductNames(tbl); //No Errors. Yes!

Console.Write("Row Count is " tbl.Rows.Count.ToString());
Response.Write("Row Count is " tbl.Rows.Count.ToString());

可以在 CodeProject 上找到一篇關於 TableAdapter 動態 SQL 的優秀文章。

关注点

tbl.Constraints.Clear() 並不是解決問題的方法。AllowDBNull 在所有情況下才是真正的解決方案。我花了一些時間才意識到,我幾乎總是返回一個 DataTable,並且從未嘗試將一個 DataTable 傳遞以進行填充。那時我才意識到 **fill** DataTable 自定義方法的用處。

您始終可以嘗試更改架構或創建單獨的 TableAdapter 以生成與您的數據一致的架構,但何必呢?這種方法非常有效。

您創建的第一個 Select 查詢是所有其他查詢的架構基礎。它成為默認查詢,並且其方法被 DataObjectMethodAttribute 裝飾,並且 Select 被設置為 true。現在,所有其他查詢都必須使用此默認架構。這就是為什麼您會看到上面顯示的警告對話框。

注意 SQL 旁邊的複選標記。這是 TableAdapter 中的第一個也是默認的 Select 查詢。第二個查詢成為 CommandCollection[1],依此類推。

謝謝,您們真是太棒的聽眾。

RickIsWright - www.rickiswright.com

历史

  • 發布日期:2009 年 5 月 11 日。
© . All rights reserved.