在使用 Entity Framework 数据库优先在表上插入行之前,如何从 PL/SQL 执行触发器?
Posted
技术标签:
【中文标题】在使用 Entity Framework 数据库优先在表上插入行之前,如何从 PL/SQL 执行触发器?【英文标题】:How to execute a trigger from PL/SQL before inserting a row on a table with Entity Framework database-first? 【发布时间】:2017-04-24 14:02:58 【问题描述】:我在 PL/SQL 中创建了一个触发器,当在表中插入一行之前触发,这通过 Oracle 序列增加值,然后作为主键插入到表中。
这是我的 PL/SQL 触发代码:
create or replace trigger FUT_SYS_USER_BE_I
before insert on FUT_SYS_USER referencing old as O new as N
for each row
declare
--local variables here
begin
if :N.SYS_USER_ID is null then
:N.SYS_USER_ID := SYS_USER_SEQ.NEXTVAL;
end if;
end FUT_SYS_USER_BE_I;
但是这个触发器永远不会执行,因为当我插入一行时,主键 SYS_USER_ID
永远不会增加并保存零值。
这是我的 C# 代码:
using(DemoDBEntities db = new DemoDBEntities())
FUT_SYS_USER SU = new FUT_SYS_USER();
SU.LOGIN_NAME = user.LoginName;
SU.PASSWORD_ENCRYPTED_TEXT = user.Password;
SU.ROW_CREATED_SYSUSER_ID = user.SYSUserID > 0 ? user.SYSUserID : 1;
SU.ROW_MODIFIED_SYSUSER_ID = user.SYSUserID > 0 ? user.SYSUserID : 1;
SU.ROW_CREATED_DATETIME = DateTime.Now;
SU.ROW_MODIFIED_DATETIME = DateTime.Now;
db.FUT_SYS_USER.Add(SU);
db.SaveChanges();
关于如何解决此问题的任何想法?
【问题讨论】:
我对oracle不太熟悉,但是它的主键没有自动递增功能吗? 我的猜测是SYS_USER_ID
被实体框架填充为 0,此时该值不再为空,并且触发器通过将 SYS_USER_ID
设置为序列的值。检查您是否可以将SYS_USER_ID
显式传递为NULL
,以更改触发器中IF
语句的逻辑。是的,@Kurev,Oracle 提供了一个 Identity 列,即自 12.1.0.1 以来的自动增量功能
您必须先创建一个序列,然后使用 SYS_USER_SEQ.NEXTVAL 递增该值。
在 Oracle 12.1 之前,您可以像示例中那样在行级触发器中对其进行编码,这看起来不错,只是在同一个 PK 中允许两个不同的键序列是自找麻烦。跨度>
【参考方案1】:
您需要告诉 EF 这是由数据库填充的列。如果您打开了.edmx
设计器,请选择有问题的列,然后查看其属性。您正在寻找的是属性 StoreGeneratedPattern,它可以设置为“None”(默认值)、“Computed”或“Identity”。
我不确定哪一个可以在 Oracle 中工作,但在 SQL Server 中,对于 identity
列(在插入行时由 SQL Server 自动递增),我总是设置 StoreGeneratedPattern=Identity
-在这种情况下,EF 不会为此列向数据库发送值,然后您的触发器应该会执行它的工作。
【讨论】:
【参考方案2】:您需要在该列的 .edmx
模型属性中为键列 (SYS_USER_ID) 将 StoreGeneratedPattern 设置为 Identity。如果将来您从 .edmx
模型中删除表并重新创建,则需要再次设置。
【讨论】:
以上是关于在使用 Entity Framework 数据库优先在表上插入行之前,如何从 PL/SQL 执行触发器?的主要内容,如果未能解决你的问题,请参考以下文章
在Oracle中使用Entity Framework 6 CodeFirst
在服务器中使用 Entity Framework 的 Migration 更新数据库