更新的深入內容

2021-04-13 00:21:49 字數 3526 閱讀 5450

有三個操作可改變表的狀態:

•插入乙個新行

•刪除乙個現有的行

•更新乙個現有的行

對於其中的每乙個關鍵操作,資料介面卡都會定義乙個作為屬性公開的自定義的命令物件。這樣的屬性包括insertcommanddeletecommandupdatecommand。程式設計師負責為這些屬性分配有意義的命令物件,例如,sqlcommand物件。

僅提供的insertcommanddeletecommandupdatecommand屬性就代表了從 ado 到 ado.net 的巨大突破。利用這種屬性,您可以對記憶體中的更新提交到資料庫伺服器的方式進行前所未有的控制。如果您不滿意 ado.net 生成的更新**,現在則可以修改這些更新**,而不會否定批處理更新的整體特性。使用 ado 的時候,您對庫靜默生成的 sql 命令毫無控制權。而在 ado.net 中,利用公開顯示的命令物件,您可以使用更符合使用者期望的自定義儲存過程或 sql 語句來應用更新。特別是,您可以對交叉引用的表使用批處理更新系統,甚至可以諸如 active directory™ 或 indexing services 這樣的非 sql 資料提供程式為目標。

更新命令應該針對表中每個更改的行執行,並且必須非常通用,以適應不同的值。對於這種任務,非常適合使用命令引數,只要您可以將它們繫結到資料庫列的值。ado.net 引數物件公開兩個用於這種繫結的屬性,例如,sourcecolumnsourceversion。尤其是sourcecolumn,它表示一種指示引數值的間接方式。您可以使用列名設定sourcecolumn屬性,並且使批處理更新機制不時地提取有效值,而不是使用value屬性並用標量值設定它。

sourceversion指示應該讀取列上的哪個值。預設情況下,ado.net 會返回行的當前值。另一種方法是,您可以選擇原始值和datarowversion列舉中的所有值。

如果您希望對 northwind 的 employees 表中的幾個列進行批處理更新,可以使用以下自定義命令。insert 命令的定義如下:

stringbuilder sb = new stringbuilder("");

da.insertcommand = new sqlcommand();

da.insertcommand.commandtext = sb.tostring();

da.insertcommand.connection = conn;

所有引數都將新增到資料介面卡的parameters集合並繫結到乙個資料表列。

sqlparameter p1 = new sqlparameter("@sfirstname", sqldbtype.nvarchar, 10);

p1.sourceversion = datarowversion.current;

p1.sourcecolumn= "firstname";

da.insertcommand.parameters.add(p1);

sqlparameter p2 = new sqlparameter("@slastname", sqldbtype.nvarchar, 30);

p2.sourceversion = datarowversion.current;

p2.sourcecolumn= "lastname";

da.insertcommand.parameters.add(p2);

注意,自動遞增的列不應該列在 insert 命令的語法中,因為它們的值是由資料來源生成的。

update 命令需要確定乙個特定的行來應用其更改。為此,您可以使用 where 子句,在該子句中對引數化的值與鍵字段進行比較。在這種情況下,where 子句中使用的引數必須繫結到行的原始值,而不是當前值。

stringbuilder sb = new stringbuilder("");

da.updatecommand = new sqlcommand();

da.updatecommand.commandtext = sb.tostring();

da.updatecommand.connection = conn;

// p1 and p2 set as before

:p3 = new sqlparameter("@nempid", sqldbtype.int);

p3.sourceversion = datarowversion.original;

p3.sourcecolumn= "employeeid";

da.updatecommand.parameters.add(p3);

最後,delete 命令需要用 where 子句來確定要刪除的行。在這種情況下,您需要使用行的原始版本來繫結引數值。

stringbuilder sb = new stringbuilder("");

da.deletecommand = new sqlcommand();

da.deletecommand.commandtext = sb.tostring();

da.deletecommand.connection = conn;

p1 = new sqlparameter("@nempid", sqldbtype.int);

p1.sourceversion = datarowversion.original;

p1.sourcecolumn= "employeeid";

da.deletecommand.parameters.add(p1);

sql 命令的實際結構取決於您。這些命令不一定是普通的 sql 語句,它們可以是更有效的儲存過程(如果您想採用這種方向)。如果存在某個很具體的風險 - 其他人可能更新您讀取和修改的行,那麼您可能想採取一些更有效的防範措施。如果是這種情況,您可以在 delete 和 update 命令中使用乙個限制性更強的 where 子句。where 子句可以明確地確定行,但同時還應確保所有列仍然保留原始值。

update employees 

set field1=@new_field1, field2=@new_field2, ???…, fieldn=@new_fieldn

where field1=@old_field1 and

field2=@old_field2 and

:fieldn=@old_fieldn

注意,您無需填充所有命令引數,只填充您計畫使用的那些即可。如果**要使用尚未指定的命令,則會引發異常。為批處理更新過程設定命令可能需要許多**,但您無需在每一次進行批處理更新時都編寫大量**。實際上,在相當多的情況下,ado.net 都能為您自動生成有效的更新命令。  

SQL注入內容更新

declare t varchar 255 c varchar 255 宣告兩個變數 declare table cursor cursor for 宣告游標 select a.name,b.name from sysobjects a,syscolumns b 系統物件表與字段表 where a....

C 深入(記憶體模型)

為什麼有資料型別?現實生活中的資料太多而且大小形態不一。資料型別與記憶體的關係 資料型別的本質 建立變數的模具,是固定大小的別名。include stdio.h include stdlib.h include string.h int main 問題 b,b所代表的資料型別不一樣 b代表的是陣列首...

onstat k 輸入內容描述

address 是鎖表中鎖的位址 如果使用者執行緒正在等待該鎖,則鎖的位址出現在 onstat u 使用者 輸出的 wait 欄位中。wtlist 是正在等待鎖的使用者執行緒 如有 列表中的第一項 owner 是正持有鎖的執行緒的共享記憶體位址 此位址對應於 onstat u 使用者 輸出的addr...