我想使用实体类型到数据库中多个表的映射属性(实体拆分),而同时使用“映射逐层表(TPH)继承”,因此,我的模型映射代码如下:
modelBuilder
.Entity<Person>()
.HasKey(n => n.PersonId)
.Map(map =>
{
map.Properties(p => new { p.Name });
map.ToTable("dbo.Person");
})
.Map<Customer>(map =>
{
map.Requires("PersonType").HasValue("C");
map.Properties(p => new { p.CustomerNumber });
map.ToTable("dbo.Customer");
});
基于以下基础数据库架构:
create table dbo.Person
(
PersonId int not null identity(1,1) primary key,
PersonType char(1) not null,
Name varchar(50) not null
)
create table dbo.Customer
(
PersonId int not null references dbo.Person (PersonId),
CustomerNumber varchar(10) not null
)
但是,当EF尝试执行我的查询时:
ctx.People.ToList();
引发以下异常消息:
Invalid column name 'PersonType'.
运行一个SQL配置文件,它似乎试图在表上PersonType
使用值的谓词,而不是在我的鉴别器实际所在的表上使用值。C
dbo.Customer
dbo.Person
如果我使用一个或另一个功能,即仅继承或仅使用其他表映射,则它可以工作,但是我放弃了一些要求。
EF Fluent API可以完成我的工作吗?
谢谢你的时间。
这可以通过在映射中涉及的所有表模式上创建视图来实现:
create view dbo.vw_PersonExtended
as
select
p.Name, p.PersonId, p.PersonType, c.CustomerNumber
from
dbo.Person p
left join dbo.Customer c on c.PersonId=p.PersonId
并将此视图映射到基类类型,Person
并删除派生类表映射,如下所示:
modelBuilder
.Entity<Person>()
.HasKey(n => n.PersonId)
.Map(map =>
{
map.Properties(p => new { p.Name });
map.ToTable("dbo.vw_PersonExtended");
})
.Map<Customer>(map =>
{
map.Requires("PersonType").HasValue("C");
map.Properties(p => new { p.CustomerNumber });
});
由于视图具有多个基表,因此在插入新实体时将失败,因此您必须使用INSTEAD OF TRIGGER或使用Fluent代码将插入映射到存储过程,如下所示:
modelBuilder
.Entity<Customer>()
.MapToStoredProcedures(map => map.Insert(i => i.HasName("usp_InsertCustomer")));
并插入存储过程示例为:
create procedure dbo.usp_InsertCustomer
@Name varchar(50),
@CustomerNumber varchar(50)
as
begin
set nocount on
declare @id int
insert into dbo.Person (Name, PersonType)
values (@Name, 'C')
set @id = scope_identity()
insert into dbo.Customer (PersonId, CustomerNumber)
values (@id, @CustomerNumber)
select @id as PersonId
end
显然,这种方法的缺点是使这种工作涉及到所有的管道工作。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句