2013-10-30 57 views
0

我們需要將「安裝」結構存儲在SQL Server數據庫中。 「設置」具有多個可以具有子頻道的「頻道」。每個通道可以有多個包含具有值的標準屬性的「變量」。在SQL Server中保存(分層)c#對象的結構 - >複雜嗎?

該結構在C#項目中定義。所以,有一個包含List的Setup對象,有一個包含List和List的Channel對象。

我實際上完成了項目,通過創建一個安裝程序表,一個包含安裝程序和自引用的外鍵的通道表,以及一個帶有通道外鍵的變量表。

c#程序需要一些功能列出現有的設置,加載和保存。

我創建了一個存儲過程來保存一個接受3個表參數的設置:安裝程序(應該只包含一行),Channel和Variable。輸入參數僅包含實體的自然鍵。然後存儲過程將其插入或更新到db中。

爲了加載一個設置,我創建了一個執行3個選擇的存儲過程。然後c#通過SqlCommand.ExecuteReader()讀取它們。

問題:保存設置存儲過程是該死的太複雜了。這裏簡要介紹一下步驟。這一切都變得更加複雜,因爲渠道的層次結構的,因爲我需要通過爲每個層次一步過程步驟:

Parameter validity check 

Check if Setup exists 
    if yes, update, keep its id (SetupID) 
    if not, insert, keep its id (SetupID) 

Update SetupID in parameter tables Channel,Variable 
Fetch ChannelID for channels given in parameters that do exist in the database 
Fetch VariableID for variables given in parameters that do exist in the database 

Delete channels and variables that do exist in database for that setup, but were not provided in the parameters 
    Channels should be recursively deleted, first the ones without children, then their parents etc. 

Insert new Channels (given in parameters, not existing in the database) 
    Do it recursively, first for the ones without children, then, their parents, etc. 
    Every time you do some insert, update the respective ChannelID in the parameter tables 
Update Channels given in parameters that do exist in the database 

Insert new Variables (given in parameters, not existing in the database) 
Update Variables given in parameters that do exist in the database 

它轉換成大約250的T-SQL代碼行說了我2天來寫和錯誤檢查。它現在可以正常工作,但我確信它可以以更簡單的方式完成。 任何想法/評論?

PS:保存在XML不是一種選擇,因爲該項目的核心思想是能夠查看所有屬性,並進行查詢後,他們,驗證,報告和統計數據等

謝謝提前!

更新:表創建腳本

CREATE TABLE [dbo].[Setup](
    [SetupID] [int] IDENTITY(1,1) NOT NULL, 
    [Name] [nvarchar](50) NOT NULL, 
    [Type] [nvarchar](4000) NULL, 
    [Info] [nvarchar](4000) NULL, 
    [FirstInserted] [datetime] NULL, 
    [LastUpdated] [datetime] NULL, 
CONSTRAINT [PK$Setup] PRIMARY KEY CLUSTERED 
([SetupID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 
CREATE UNIQUE NONCLUSTERED INDEX [UQ$Setup$Name] ON [dbo].[Setup] 
([Name] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 

CREATE TABLE [dbo].[Channel](
    [ChannelID] [int] IDENTITY(1,1) NOT NULL, 
    [SetupID] [int] NOT NULL, 
    [Type] [nvarchar](50) NOT NULL, 
    [ParentChannelID] [int] NULL, 
    [Sequence] [int] NOT NULL, 
    [PanelIdx] [nvarchar](4000) NULL, 
    [Visible] [nvarchar](4000) NULL, 
    [FirstInserted] [datetime] NULL, 
    [LastUpdated] [datetime] NULL, 
CONSTRAINT [PK$Channel] PRIMARY KEY CLUSTERED 
([ChannelID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 
ALTER TABLE [dbo].[Channel] WITH CHECK ADD CONSTRAINT [FK$Channel$Channel] FOREIGN KEY([ParentChannelID]) 
REFERENCES [dbo].[Channel] ([ChannelID]) 
GO 
ALTER TABLE [dbo].[Channel] CHECK CONSTRAINT [FK$Channel$Channel] 
GO 
ALTER TABLE [dbo].[Channel] WITH CHECK ADD CONSTRAINT [FK$Channel$Setup] FOREIGN KEY([SetupID]) 
REFERENCES [dbo].[Setup] ([SetupID]) 
GO 
ALTER TABLE [dbo].[Channel] CHECK CONSTRAINT [FK$Channel$Setup] 
GO 
CREATE UNIQUE NONCLUSTERED INDEX [UQ$Channel$SetupID_Type] ON [dbo].[Channel] 
([SetupID] ASC,[Type] ASC) 
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 
CREATE UNIQUE NONCLUSTERED INDEX [UQ$Channel$SetupID_ParentChannelID_Sequence] ON [dbo].[Channel] 
([SetupID] ASC, [ParentChannelID] ASC, [Sequence] ASC) 
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 

CREATE TABLE [dbo].[Variable](
    [VariableID] [int] IDENTITY(1,1) NOT NULL, 
    [ChannelID] [int] NOT NULL, 
    [Key] [nvarchar](50) NOT NULL, 
    [Sequence] [int] NOT NULL, 
    [DefaultText] [nvarchar](4000) NULL, 
    [IONumber] [nvarchar](4000) NULL, 
    [LinkType] [nvarchar](4000) NULL, 
    [DataType] [nvarchar](4000) NULL, 
    [ImageTrue] [nvarchar](4000) NULL, 
    [ImageFalse] [nvarchar](4000) NULL, 
    [FormatString] [nvarchar](4000) NULL, 
    [GroupBoxIdx] [nvarchar](4000) NULL, 
    [ControlIdx] [nvarchar](4000) NULL, 
    [PlcVar] [nvarchar](4000) NULL, 
    [Value] [nvarchar](4000) NULL, 
    [DefaultValue] [nvarchar](4000) NULL, 
    [MinValue] [nvarchar](4000) NULL, 
    [MaxValue] [nvarchar](4000) NULL, 
    [Measure] [nvarchar](4000) NULL, 
    [KeyIdx] [nvarchar](4000) NULL, 
    [Behavior] [nvarchar](4000) NULL, 
    [TrueEnter] [nvarchar](4000) NULL, 
    [ShowCheckDigit] [nvarchar](4000) NULL, 
    [ShowOverflow] [nvarchar](4000) NULL, 
    [Visible] [nvarchar](4000) NULL, 
    [ReadOnly] [char](1) NULL, 
    [Dynamic] [char](1) NULL, 
    [FirstInserted] [datetime] NULL, 
    [LastUpdated] [datetime] NULL, 
CONSTRAINT [PK$Variable] PRIMARY KEY CLUSTERED 
([VariableID] ASC) 
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 
CREATE UNIQUE NONCLUSTERED INDEX [UQ$Variable$ChannelID_Key] ON [dbo].[Variable] 
([ChannelID] ASC, [Key] ASC) 
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 
CREATE UNIQUE NONCLUSTERED INDEX [UQ$Variable$ChannelID_Sequence] ON [dbo].[Variable] 
([ChannelID] ASC, [Sequence] ASC) 
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 
ALTER TABLE [dbo].[Variable] WITH CHECK ADD CONSTRAINT [FK$Variable$Channel] FOREIGN KEY([ChannelID]) 
REFERENCES [dbo].[Channel] ([ChannelID]) 
GO 
ALTER TABLE [dbo].[Variable] CHECK CONSTRAINT [FK$Variable$Channel] 
GO 
ALTER TABLE [dbo].[Variable] WITH CHECK ADD CONSTRAINT [CK$ChannelVariable$Dynamic_TF] CHECK (([Dynamic]='T' OR [Dynamic]='F')) 
GO 
ALTER TABLE [dbo].[Variable] CHECK CONSTRAINT [CK$ChannelVariable$Dynamic_TF] 
GO 
ALTER TABLE [dbo].[Variable] WITH CHECK ADD CONSTRAINT [CK$ChannelVariable$ReadOnly_TF] CHECK (([ReadOnly]='T' OR [ReadOnly]='F')) 
GO 
ALTER TABLE [dbo].[Variable] CHECK CONSTRAINT [CK$ChannelVariable$ReadOnly_TF] 
GO 
+1

你應該看看[實體框架代碼優先](http://weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with-entity-framework-4。 ASPX)。您可以共享您的C#模型並將其插入後端MSSQL數據庫。您甚至可以使用現有的存儲過程 – CodingIntrigue

+0

您在前兩段中描述的結構看起來並不複雜。你能分享你的設置,頻道,屬性和價值的課程代碼嗎? –

+0

我的意思是,插入/更新的過程聽起來很複雜。結構或多或少簡單:設置 - >通道 - >變量。 (儘管頻道的分層結構)。 – Manolis

回答

1

考慮使用一個Object Relational Mapper

.Net中的一些示例是Entity Framework(來自Microsoft),NHibernate(開放源代碼)和LLBLGen(商業版)。

還有其他的,每個人都有自己的優點和缺點。