Serialization Mode = Unidirectional Causes Unnecessary Query
Posted: Thu 05 May 2011 21:09
Here's the example to produce the bug...
Tables:
ParentTable
ChildInsertTable
ChildOtherTable
Dim dc As New Data.TestDataContext()
databaseMonitor.IsActive = True
Dim parent = dc.Parenttables.FirstOrDefault()
Dim insert As New Data.Childinserttable()
parent.Childinserttables.Add(insert)
insert.Mydata = "My Insert"
dc.SubmitChanges()
If Serialization Mode = Unidirectional then, for no apparent reason, the above code will perform a query of Childothertable as follows
SELECT t1.ID, t1.MYDATA, t1.PARENTTABLEID
FROM ZSESSARY.CHILDOTHERTABLE t1
WHERE :np0 = t1.PARENTTABLEID
where paremeter :np0 is the PK of parent.
However, if you leave the default Serialization Mode = None, this pointless query is not performed.
I can email a solution demonstrating the issue. The SQL to generate my example schema is posted at the end.
One of my team members is doing work that requires serialization of the data objects, but pointlessly querying hundreds or even hundreds of thousands of child records is not going to work for us.
Thanks,
Zach
/*
-- Drop talbes and values
DROP TABLE PARENTTABLE CASCADE CONSTRAINTS PURGE;
DROP TABLE CHILDINSERTTABLE CASCADE CONSTRAINTS PURGE;
DROP TABLE CHILDOTHERTABLE CASCADE CONSTRAINTS PURGE;
-- Drop sequences
DROP SEQUENCE PARENTTABLE_SEQ;
DROP SEQUENCE CHILDINSERTTABLE_SEQ;
DROP SEQUENCE CHILDOTHERTABLE_SEQ;
*/
-- Create the Tables
CREATE TABLE parenttable (
id INTEGER PRIMARY KEY,
mydata VARCHAR2(50) NOT NULL
);
CREATE TABLE childinserttable (
id INTEGER PRIMARY KEY,
mydata VARCHAR2(50) NOT NULL,
parenttableid NUMBER NOT NULL,
CONSTRAINT parenttable_childinserttable
FOREIGN KEY (parenttableid)
REFERENCES parenttable (id)
);
CREATE TABLE childothertable (
id INTEGER PRIMARY KEY,
mydata VARCHAR2(50) NOT NULL,
parenttableid NUMBER NOT NULL,
CONSTRAINT parenttable_childothertable
FOREIGN KEY (parenttableid)
REFERENCES parenttable (id)
);
-- Create the Sequences
CREATE SEQUENCE PARENTTABLE_SEQ NOCACHE START WITH 2;
CREATE SEQUENCE CHILDINSERTTABLE_SEQ NOCACHE START WITH 2;
CREATE SEQUENCE CHILDOTHERTABLE_SEQ NOCACHE START WITH 4;
-- Create the Triggers
CREATE TRIGGER PARENTTABLE_BEFORE_INSERT
BEFORE INSERT ON PARENTTABLE FOR EACH ROW
BEGIN
-- If not provided, auto-generate ID
IF :NEW.ID IS NULL THEN
SELECT PARENTTABLE_SEQ.NEXTVAL
INTO :NEW.ID FROM DUAL;
END IF;
END;
/
CREATE TRIGGER CHILDINSERTTABLE_BEFORE_INSERT
BEFORE INSERT ON CHILDINSERTTABLE FOR EACH ROW
BEGIN
-- If not provided, auto-generate ID
IF :NEW.ID IS NULL THEN
SELECT CHILDINSERTTABLE_SEQ.NEXTVAL
INTO :NEW.ID FROM DUAL;
END IF;
END;
/
CREATE TRIGGER CHILDOTHERTABLE_BEFORE_INSERT
BEFORE INSERT ON CHILDOTHERTABLE FOR EACH ROW
BEGIN
-- If not provided, auto-generate ID
IF :NEW.ID IS NULL THEN
SELECT CHILDOTHERTABLE_SEQ.NEXTVAL
INTO :NEW.ID FROM DUAL;
END IF;
END;
/
-- Insert initial Values
INSERT INTO PARENTTABLE VALUES (1, 'Parent Value 1');
INSERT INTO CHILDINSERTTABLE VALUES (1, 'Insert Value 1', 1);
INSERT INTO CHILDOTHERTABLE VALUES (1, 'Other Value 1', 1);
INSERT INTO CHILDOTHERTABLE VALUES (2, 'Other Value 2', 1);
INSERT INTO CHILDOTHERTABLE VALUES (3, 'Other Value 3', 1);
Tables:
ParentTable
ChildInsertTable
ChildOtherTable
Dim dc As New Data.TestDataContext()
databaseMonitor.IsActive = True
Dim parent = dc.Parenttables.FirstOrDefault()
Dim insert As New Data.Childinserttable()
parent.Childinserttables.Add(insert)
insert.Mydata = "My Insert"
dc.SubmitChanges()
If Serialization Mode = Unidirectional then, for no apparent reason, the above code will perform a query of Childothertable as follows
SELECT t1.ID, t1.MYDATA, t1.PARENTTABLEID
FROM ZSESSARY.CHILDOTHERTABLE t1
WHERE :np0 = t1.PARENTTABLEID
where paremeter :np0 is the PK of parent.
However, if you leave the default Serialization Mode = None, this pointless query is not performed.
I can email a solution demonstrating the issue. The SQL to generate my example schema is posted at the end.
One of my team members is doing work that requires serialization of the data objects, but pointlessly querying hundreds or even hundreds of thousands of child records is not going to work for us.
Thanks,
Zach
/*
-- Drop talbes and values
DROP TABLE PARENTTABLE CASCADE CONSTRAINTS PURGE;
DROP TABLE CHILDINSERTTABLE CASCADE CONSTRAINTS PURGE;
DROP TABLE CHILDOTHERTABLE CASCADE CONSTRAINTS PURGE;
-- Drop sequences
DROP SEQUENCE PARENTTABLE_SEQ;
DROP SEQUENCE CHILDINSERTTABLE_SEQ;
DROP SEQUENCE CHILDOTHERTABLE_SEQ;
*/
-- Create the Tables
CREATE TABLE parenttable (
id INTEGER PRIMARY KEY,
mydata VARCHAR2(50) NOT NULL
);
CREATE TABLE childinserttable (
id INTEGER PRIMARY KEY,
mydata VARCHAR2(50) NOT NULL,
parenttableid NUMBER NOT NULL,
CONSTRAINT parenttable_childinserttable
FOREIGN KEY (parenttableid)
REFERENCES parenttable (id)
);
CREATE TABLE childothertable (
id INTEGER PRIMARY KEY,
mydata VARCHAR2(50) NOT NULL,
parenttableid NUMBER NOT NULL,
CONSTRAINT parenttable_childothertable
FOREIGN KEY (parenttableid)
REFERENCES parenttable (id)
);
-- Create the Sequences
CREATE SEQUENCE PARENTTABLE_SEQ NOCACHE START WITH 2;
CREATE SEQUENCE CHILDINSERTTABLE_SEQ NOCACHE START WITH 2;
CREATE SEQUENCE CHILDOTHERTABLE_SEQ NOCACHE START WITH 4;
-- Create the Triggers
CREATE TRIGGER PARENTTABLE_BEFORE_INSERT
BEFORE INSERT ON PARENTTABLE FOR EACH ROW
BEGIN
-- If not provided, auto-generate ID
IF :NEW.ID IS NULL THEN
SELECT PARENTTABLE_SEQ.NEXTVAL
INTO :NEW.ID FROM DUAL;
END IF;
END;
/
CREATE TRIGGER CHILDINSERTTABLE_BEFORE_INSERT
BEFORE INSERT ON CHILDINSERTTABLE FOR EACH ROW
BEGIN
-- If not provided, auto-generate ID
IF :NEW.ID IS NULL THEN
SELECT CHILDINSERTTABLE_SEQ.NEXTVAL
INTO :NEW.ID FROM DUAL;
END IF;
END;
/
CREATE TRIGGER CHILDOTHERTABLE_BEFORE_INSERT
BEFORE INSERT ON CHILDOTHERTABLE FOR EACH ROW
BEGIN
-- If not provided, auto-generate ID
IF :NEW.ID IS NULL THEN
SELECT CHILDOTHERTABLE_SEQ.NEXTVAL
INTO :NEW.ID FROM DUAL;
END IF;
END;
/
-- Insert initial Values
INSERT INTO PARENTTABLE VALUES (1, 'Parent Value 1');
INSERT INTO CHILDINSERTTABLE VALUES (1, 'Insert Value 1', 1);
INSERT INTO CHILDOTHERTABLE VALUES (1, 'Other Value 1', 1);
INSERT INTO CHILDOTHERTABLE VALUES (2, 'Other Value 2', 1);
INSERT INTO CHILDOTHERTABLE VALUES (3, 'Other Value 3', 1);