2014-09-01 43 views
2

我想創建基業爲使用SQL Server在C#對象,我有:SQL中的繼承。如何保證它?

create table dbo.Evaluations 
(
    Id int not null constraint primary key clustered (Id), 
    Created datetime not null 
); 

create table dbo.Exams 
(
    Id int not null, 
    Value int not null 
    // Some other fields 
); 

create table dbo.Tests 
(
    Id int not null, 
    Order int not null 
    // Some other fields 
); 

alter table dbo.Exams 
add constraint FK_Exams_Id foreign key (Id) references dbo.Evaluations(Id); 

alter table dbo.Tests 
add constraint FK_Tests_Id foreign key (Id) references dbo.Evaluations(Id); 

這將轉化爲:

public class Evaluation {} 

public class Exam : Evaluation {} 

public class Test : Evaluation {} 

我認爲這是去,但我有辦法問題:

  1. 如何強制,一個Evaluation只有一個Test或一個Exam但不是機器人H?

  2. 要找到我有哪種類型的評估,我可以檢查考試或測試null。但是,我應該有表中的EvaluationType嗎?

注: 在現實中,我有4個亞型每一個與大約40到60個不同的列。 而在評估表中,我有大約20個常用列,這些列也是我經常用來查詢的列,所以我列出了列表。

+2

http://stackoverflow.com/questions/386652/techniques-for-database-inheritance – Donal 2014-09-01 14:29:24

+0

是的,我已經讀過......但我不知道如何回答我的2個問題......我應該使用2個表格,考試和考試,並將共同的列放入其中?事實上,我有兩個對象和大約15個共同的列,所以我雖然這是要走的路。 – 2014-09-01 14:33:31

+0

我會和戈登一起回答 – Donal 2014-09-01 14:35:19

回答

2

首先,不要使用保留字如order作爲列名。

你有幾個選擇要做什麼。對於這個簡單的例子,我建議僅在evaluation表中使用兩個外鍵引用,以及一些約束和計算列。像這樣:

create table dbo.Evaluations 
(
    EvaluationId int not null constraint primary key clustered (Id), 
    ExamId int references exams(ExamId), 
    TestId int references tests(TestId), 
    Created datetime not null, 
    EvaluationType as (case when ExamId is not null then 'Exam' when TestId is not null then 'Test' end), 
    check (not (ExamId is not null and TestId is not null)) 
); 

如果您有很多子類型,這種方法變得不太實際。但對於您的情況,它提供了以下內容:

  • 對子表的外鍵引用。
  • 指定類型的列。
  • 確認每個評估至多設置一種類型。

它確實有一點額外的,未使用的ID的開銷,但這是一個小開銷。

編輯:

隨着四種亞型,可以在具有在父表中的單個參考和類型,然後使用條件列和索引的另一個方向去執行約束:

create table dbo.Evaluations 
(
    EvaluationId int not null constraint primary key clustered (Id), 
    EvaluationType varchar(255) not null, 
    ChildId int not null, 
    CreatedAt datetime not null, 
    EvaluationType as (case when ExamId is not null then 'Exam' when TestId is not null then 'Test' end), 
    ExamId as (case when EvaluationType = 'Exam' then ChildId end), 
    TestId as (case when EvaluationType = 'Test' then ChildId end), 
    Other1Id as (case when EvaluationType = 'Other1' then ChildId end), 
    Other2Id as (case when EvaluationType = 'Other2' then ChildId end), 
    Foreign Key (ExamId) int references exams(ExamId), 
    Foreign Key (TestId) int references tests(TestId), 
    Foreign Key (Other1Id) int references other1(Other1Id), 
    Foreign Key (Other2Id) int references other2(Other2Id) 
); 

在某些方面,這是對問題更好的解決方案。它最大限度地減少了存儲空間,並且可以擴展到其他類型。請注意,它使用計算列作爲外鍵引用,所以它仍然保持關係完整性。

+0

我更新了我的答案並添加了一個註釋......我有4個亞型和許多列......我覺得在評估中使用FK會感覺很奇怪......您怎麼看?如果我有4個或更多的子類型,我會得到很多空值......這就是爲什麼我最終選擇了另一個選項。 – 2014-09-01 14:38:17

+0

是的,訂單僅僅是一個例子......我忘了它是一個保留字。我輸入的例子並不是真正的例子,因爲真正的例子有很多列和更多的表格。 – 2014-09-01 14:39:51

0

我最好的體驗是在一張表中包含所有列。 關係模型與面向對象的設計不太友好。 如果您將每個類視爲一個表,那麼您可以在「base-table」(基類)中獲得大量行的性能問題,或者如果您具有繼承級別,則可能會遇到大量聯接。

如果您希望最小化工作量以獲得正確的結構,請創建您自己的工具,它可以創建/更改所選類表的表格腳本。這其實很簡單。然後你可以生成你的數據訪問層。結果你會得到自動工作者,你可以專注於複雜的任務,並將「訓練過的猴子」的工作委託給計算機而不是人類。