问题描述
TL; DR
我需要在现有数据库上实现TPT。我有表格:实体,公司和人。 Company和Person通过其主键(一对一)-EntityId与Entity链接。
有关表包含审核列: CreateDate(非NULL),ChangeDate,createuserId(非NULL),ChangeUserId,CreateTransactionId,ChangeTransactionId ,我无法删除它们。我能够实现TPT和GET正常工作,但是当我尝试使用EF6将记录插入到表中时会引发错误,例如列之一中的CreateDate不能为null。原因是:审核数据已映射到Entity表,并且没有将该信息添加到Person / Company表中。
TPT是通过Person和Company类从实体派生的方式实现的。
在使用TPT时如何强制EF6在两个表中保存属性?实体拆分不起作用,它会引发一个错误,即非键属性无法映射两次。
如果不是EF6,那么是否有一种方法(例如前/后触发器)可以用数据填充问题列?
背景-当前实施-使用EF6
我有一个看起来像这样的现有数据库: CurrentDatabase
如您所见:
- 实体是一个表,用于存储“人”和“公司”的所有常用信息
- 人员和公司扩展特定实体的数据
- 实体人和实体公司(橙色标记)之间存在一对一关系
- 应用程序通过CustomerEntityId与实体表(一对多)(橙色标记)链接
- 所有表均包含审核列(黄色标记): CreateDate(非NULL),ChangeDate,createuserId(非NULL),ChangeUserId,CreateTransactionId,ChangeTransactionId 。应用程序表也包含它们,但为简单起见,我决定不在打印屏幕上显示它们。
public class ApplicationEntity : AbstractAuditableEntity
{
public override int Id { get; set; }
public int CustomerId { get; set; }
public virtual CustomerEntity Customer { get; set; }
}
public class Entity : AbstractAuditableEntity
{
public override int Id { get; set; }
public string Type { get; set; }
public string Name { get; set; }
public int? Status { get; set; }
public string Notes { get; set; }
}
public class CustomerEntity : AbstractAuditableEntity
{
public override int Id { get; set; }
public int? Title { get; set; }
public string Surname { get; set; }
public string MiddleName { get; set; }
public string Forename { get; set; }
public virtual Entity Entity { get; set; }
}
public class CompanyEntity : AbstractAuditableEntity
{
public override int Id { get; set; }
public string CompanyName { get; set; }
public Int16 HostCompany { get; set; }
public virtual Entity Entity { get; set; }
}
所有现有类都派生自Abstract AuditableEntity,这意味着它们包含: CreatedByUserId,CreatedDate,CreateTransactionId,ChangedByUserId,ChangedDate,ChangeTransactionId 。
CustomerEntity(与Person表链接)和CompanyEntity具有属性Entity。 此外,ApplicationEntity包含一个CustomerEntity的外键,借助它,您可以从DB获取有关Entity本身的信息的对象,例如
var application = _unitOfWork.GetRepository<ApplicationEntity>().GetById(1);
var entityType = application.Customer.Entity.Type;
当然,所有配置都允许我在DB中进行GET / INSERT / UPDATE数据:
- 我已将所有属性映射到有效列,
- 关系是正确的
- 等
问题描述
现在,我必须对代码进行一些更改。要求是将ApplicationEntity与CompanyEntity链接起来,并假设如果某个应用程序拥有一个Company,则该公司不能与Customer链接。话虽这么说,我决定用一些TPC来实现TPT方法。
为什么?如果CustomerEntity和CompanyEntity源自相同的BaseEnterpriseEntity,然后又从Entity衍生,则可以将其与ApplicationEntity链接。一切似乎都有效。当我从存储库中获取对象时,所有字段都将正确填充。我唯一的问题是当我插入/更新数据时。我收到一条错误消息,指出无法处理数据库查询,因为其中一个属性(CreateDate)为NULL。之所以有意义,是因为该字段也在实体表中,并且EF在那里将其映射(请参见下面的查询)。
exec sp_executesql N'INSERT [dbo].[Entity]([EntityType],[EntityName],[Status],[Notes],[CreateDate],[createuserId],[CreateTransactionId],[ChangeDate],[ChangeUserId],[ChangeTransactionId],[CommunicationRequirement])
VALUES (@0,@1,NULL,@2,@3,@4,NULL)
SELECT [EntityId]
FROM [dbo].[Entity]
WHERE @@ROWCOUNT > 0 AND [EntityId] = scope_identity()',N'@0 varchar(8000),@1 varchar(8000),@2 datetime2(7),@3 int,@4 uniqueidentifier,@5 int',@0='P',@1='Victoria McQueen',@2='2020-10-08 14:34:07.9033492',@3=-1,@4='0000000-0000-0000-0000-000000000000'
exec sp_executesql N'INSERT [dbo].[Person]([EntityId],[Title],[Surname],[MiddleNames],[Forename])
VALUES (@0,@3)
',N'@0 int,@1 int,@2 varchar(8000),@3 varchar(8000)',@0=7,@1=1254,@2='McQueen',@3='Victoria',@4='',@5='Vicki'
我试图将属性拆分为映射到两个表,但是EF表示无法完成:
“公司”类型的属性只能映射一次。非关键属性“ CreatedDate”被映射多次。确保Properties方法仅指定每个非关键属性一次。
最后
我想拥有的是:
- 表格的“审核”列必须保留
- 创建新公司时,需要填充每个表的数据。由于我无法删除审核表,因此必须使用相同的信息填充它们,例如实体表将包含与公司表相同的CreateDate。 我已经考虑过要在company表上添加某种预插入触发器,但是看来它不适用于EF查询。
有什么建议吗?
当前类的实现:
public class ApplicationEntity : AbstractAuditableEntity
{
public override int Id { get; set; }
public int CustomerId { get; set; }
public virtual BaseEnterpriseEntity Customer { get; set; } // or Entity as type
}
public class Entity : AbstractAuditableEntity
{
public override int Id { get; set; }
public string Type { get; set; }
public string Name { get; set; }
public int? Status { get; set; }
public string Notes { get; set; }
}
public abstract class BaseEnterpriseEntity : Entity
{
public override int Id { get; set; }
}
public class CustomerEntity : BaseEnterpriseEntity
{
public override int Id { get; set; }
public int? Title { get; set; }
public string Surname { get; set; }
public string MiddleName { get; set; }
public string Forename { get; set; }
}
public class CompanyEntity : BaseEnterpriseEntity
{
public override int Id { get; set; }
public string CompanyName { get; set; }
public Int16 HostCompany { get; set; }
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)