1

我正在使用SQL Server 2008/LinqToSQL /定製存儲庫作爲DAL的多用戶互聯網數據庫驅動的網站。我遇到了一個規範化問題,如果正確利用,會導致數據庫狀態不一致,我想知道如何處理這個問題。如何避免此數據庫模式中的衝突數據?

問題:幾個不同的公司有權訪問我的網站。他們應該能夠在我的網站上跟蹤他們的項目和客戶。一些(但不是全部)項目應該分配給客戶。

這將導致以下數據庫模式:

**Companies:** 
ID 
CompanyName 

**Clients:** 
ID 
CompanyID (not nullable) 
FirstName 
LastName 


**Projects:** 
ID 
CompanyID (not nullable) 
ClientID (nullable) 
ProjectName 

這導致以下關係:

Companies-Clients (1:n) 
Companies-Projects (1:n) 
Clients-Projects(1:n) 

現在,如果用戶是惡意的,他可能例如插入一個項目他自己的CompanyID,但具有屬於另一個用戶的ClientID,導致數據庫處於不一致狀態。

問題以類似的方式發生在我的數據庫模式上,所以我想以通用的方式解決這個問題。我有以下兩種想法:

  • 檢查可能導致DAL不一致的數據庫寫入。這是通用的,但在更新和創建查詢之前需要額外的數據庫查詢,因此會導致性能下降。

  • 爲客戶 - 項目關係創建一個附加表並確保以此方式創建的關係是一致的。這也需要一些額外的選擇查詢,但遠低於第一種情況。另一方面,它不是通用的,所以從長遠來看,更容易錯過某些東西,尤其是在向數據庫添加更多表/依賴項時。

你會做什麼?我錯過了更好的解決方案嗎?

編輯:你可能想知道爲什麼Projects表有一個CompanyID。這是因爲我希望用戶能夠使用和不使用客戶端來添加項目。我需要跟蹤哪個公司(以及哪個網站用戶)屬於無客戶端項目,這就是爲什麼項目需要公司ID。

回答

0

最後,我實現了一個完全通用的解決方案,它可以解決我的問題,而無需太多的運行時間開銷,也不需要對數據庫進行任何更改。我會在這裏描述它以防別人遇到同樣的問題。

首先,該方法僅適用,因爲其他表通過多個路徑引用的唯一表是公司表。由於在我的數據庫中就是這種情況,我只需檢查每個要創建/更新/刪除的實體的所有n:1引用實體是否引用同一家公司(或根本沒有公司)。

我通過獲得所有我的LINQ實體從以下類型中的一種執行這樣的:

  1. SingleReferenceEntityBase - 限額。只有(通過反思)檢查公司表中是否只有一個參考(無論是過渡性的還是不敏感的)。如果是這種情況,那麼對公司表的引用不會變得不一致。

  2. MultiReferenceEntityBase - 對於特殊情況,例如上面的Projects表。詢問所有直接引用的實體所引用的公司ID。如果不一致,則引發異常。這會使我爲每個CRUD操作選擇幾個查詢,但由於MultiReferenceEntities比SingleReferenceEntities少得多,所以這可以忽略不計。

這兩種類型的實施「CheckReferences」和我打電話它每當LINQ實體通過部分地實現該自動生成的OnValidate(System.Data.Linq.ChangeAction動作)方法寫入到數據庫適用於所有Linq實體。

0

如果你想使用這樣的表,並避免所有新的查詢只是把觸發器放在表上,當用戶試圖插入錯誤的數據行觸發器阻止他。 最好的問候, Iordan

+0

我認爲重點在於,如果沒有某種方法記錄數據庫中允許或不允許的內容,觸發器無法確定實際上有效的數據是否有意義。 – ninesided 2009-08-05 08:25:50

+0

正是。我可能會嘗試在我的DAL中執行相同的操作,而不是使用觸發器,但我需要爲每個更新/插入/刪除操作添加一些額外的select查詢,這將導致我在上面提到的第一種可能的解決方案。 – 2009-08-05 08:37:19

2

我願意與後者,有一個或多個表,定義實體之間的允許關係。

1

請注意,您的參考文獻中沒有循環,因此標題具有誤導性。

你有什麼是衝突的數據的可能性,這是不同的。


爲什麼在項目表中有「CompanyID」?涉及的公司的ID由您鏈接的客戶端隱式給出。你不需要它。

刪除該列並刪除了問題。

此外,客戶端表中「名稱」列的用途是什麼?你能爲客戶提供一個與公司名稱不同的名稱嗎?

或者是「客戶」在那家公司的人?


編輯:確定與澄清有關項目沒有公司,我會單獨拿出來引用,但你不會擺脫您所描述的問題不在於防止多個引用被限制製作。

現有表的一個簡單約束是,項目行的CompanyID和ClientID字段不能同時爲非null。

+0

請參閱我的編輯上面的澄清 – 2009-08-05 12:12:59

0

我的第一個想法是爲名稱爲「無客戶」的每家公司創建一個特殊的客戶記錄。然後從Project表中刪除CompanyId,如果項目沒有客戶端,請使用「無客戶端」記錄而不是「正常」客戶端記錄。如果處理這樣的非客戶端是特殊的,則向無客戶端記錄添加標誌以明確標識它。 (我不願意依賴名稱是「沒有客戶端」或類似的東西 - 太模糊了)。

然後就沒有辦法存儲不一致的數據,所以問題就會消失。