mod*_*diX 9 c# asp.net entity-framework sql-server-2012 entity-framework-6
我基于SQL Server中的实现表继承一文,在我的SQL-Server中实现了一个模拟表继承构造.
除了使用简单的1到0 ... 1关系之外,您还可以为类型表创建另一个约束,该类型表列出了基表的所有可能子类型,如"建模一对一约束"一节中的文章中所述.
每个子表都包含一个TYPE字段,该字段具有ComputedColumnSpecification,其持久化编号表示类型表中类型的ID.由于TYPE字段是约束的一部分,因此它将确保只能为基础数据集创建一个子节点.
为了更好地理解,我创建了一个示例数据库,用于描述匹配的ASP.NET解决方案的问题.要在本地环境中复制该问题,请在执行此脚本之前创建名为"PLAYGROUND"的数据库:
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
Run Code Online (Sandbox Code Playgroud)
该表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 = "admin@example.org";
user.NATURAL_USER = new NATURAL_USER();
user.NATURAL_USER.BirthDate = new DateTime(1980, 01, 01);
model.USER.Add(user);
model.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
在model.SaveChanges();我得到例外:
ReferentialConstraint中的依赖属性映射到存储生成的列.栏目:'TYPE'.
样品溶液:https://dl.dropboxusercontent.com/u/55589036/zzzOther/Playground.zip(示例代码是在Page_Load的Default.aspx.cs.
据我所知,EntityFramework尝试设置列字段并失败,因为它的存储是生成的(持久化).这甚至发生在我设置时user.NATURAL_USER.TYPE = 1;.
我试图覆盖OnModelCreating以附加我自己的规则并将两TYPE列定义为Computed,但从OnModelCreating未被调用,因为我做了EDMX-after并且我想坚持这一点.
所以,这个实体模型是基于数据库生成的,我想保持这种方式,而且每次我更新模型时都不想编辑任何代码.
另外,我认为表继承概念在数据库层上实现得很好,因为它不使用触发器.我想保持它无触发.
我怎么解决这个问题?
我在实施该方法时犯了一个严重的错误,但它以前确实有效。我不小心搞乱了约束FK_NATURAL_USER___USER___TYPEVALIDATION。
它应该像约束一样构建FK_JURIDICAL_USER___USER___TYPEVALIDATION。
EF 能够处理持久化列。问题是它试图写入 PK,而[USER_T]该 PK 根本不应该是约束的一部分。
我对所有为此浪费时间的人感到抱歉。
| 归档时间: |
|
| 查看次数: |
1431 次 |
| 最近记录: |