PetaPoco / Npgsql在使用表触发器插入时失败。
我认为这与PetaPoco insert fails on table with trigger非常相似,不同之处在于问题是针对SQL 2008而我的是 PostgreSQL 9.5.4 使用Npgsql C#驱动程序,其中包含一个表多个 触发器。我的情况是我在PostgreSQL中定义了多个触发器的表,如:
CREATE TABLE procedures
(
recid serial NOT NULL,
orderno integer NOT NULL,
torder timestamp without time zone NOT NULL DEFAULT now(),
cpt_recid integer NOT NULL,
dx_recid integer,
send_out boolean,
modified timestamp without time zone NOT NULL DEFAULT now(),
)
WITH (
OIDS=FALSE
);
ALTER TABLE procedures
OWNER TO postgres;
CREATE TRIGGER update_modified
BEFORE UPDATE
ON procedures
FOR EACH ROW
EXECUTE PROCEDURE update_modified();
CREATE TRIGGER zzz_get_next_order_number_trigger
BEFORE INSERT
ON procedures
FOR EACH ROW
EXECUTE PROCEDURE getnextorderno();
CREATE OR REPLACE FUNCTION getnextorderno()
RETURNS trigger AS
$BODY$
BEGIN
NEW.orderno := nextval('order_number_seq');
Return NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION getnextorderno()
OWNER TO postgres;
我的主要问题是PetaPoco database.Insert()坚持保存0和纪元时间而不是下一个orderno或当前时间。
是否可以对PetaPoco进行简单的更改,以尊重列上的DEFAULTS或允许触发器正常运行?
(我对PetaPoco很新)。
TIA
编辑#1根据建议的更改,该表现在如下所示。我仍然遇到的问题是 orderno仍然被0 填充,因此违反了唯一约束。
重复键值违反了唯一约束 “procedure_order_unique”键(orderno)=(0)已经存在。
正在从WCF服务调用PetaPoco插入:
p = new procedure
{
cpt_recid = cpt.recid,
chart_recid = _procedure.chart_recid,
dx_recid = _procedure.dx_recid,
torder = _procedure.torder,
on_return_to_office = _procedure.on_return_to_office,
send_out = _procedure.send_out,
standing_order = _procedure.standing_order,
stat = _procedure.stat,
tstop = _procedure.tstop,
isprocedure = _is_procedure
};
db.Insert(p);
CREATE TABLE procedures
(
recid serial NOT NULL,
orderno integer NOT NULL DEFAULT nextval('order_number_seq'::regclass),
torder timestamp without time zone NOT NULL DEFAULT now(),
cpt_recid integer NOT NULL,
dx_recid integer,
send_out boolean,
modified timestamp without time zone NOT NULL DEFAULT now(),
stat boolean,
standing_order boolean,
tstop timestamp without time zone,
on_return_to_office boolean,
chart_recid integer NOT NULL,
isprocedure boolean NOT NULL DEFAULT false,
is_deferred boolean,
CONSTRAINT procedures_pk PRIMARY KEY (recid),
CONSTRAINT procedures_chart_fk FOREIGN KEY (chart_recid)
REFERENCES charts (recid) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE RESTRICT,
CONSTRAINT procedures_cpt_fk FOREIGN KEY (cpt_recid)
REFERENCES cpt (recid) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE RESTRICT,
CONSTRAINT procedures_dx_fk FOREIGN KEY (dx_recid)
REFERENCES dx (recid) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE RESTRICT,
CONSTRAINT procedure_order_unique UNIQUE (orderno)
)
WITH (
OIDS=FALSE
);
ALTER TABLE procedures
OWNER TO postgres;
CREATE TRIGGER insert_modified
BEFORE INSERT
ON procedures
FOR EACH ROW
EXECUTE PROCEDURE update_modified();
CREATE TRIGGER update_modified
BEFORE UPDATE
ON procedures
FOR EACH ROW
EXECUTE PROCEDURE update_modified();
感谢您的帮助。
答案 0 :(得分:1)
您不需要订单号的触发器,只需在列上设置序列并删除触发器的需要。
正在保存修改,因为您的POCO修改属性不为null,因此它发送默认值。如果你想防止这种情况,你的修改后的触发器会在插入/更新之前同时运行。
BEFORE INSERT OR UPDATE
http://www.toptensoftware.com/petapoco/
文档说要使用主键修饰类定义:
[PetaPoco.PrimaryKey("orderno")]
要使用属性修改表格并修改T4模板,您需要为列id
命名。
PetaPoco会在插入时忽略它,并允许数据库处理它。
任何其他列名称将被假定为非主键,并且将发送默认值。
PostgreSQL和SQL Server将在插入时给出值,忽略SERIAL
和IDENTITY
列,就像场景中发生的那样。
答案 1 :(得分:0)
以Phill为主导(上图)并且不想更改PostgreSQL过程表本身,我发现以下内容正常:
“调整”PetaPoco Database.tt T4模板:
tables["procedures"]["orderno"].PropertyType="int?"; // Setting default value of orderno to null forces PostgreSQL trigger.
将触发程序更改为:
CREATE OR REPLACE FUNCTION getnextorderno()
RETURNS trigger AS
$BODY$
BEGIN
IF NEW.orderno is null THEN
NEW.orderno := nextval('order_number_seq');
END IF;
Return NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION getnextorderno()
OWNER TO postgres;
根据上面的Phill,如果使用值0,则将忽略触发器。