我已經在我的SQL Server中基於文章Implementing Table Inheritance in SQL Server實現了一個模擬表繼承構造。」ReferentialConstraint中的依賴屬性映射到商店生成的列。「在一個持久的計算列(EntityFramework數據庫優先)
除了事實用簡單的1到0 ... 1間的關係,創建另一個約束,列出了所有可能的子類型,在段落在文章中解釋了基表的類型表「造型一對一約束條件「。
你的子表的每一個包含有一個堅持數字,表示在類型表類型的ID的ComputedColumnSpecification類型字段。由於TYPE字段是約束的一部分,它將確保只有一個孩子可以創建到基礎數據集。
爲了更好地理解我已經創建了用於與匹配的ASP.NET解決方案來描述問題的樣本數據庫。要複製在當地的環境問題,在執行此腳本之前創建一個名爲「樂園」數據庫:
USE [PLAYGROUND]
GO
/****** Object: Table [dbo].[USER] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[USER](
[ID] [int] IDENTITY(1,1) NOT NULL,
[TYPE__ID] [int] NOT NULL,
[Enabled] [bit] NOT NULL,
[Username] [nvarchar](32) NOT NULL,
[Password] [nchar](32) NOT NULL,
[Email] [nvarchar](255) NOT NULL,
CONSTRAINT [PK_USER] PRIMARY KEY CLUSTERED
(
[ID] 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
/****** Object: Table [dbo].[NATURAL_USER] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[NATURAL_USER](
[ID] [int] NOT NULL,
[TYPE] AS ((1)) PERSISTED NOT NULL,
[BirthDate] [date] NOT NULL,
CONSTRAINT [PK_NATURAL_USER] PRIMARY KEY CLUSTERED
(
[ID] 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
SET ANSI_PADDING OFF
GO
/****** Object: Table [dbo].[JURIDICAL_USER] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[JURIDICAL_USER](
[ID] [int] NOT NULL,
[TYPE] AS ((2)) PERSISTED NOT NULL,
[CompanyName] [nvarchar](256) NOT NULL,
[RegistrationNo] [nvarchar](max) NOT NULL,
[Description] [nvarchar](max) NOT NULL,
CONSTRAINT [PK_LEGAL_USER] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
/****** Object: Table [dbo].[USER_T] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[USER_T](
[ID] [int] IDENTITY(1,1) NOT NULL,
[TYPE] [nvarchar](32) NOT NULL,
CONSTRAINT [PK_USER_T] PRIMARY KEY CLUSTERED
(
[ID] 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
/****** Object: Index [IX_USER] ******/
ALTER TABLE [dbo].[USER] ADD CONSTRAINT [IX_USER] UNIQUE NONCLUSTERED
(
[Username] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
/****** Object: Index [PK_USER_TYPE] ******/
CREATE UNIQUE NONCLUSTERED INDEX [PK_USER_TYPE] ON [dbo].[USER]
(
[ID] ASC,
[TYPE__ID] 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
SET ANSI_PADDING ON
GO
/****** Object: Index [IX_USER_T] ******/
ALTER TABLE [dbo].[USER_T] ADD CONSTRAINT [IX_USER_T] UNIQUE NONCLUSTERED
(
[TYPE] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO
/****** TYPE DATA ******/
SET IDENTITY_INSERT [dbo].[USER_T] ON
GO
INSERT [dbo].[USER_T] ([ID], [TYPE]) VALUES (2, N'JURIDICAL_USER')
GO
INSERT [dbo].[USER_T] ([ID], [TYPE]) VALUES (1, N'NATURAL_USER')
GO
SET IDENTITY_INSERT [dbo].[USER_T] OFF
GO
/****** Contraints ******/
ALTER TABLE [dbo].[JURIDICAL_USER] WITH CHECK ADD CONSTRAINT [FK_JURIDICAL_USER___USER] FOREIGN KEY([ID])
REFERENCES [dbo].[USER] ([ID])
GO
ALTER TABLE [dbo].[JURIDICAL_USER] CHECK CONSTRAINT [FK_JURIDICAL_USER___USER]
GO
ALTER TABLE [dbo].[JURIDICAL_USER] WITH CHECK ADD CONSTRAINT [FK_JURIDICAL_USER___USER___TYPEVALIDATION] FOREIGN KEY([ID], [TYPE])
REFERENCES [dbo].[USER] ([ID], [TYPE__ID])
GO
ALTER TABLE [dbo].[JURIDICAL_USER] CHECK CONSTRAINT [FK_JURIDICAL_USER___USER___TYPEVALIDATION]
GO
ALTER TABLE [dbo].[NATURAL_USER] WITH CHECK ADD CONSTRAINT [FK_NATURAL_USER___USER] FOREIGN KEY([ID])
REFERENCES [dbo].[USER] ([ID])
GO
ALTER TABLE [dbo].[NATURAL_USER] CHECK CONSTRAINT [FK_NATURAL_USER___USER]
GO
ALTER TABLE [dbo].[NATURAL_USER] WITH CHECK ADD CONSTRAINT [FK_NATURAL_USER___USER___TYPEVALIDATION] FOREIGN KEY([TYPE])
REFERENCES [dbo].[USER_T] ([ID])
GO
ALTER TABLE [dbo].[NATURAL_USER] CHECK CONSTRAINT [FK_NATURAL_USER___USER___TYPEVALIDATION]
GO
ALTER TABLE [dbo].[USER] WITH CHECK ADD CONSTRAINT [FK_USER___USER_T] FOREIGN KEY([TYPE__ID])
REFERENCES [dbo].[USER_T] ([ID])
GO
ALTER TABLE [dbo].[USER] CHECK CONSTRAINT [FK_USER___USER_T]
GO
USE [master]
GO
ALTER DATABASE [PLAYGROUND] SET READ_WRITE
GO
表USER
是基表和表NATURAL_USER
和JURIDICAL_USER
是它的孩子。 USER_T
是USER
的類型表。現在
,在使用的EntityFramework 6我的ASP.NET應用程序嘗試創建一個新用戶的方式如下:
using (PLAYGROUNDEntities model = new PLAYGROUNDEntities())
{
USER user = new USER();
user.Username = "admin";
user.Password = "RANDOMHASH#123456";
user.Email = "[email protected]";
user.NATURAL_USER = new NATURAL_USER();
user.NATURAL_USER.BirthDate = new DateTime(1980, 01, 01);
model.USER.Add(user);
model.SaveChanges();
}
而且在model.SaveChanges();
我得到異常:
從屬ReferentialConstraint中的屬性映射到商店生成的列。列:'TYPE'。
樣品溶液:。https://dl.dropboxusercontent.com/u/55589036/zzzOther/Playground.zip(示例代碼是在Default.aspx.cs
的Page_Load
我明白了,的EntityFramework試圖設置列字段和失敗,因爲它的商店產生的(持續)這甚至發生在我設置user.NATURAL_USER.TYPE = 1;
。
我試圖重寫OnModelCreating
附上我自己的規則和定義都TYPE
列作爲Computed
,但OnModelCreating
不會被調用,因爲我做EDMX在之後,我想堅持這一點。
因此,基於數據庫生成此實體模型,我想保持下去,再加上我不想編輯,當我再次更新我的模型每一次的任何代碼。
而且,我認爲表繼承的概念在數據庫層上很好實現的,因爲它不使用觸發器。我想保持它不觸發。
我該如何解決這個問題?
爲什麼不直接使用帶有自己的繼承(TPT或TPH)的EF?你有使用DB First的項目限制嗎? – bubi
@bubi TPT或TPH方法只是EF上的繼承系統,仍然允許使用普通SQL在數據庫上繞過它。 TPT/TPH要求我在重新創建EDMX文件後在設計器中創建關聯。如果我在這裏錯了,請糾正我。 – modiX
TPT和TPH是與Code First嚴格相關的方法。如果您正在處理現有的數據庫(DB First + EDMX)不是一個好方法。你的情況是TPH(單表+鑑別字段),但如果DB + EDMX是一個約束標準EF TPH不是一個好方法。 – bubi