Bugzilla – Bug 316424
XSD generates wrong code for ForeignKeyConstraints in typed datasets
Last modified: 2007-09-15 21:24:23 UTC
---- Reported by martin.voelkle@epfl.ch 2004-11-09 11:00:28 MST ---- Description of Problem: When generating a typed dataset from a schema file which contains foreign key constraints, the resulting code is wrong. Steps to reproduce the problem: 1. Here is a simple schema with 2 relations (foreign key constraints) <?xml version="1.0" standalone="yes"?> <xs:schema xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="MyDataSet" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="MyDataSet" msdata:IsDataSet="true" msdata:Locale=""> <xs:complexType> <xs:choice maxOccurs="unbounded"> <xs:element name="Playlists"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" name="name" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="PlaylistsItems"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" name="playlist" type="xs:string" /> <xs:element minOccurs="0" name="position" type="xs:int" /> <xs:element minOccurs="0" name="file" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Files"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" name="name" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> </xs:choice> </xs:complexType> <xs:unique name="PlaylistsPkey" msdata:PrimaryKey="true"> <xs:selector xpath=".//Playlists" /> <xs:field xpath="name" /> </xs:unique> <xs:unique name="PlaylistsItemsPkey" msdata:PrimaryKey="true"> <xs:selector xpath=".//PlaylistsItems" /> <xs:field xpath="playlist" /> <xs:field xpath="position" /> </xs:unique> <xs:unique name="FilesPkey" msdata:PrimaryKey="true"> <xs:selector xpath=".//Files" /> <xs:field xpath="name" /> </xs:unique> <xs:keyref refer="PlaylistsPkey" name="Relation1"> <xs:selector xpath=".//PlaylistsItems" /> <xs:field xpath="playlist" /> </xs:keyref> <xs:keyref refer="FilesPkey" name="Relation2"> <xs:selector xpath=".//PlaylistsItems" /> <xs:field xpath="file" /> </xs:keyref> </xs:element> </xs:schema> 2. Generate the dataset xsd schema.xsd /dataset 3. Try to use the generated class public class MyClass { public static void Main(string[] args) { MyDataSet data = new MyDataSet(); } } Actual Results: Unhandled Exception: System.ArgumentException: Neither ParentColumns or ChildColumns can't be zero length. in <0x000af> System.Data.ForeignKeyConstraint:_validateColumns (System.Data.DataColumn[],System.Data.DataColumn[]) in <0x00014> System.Data.ForeignKeyConstraint:_foreignKeyConstraint (string,System.Data.DataColumn[],System.Data.DataColumn[]) in <0x00047> System.Data.ForeignKeyConstraint:.ctor (string,System.Data.DataColumn[],System.Data.DataColumn[]) in <0x003e1> Prometheus.Data:InitializeClass () in <0x00024> Prometheus.Data:.ctor () in <0x00025> Prometheus.Test:Main (string[]) Expected Results: No error How often does this happen? Always Additional Information: By looking at the generated file, the problem is here (for Relation1): fkc = new System.Data.ForeignKeyConstraint("Relation1", new System.Data.DataColumn[] { this.__tablePlaylistsItems.Columns["playlist"], this.__tablePlaylistsItems.Columns["name"]}, new System.Data.DataColumn[0]); and should be fkc = new System.Data.ForeignKeyConstraint("Relation1", new System.Data.DataColumn[] { this.__tablePlaylistsItems.Columns["name"], new System.Data.DataColumn[] { this.__tablePlaylistsItems.Columns["playlist"]}); Looking in mono's source code, I found the error. Here is the patch: --- class/System.Data/System.Data/CustomDataClassGenerator.old.cs 2004-11-09 15:39:48.000000000 +0100 +++ class/System.Data/System.Data/CustomDataClassGenerator.cs 2004-11-09 15:41:00.000000000 +0100 @@ -759,12 +759,12 @@ namespace System.Data private void CreateForeignKeyStatements (CodeMemberMethod m,ForeignKeyConstraint fkc, string tableField) { ArrayList pcols = new ArrayList (); - foreach (DataColumn col in fkc.Columns) + foreach (DataColumn col in fkc.RelatedColumns) pcols.Add (IndexerRef (PropRef (FieldRef (tableField), "Columns"), Const (col.ColumnName))); ArrayList ccols = new ArrayList (); - foreach (DataColumn col in fkc.RelatedColumns) - pcols.Add (IndexerRef (PropRef (FieldRef (tableField), "Columns"), Const (col.ColumnName))); + foreach (DataColumn col in fkc.Columns) + ccols.Add (IndexerRef (PropRef (FieldRef (tableField), "Columns"), Const (col.ColumnName))); m.Statements.Add (Let (Local ("fkc"), New ( typeof (ForeignKeyConstraint), --- class/System.Data/System.Data/CustomDataClassGenerator.old.cs 2004-11-09 15:39:48.000000000 +0100 +++ class/System.Data/System.Data/CustomDataClassGenerator.cs 2004-11-09 15:41:00.000000000 +0100 @@ -759,12 +759,12 @@ namespace System.Data private void CreateForeignKeyStatements (CodeMemberMethod m,ForeignKeyConstraint fkc, string tableField) { ArrayList pcols = new ArrayList (); - foreach (DataColumn col in fkc.Columns) + foreach (DataColumn col in fkc.RelatedColumns) pcols.Add (IndexerRef (PropRef (FieldRef (tableField), "Columns"), Const (col.ColumnName))); ArrayList ccols = new ArrayList (); - foreach (DataColumn col in fkc.RelatedColumns) - pcols.Add (IndexerRef (PropRef (FieldRef (tableField), "Columns"), Const (col.ColumnName))); + foreach (DataColumn col in fkc.Columns) + ccols.Add (IndexerRef (PropRef (FieldRef (tableField), "Columns"), Const (col.ColumnName))); m.Statements.Add (Let (Local ("fkc"), New ( typeof (ForeignKeyConstraint), Yes, the only problem is not only that all the columns were added to the same ArrayList, but also that the parent columns are the related ones. ---- Additional Comments From martin.voelkle@epfl.ch 2004-11-09 11:50:36 MST ---- Created an attachment (id=167016) Last patch was incorrect, here is an improved version (untested) ---- Additional Comments From atsushi@ximian.com 2004-11-10 06:14:33 MST ---- Applied your patch with a tiny fix. Thanks! ---- Additional Comments From notzcoolx@yahoo.es 2005-04-10 16:59:08 MST ---- Created an attachment (id=167017) Patch to add the constraint relations to the generated DataSet ---- Additional Comments From notzcoolx@yahoo.es 2005-04-10 17:03:09 MST ---- I've added a patch that add the unknown relations and the foreing keys relations to the generated DataSet. The old behaviour didn't add them and breaks the Row methods that returns child or parent rows from the related table. I've tested in my installation and it works as expected, I've also test mono class libraries and passes all the tests (well, i think, it says '58 correctly detected errors (93.55 %)'). ---- Additional Comments From notzcoolx@yahoo.es 2005-04-10 18:46:06 MST ---- Created an attachment (id=167018) Sorry, previous patch was wrong. I hope this one is OK. ---- Additional Comments From atsushi@ximian.com 2005-04-12 02:03:32 MST ---- Daniel, can you please attach an example case that differentiates the results? And please enter different bug report that is independent to other bugs, next time (the original bug reporter will receive those updates every time, while he or she has nothing to do with another bug). ---- Additional Comments From notzcoolx@yahoo.es 2005-04-12 21:28:15 MST ---- Created an attachment (id=167019) Simple XSD DataSet Schema ---- Additional Comments From notzcoolx@yahoo.es 2005-04-12 21:29:19 MST ---- Created an attachment (id=167020) Foreign Key DataSet Test Case ---- Additional Comments From notzcoolx@yahoo.es 2005-04-12 21:32:40 MST ---- Here you have a simple testcase (xsd + cs). It should output "It worked..." with my patch applied (and in .Net too) or "It failed..." before applying my patch. Sorry about not opening another bug, I though this one was related to mine. ---- Additional Comments From atsushi@ximian.com 2005-04-13 06:56:47 MST ---- Fixed in svn. Thanks! Imported an attachment (id=167016) Imported an attachment (id=167017) Imported an attachment (id=167018) Imported an attachment (id=167019) Imported an attachment (id=167020)