我想在以下场景中使用 EF (4.2):
- 已经存在一个数据库(所以我选择了数据库优先的方法),它是一个 SQL Anywhere 数据库。
- 我想使用持久性无知的业务对象,所以我使用模板从 EDM
DbContext
生成类。POCO
- 我的实体之间有一个简单的继承层次结构:一个抽象的基础实体和两个具体的派生实体。
- 在数据库中,每种类型的继承层次都有一个表(Table-Per-Type Strategy)。
- 这三个表中的每一个都有一个主键列 (
Id
, type:integer
),具体实体与基本实体的关联是通过Id
在两个表中具有相同的来完成的(这意味着Id
具体类型表的主键 ( )同时是基表的外键;我认为这是一种非常常见的方法)。
我必须在设计器中手动定义继承,因为 EDM 助手不会自动识别,即希望在所描述的实体之间具有继承关联。
到此为止,没有任何更大的问题。现在到手头的问题:我使用的数据库有一个限制:Primarykey
值必须由数据库生成,使用数据库函数。我想before-insert-trigger
在base-table
.
为了让实体框架知道一个值是由数据库生成的,我设置了toStoreGeneratedPattern
的Id
Property的属性(据我了解,这是在插入新的实体实例后告诉EF获取生成的值的方式)。base-entity
Identity
当我创建派生实体的新实例时,将其添加到上下文的对应并调用时,会抛出 a DbSet
,DbContext
说明违反了约束。通过检查数据库的请求日志,我看到基本实体被插入到基表中,但是在派生表中插入行时,出现上述错误,因为它显然没有使用新生成的基表中的新条目。SaveChanges
DbUpdateException
foreignkey
Id
由于我认为在数据库级别上对此我无能为力,因此问题是,是否可以配置(或修改)EDM 或 DbContext 以首先插入基本行,然后获取生成的Id
并将其用于插入派生行。
我知道有几种方法可以避免这种情况(不使用继承,使用存储过程插入新的派生实体,在插入之前调用生成 id 的 db 函数并Id
自己在实体上设置属性),但目前上述行为将是最可取的,所以我想确保在决定任何“B计划”之前不要忽视某些事情。
非常感谢有关此主题的任何建议,在此先感谢。
这是触发器的代码:
ALTER TRIGGER "TRG_GENERATE_ID" before insert order 1 on
BASE_TABLE
referencing new as NewEntry
for each row
begin
declare NewID integer;
set NewID = F_GET_NEW_ID('BASE_TABLE', NewEntry.SOME_OTHER_ID);
set NewEntry.ID = NewID
end
在触发器中调用函数“F_GET_NEW_ID”来为基表中的新条目生成新 ID。它有两个参数:"Tablename" -> 应该为其生成新ID的表的名称,第二个参数取数据库所有表中标准列的值(生成新ID是必需的) )。