簡體   English   中英

如何在實際項目中使用數據庫觸發器?

[英]How to use database triggers in a real world project?

我在最后的弱點中學到了很多關於觸發器和活動數據庫的知識,但我對這些真實世界的例子有一些疑問。

在工作中,我們使用帶有 ASP.Net 和 MSSQL 服務器的實體框架。 我們只使用自動生成的約束,不使用觸發器。

當我聽說觸發器時,我問自己以下問題:

  1. 觸發器可以執行哪些任務? 例如:報告數據的生成:目前報告的數據是在 vb 中創建的,但我認為觸發器也可以處理這個問題。 vb 中的創建需要很多時間,用戶應該不需要等待,因為這對他的工作來說不是必需的。 這是觸發器完美任務的示例嗎?

  2. OR-Mapper 如何處理觸發器操縱的數據? 例如:OR-Mapper 是否識別觸發器是否操縱了數據? 實體框架似乎緩存了很多數據,所以我不確定如果觸發器操作數據,在處理框架的插入/更新/刪除后它是否讀取更新的數據。

  3. 數據庫中應該有多少約束處理? 例如:有時數據庫中的約束看起來比上面的層(vb.net,...)更容易和更快,但是如何將異常拋出到可以由OR-Mapper 處理的上層? 在任何 OR-Mapper 中處理 SQL 異常(來自觸發器)是否有一個好的解決方案?

提前致謝

當您聽說一種新工具或新功能時,並不意味着您必須在任何地方都使用它。 您應該考慮應用程序的設計。

當邏輯在數據庫中時,觸發器被大量使用,但是如果您在數據庫之上構建 ORM 層,您希望業務層中的邏輯使用 ORM。這並不意味着您不應該使用觸發器。 這意味着您應該以與存儲過程或數據庫函數相同的方式將它們與 ORM 一起使用 - 僅當它有意義或提高性能時。 如果你將大量邏輯傳遞給數據庫,你可以扔掉 ORM 甚至整個業務層,並使用兩層架構,其中 UI 將直接與數據庫對話,數據庫將完成你需要的一切——這樣的架構被認為是“舊的”。

  1. 當使用 ORM 觸發器時,對於某些數據庫生成的數據(如審計列或主鍵值的自定義序列)可能會有幫助。
  2. 當前 ORM 大多不喜歡觸發器 - 它們只能對當前處理的記錄的更改做出反應,因此例如,如果您保存訂單記錄並且您的更新觸發器將修改所有訂購的項目,則沒有自動的方式讓 ORM 知道這一點 - 你必須手動重新加載數據。 在 EF 中,所有在數據庫中修改或生成的數據都必須使用StoreGeneratedPattern.IdentityStoreGeneratedPattern.Computed進行設置 - EF 完全遵循邏輯在數據庫或應用程序中的模式。 一旦您定義了在數據庫中分配的值,您就無法在應用程序中更改它(它不會持久存在)。
  3. 您的應用程序邏輯應該負責數據驗證並僅在驗證通過時調用持久性。 當您可以預先知道事務將失敗時,您應該避免不必要的事務和往返數據庫。

我使用觸發器有兩個主要目的:審核和更新修改/插入時間。 審計時,觸發器將數據推送到相關的審計表。 這不會以任何方式影響 ORM,因為這些表通常不會映射到主數據上下文中(需要查看審計數據時會使用單獨的審計數據上下文)。

在記錄/修改插入/修改時間時,我通常將 model 中的這些屬性標記為[DatabaseGenerated( DatabaseGenerationOptions.Computed )]日期時間字段正確。

我以這種方式管理審計和這些日期並不是硬性規定。 有時我需要比數據庫本身可用的更多的審計信息,而是在數據層處理審計。 有時我想強制應用程序更新日期/時間(因為它們可能需要在同時更新的多個行/表中保持相同)。 在這些情況下,我可能使字段可為空,但 model 中的[Required]強制在 model 可以保留之前設置日期/時間。

觸發器用於維護數據的完整性一致性(通過使用約束),幫助數據庫設計者確保完成某些操作並創建數據庫更改日志

例如,給定數字輸入,如果您希望值被限制為小於 100,您可以編寫一個觸發器,在更新或插入時為每一行觸發,並在該列的值不小於 100 時引發應用程序錯誤滿足那個約束。

假設您要記錄對表的歷史更改 您可以創建一個在每次插入更新刪除觸發的觸發器,它還會將數據插入到日志記錄表中。 如果您需要執行自定義自定義邏輯,那么觸發器可能會吸引您。

舊的 Infomodeler/Visiomodeler ORM(不是你想的 - 它是 Object 角色建模)在生成物理 model 時提供了一個替代方案。它將提供所有帶有觸發器的參照完整性。 有兩個原因:

  1. 一些數據庫(尤其是 Sybase/SQL Server)還沒有聲明式 RI,並且
  2. 它可以提供更細粒度的完整性——例如“不超過兩個孩子”或“兒子或女兒但不是兩個”或“強制兒子或女兒但不是兩個”。

因此,與 model 相關的觸發邏輯與任何 RI 約束的方式相同。 在 SQL 服務器中,它使用 RAISERROR 處理違規。

觸發器的一個概念性問題是它們本質上是上下文無關的——無論上下文如何,它們總是觸發(至少沒有很大的痛苦,你最好將它們的邏輯包含在上下文特定邏輯的 rest 中。)所以全局域約束是我發現它們唯一有用的地方——我想這是識別“參照完整性”的另一種通用方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM