PetaPoco 插入在 PostgreSQL 中具有多个触发器的表上失败
PetaPoco insert fails on tables with multiple triggers in PostgreSQL
PetaPoco/Npgsql 使用 table 触发器插入失败。
我认为这与 PetaPoco insert fails on table with trigger 非常相似,不同之处在于该问题针对的是 SQL 2008 而我的问题针对的是 PostgreSQL 9.5.4 使用带有 table 的 Npgsql C# 驱动程序 多个 触发器。 我的情况是 tables 在 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 和纪元时间而不是下一个订单号或当前时间。
是否可以对 PetaPoco 进行简单的更改以遵守列上的默认值或允许触发器正常运行?
(我对 PetaPoco 很陌生)。
TIA
编辑#1 按照提议的更改,table 现在看起来如下所示。我仍然遇到的问题是 orderno 仍然被 0 填充,因此违反了唯一约束。
duplicate key value violates unique constraint
"procedure_order_unique" Key (orderno)=(0) already exists.
PetaPoco 插入从 WCF 服务调用为:
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();
感谢您的帮助。
您不需要订单号的触发器,只需在列上设置顺序并删除触发器的需要。
正在保存修改,因为您修改的 POCO 属性 不为空,因此它正在发送默认值。如果你想防止这种情况发生,请在插入前/更新前对两者进行修改后的触发器 运行。
BEFORE INSERT OR UPDATE
http://www.toptensoftware.com/petapoco/
文档说用主键修饰 class 定义:
[PetaPoco.PrimaryKey("orderno")]
要避免使用属性装饰 table 和修改 T4 模板,您需要将列命名为 id
。
PetaPoco 将在插入时忽略它并允许数据库处理它。
任何其他列名都将被假定为非主键,并且将发送默认值。
PostgreSQL 和 SQL 服务器都将忽略 SERIAL
和 IDENTITY
列,当在插入时给出值就像您的场景中发生的那样。
在 Phill 的带领下(上图)并且不想更改 PostgreSQL 过程 table 本身,我发现以下工作正常:
"Tweak" 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,触发器将被忽略。
PetaPoco/Npgsql 使用 table 触发器插入失败。
我认为这与 PetaPoco insert fails on table with trigger 非常相似,不同之处在于该问题针对的是 SQL 2008 而我的问题针对的是 PostgreSQL 9.5.4 使用带有 table 的 Npgsql C# 驱动程序 多个 触发器。 我的情况是 tables 在 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 和纪元时间而不是下一个订单号或当前时间。
是否可以对 PetaPoco 进行简单的更改以遵守列上的默认值或允许触发器正常运行?
(我对 PetaPoco 很陌生)。
TIA
编辑#1 按照提议的更改,table 现在看起来如下所示。我仍然遇到的问题是 orderno 仍然被 0 填充,因此违反了唯一约束。
duplicate key value violates unique constraint "procedure_order_unique" Key (orderno)=(0) already exists.
PetaPoco 插入从 WCF 服务调用为:
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();
感谢您的帮助。
您不需要订单号的触发器,只需在列上设置顺序并删除触发器的需要。
正在保存修改,因为您修改的 POCO 属性 不为空,因此它正在发送默认值。如果你想防止这种情况发生,请在插入前/更新前对两者进行修改后的触发器 运行。
BEFORE INSERT OR UPDATE
http://www.toptensoftware.com/petapoco/
文档说用主键修饰 class 定义:
[PetaPoco.PrimaryKey("orderno")]
要避免使用属性装饰 table 和修改 T4 模板,您需要将列命名为 id
。
PetaPoco 将在插入时忽略它并允许数据库处理它。
任何其他列名都将被假定为非主键,并且将发送默认值。
PostgreSQL 和 SQL 服务器都将忽略 SERIAL
和 IDENTITY
列,当在插入时给出值就像您的场景中发生的那样。
在 Phill 的带领下(上图)并且不想更改 PostgreSQL 过程 table 本身,我发现以下工作正常:
"Tweak" 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,触发器将被忽略。