none
Not Reproducible? Type-matching columns exception when loading a saved XML schema from DataSet RRS feed

  • General discussion

  • I discovered a bug in .NET Framework. I posted a feedback on Microsoft Connect but their reply saying that the bug is not reproducible. I tried .NET Framework 3.5 SP1 and .NET Framework 2.0 and I can produce the bug in both framework. Could anyone help me to try out the following code and see if it works?

        Sub dataSetReadXMLError()
            Dim ds As New DataSet
            Dim dtP As DataTable
            Dim dtC As DataTable
            Dim dtPCol1 As DataColumn
            Dim dtPCol2 As DataColumn
            Dim dtCCol1 As DataColumn
            Dim dtCCol2 As DataColumn
            Dim parentPrimaryKey(1) As DataColumn
            Dim parentCols(1) As DataColumn
            Dim childCols(1) As DataColumn
    
            dtP = ds.Tables.Add("ParentTable")
            dtC = ds.Tables.Add("ChildTable")
            dtPCol1 = dtP.Columns.Add("Column1", GetType(Integer))
            dtPCol2 = dtP.Columns.Add("Column2", GetType(Decimal))
            dtCCol1 = dtC.Columns.Add("Column1", GetType(Integer))
            dtCCol2 = dtC.Columns.Add("Column2", GetType(Decimal))
    
            parentPrimaryKey(0) = dtPCol2
            parentPrimaryKey(1) = dtPCol1
            dtP.PrimaryKey = parentPrimaryKey
            parentCols(0) = dtPCol1
            parentCols(1) = dtPCol2
            childCols(0) = dtCCol1
            childCols(1) = dtCCol2
            ds.Relations.Add("ValidRelation", parentCols, childCols)
            ds.WriteXmlSchema("UnableToLoadSchema.xml")
            Dim dsAnother As New DataSet
            dsAnother.ReadXmlSchema("UnableToLoadSchema.xml")
        End Sub

    Feedback Post on Microsoft Connect: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=458267
    • Edited by Very Crazy Dog Friday, June 19, 2009 5:38 AM Put the code into code block.
    • Changed type Chris Robinson- MSFT Friday, June 19, 2009 3:15 PM Its a question that was answered
    • Changed type Very Crazy Dog Saturday, June 20, 2009 1:44 AM Seems someone changed the type?
    Friday, June 19, 2009 5:34 AM

All replies

  • I resolved your bug. In messed up a little bit. I indicated that you couldn't use Reset (which you can't) but then I didn't follow my own repro to verify the workaround I gave actually worked, sorry about that. I've found the issue with the code above.

    When the DataSet checks the contraints it checks it this way

     

     for (int i = 0; i < parentKey.ColumnsReference.Length; i++) {
                        if ((parentKey.ColumnsReference[i].DataType != childKey.ColumnsReference[i].DataType) ||
                            ((parentKey.ColumnsReference[i].DataType ==  typeof(DateTime)) && 
                            (parentKey.ColumnsReference[i].DateTimeMode != childKey.ColumnsReference[i].DateTimeMode) &&
                            ((parentKey.ColumnsReference[i].DateTimeMode & childKey.ColumnsReference[i].DateTimeMode) != DataSetDateTime.Unspecified)))
                            // alow unspecified and unspecifiedlocal
                            throw ExceptionBuilder.ColumnsTypeMismatch();
                    }

     

     


    You will notice that if compares the keys to the childkeys, well in your code here
           

    	parentPrimaryKey(0) = dtPCol2
            	parentPrimaryKey(1) = dtPCol1

    You set the second one first and the first one second, then in the relations code you set it the opposite way

    	parentCols(0) = dtPCol1
            	parentCols(1) = dtPCol2

    So when it does the compare it ends up comparing decimal to int which will fail.

    This code below will work

        Sub dataSetReadXMLError()
            Dim ds As New DataSet
            Dim dtP As DataTable
            Dim dtC As DataTable
            Dim dtPCol1 As DataColumn
            Dim dtPCol2 As DataColumn
            Dim dtCCol1 As DataColumn
            Dim dtCCol2 As DataColumn
            Dim parentPrimaryKey(1) As DataColumn
            Dim parentCols(1) As DataColumn
            Dim childCols(1) As DataColumn
            dtP = ds.Tables.Add("ParentTable")
            dtC = ds.Tables.Add("ChildTable")
            dtPCol1 = dtP.Columns.Add("Column1", GetType(Integer))
            dtPCol2 = dtP.Columns.Add("Column2", GetType(Decimal))
            dtCCol1 = dtC.Columns.Add("Column1", GetType(Integer))
            dtCCol2 = dtC.Columns.Add("Column2", GetType(Decimal))
            parentPrimaryKey(0) = dtPCol1
            parentPrimaryKey(1) = dtPCol2
            dtP.PrimaryKey = parentPrimaryKey
            parentCols(0) = dtPCol1
            parentCols(1) = dtPCol2
            childCols(0) = dtCCol1
            childCols(1) = dtCCol2
            ds.Relations.Add("ValidRelation", parentCols, childCols)
            ds.WriteXmlSchema("UnableToLoadSchema.xml")
            Dim ds2 As New DataSet()
            ds2.ReadXmlSchema("UnableToLoadSchema.xml")
        End Sub

    This will definitely fix the issue you brought up.

    Thanks,
    Chris Robinson
    Program Manager - DataSet





     


    This posting is provided "AS IS" with no warranties, and confers no rights.
    Friday, June 19, 2009 3:14 PM
  • Sorry but I don't think there is any bug in my code. The bug lies in the DataSet, not my code. Let me give you an example:

        Sub unableToAddRelation()
            Dim ds As New DataSet
            Dim dtP As DataTable
            Dim dtC As DataTable
            Dim dtPCol1 As DataColumn
            Dim dtCCol1 As DataColumn
    
            dtP = ds.Tables.Add("ParentTable")
            dtC = ds.Tables.Add("ChildTable")
            dtPCol1 = dtP.Columns.Add("Column1", GetType(Integer))
            dtCCol1 = dtC.Columns.Add("Column1", GetType(Decimal))
    
            dtP.PrimaryKey = New DataColumn() {dtPCol1}
            ds.Relations.Add("ValidRelation", dtPCol1, dtCCol1)
        End Sub
    

    The above code will throw an exception when I try to add an invalid relation to the DataSet.
    That means if the relation is successfully added, it is assumed the relation is a valid one.

    In my previous function "dataSetReadXMLError", relation is added without throwing any exception. That means before calling "WriteXmlSchema", all the code above are suppose to be valid!

    In addition, no one won't expect a successfully saved "Excel" document cannot be loaded when there is no file corruption, right?

    Furthermore, I can simplify reproduce the same problem in Dataset Designer. You can try.

    Your code definitely works, and that is what I am currently using. But sorry to say I can only consider the piece of code as a "workaround" instead of a solving the root of the problem.

    Have you ever investigate the reason for this problem without modifying my code?

    By the way, why I cannot use "Reset"? Your code works well if using "Reset".
    • Edited by Very Crazy Dog Saturday, June 20, 2009 2:07 AM Adding one more question.
    Saturday, June 20, 2009 1:42 AM

  • The code that I pasted before and will paste again shows why dataset will throw an exception (this is code in DataRelation)

    for (int i = 0; i < parentKey.ColumnsReference.Length; i++) {
                        if ((parentKey.ColumnsReference[i].DataType != childKey.ColumnsReference[i].DataType) ||
                            ((parentKey.ColumnsReference[i].DataType ==  typeof(DateTime)) &&
                            (parentKey.ColumnsReference[i].DateTimeMode != childKey.ColumnsReference[i].DateTimeMode) &&
                            ((parentKey.ColumnsReference[i].DateTimeMode & childKey.ColumnsReference[i].DateTimeMode) != DataSetDateTime.Unspecified)))
                            // alow unspecified and unspecifiedlocal
                            throw ExceptionBuilder.ColumnsTypeMismatch();
                    }

    What this code does is it verifies that the datatypes between the the two tables match. You cannot have a relationship between two tables with two columns that are different types. There is documentation on msdn that explicitly states this
    http://msdn.microsoft.com/en-us/library/system.data.datarelation.aspx

    Here is a quote from the documentation:"Relationships are created between matching columns in the parent and child tables. That is, the DataType value for both columns must be identical. "

    I guess what I would do in your situtation is change the integer column to decimal, I don't see anyway around this. This isn't a bug of dataset this is simply how its implemented. Let me say this again you cannot make relationships between columns that are of different types.

    From msdn documentation it was unclear to me what the heck Reset does, so I was trying to find a different solution. What I did was do a reset and I noticed that all the tables were still there so I figured that when ReadXmlSchema was loaded it threw because the existing schema was already there.

    Now the thing that interests me more about this scenario is that you mentioned excel. How does excel play into this scenario? Perhaps its based on the format of the columns? Maybe you can change the format of the Columns in excel and they will be different so that when things are read into a dataset you don't have to match up relationships to different types. I'm just guessing here though.

    Thanks
    Chris Robinson
    Program Manager - DataSet


    This posting is provided "AS IS" with no warranties, and confers no rights.
    Saturday, June 20, 2009 3:15 AM
  • Sorry but maybe you misunderstand my previous post. Anyway.

    1. I agree with your following statement.
    ... Let me say this again you cannot make relationships between columns that are of different types.

    2. "ds.Relations.Add("ValidRelation", dtPCol1, dtCCol1)" will throw exception, because relation on different types.

        Sub unableToAddRelation()
            Dim ds As New DataSet
            Dim dtP As DataTable
            Dim dtC As DataTable
            Dim dtPCol1 As DataColumn
            Dim dtCCol1 As DataColumn
    
            dtP = ds.Tables.Add("ParentTable")
            dtC = ds.Tables.Add("ChildTable")
            dtPCol1 = dtP.Columns.Add("Column1", GetType(Integer))
            dtCCol1 = dtC.Columns.Add("Column1", GetType(Decimal))
    
            dtP.PrimaryKey = New DataColumn() {dtPCol1}
            ds.Relations.Add("ValidRelation", dtPCol1, dtCCol1)
        End Sub
    
    
    3. Please forget about the Excel file. I just want to make an analogy.

    4. My argument is:

    Given (If everyone agree):
    If the relation cannot be made and is invalid,  it will throw exception when adding relation.
    Therefore
    If no exception is throw when adding relation, the relation can be made and is valid.

    If the XML schema can be saved, no exception will be throw when loading the XML schema.
    Therefore
    If exception is throw when loading the XML schema, the XML schema cannot be save.

    If the DataSet does not contains bugs, the above statements will be true.
    Therefore
    If any of the above statements is false, the DataSet contains bugs.

    Assume:
    The DataSet does not contains bugs

    Now in the following code:
    No exception is throw when adding relation.
    XML schema can be saved.
    Exception is throw when loading the XML schema.

    Therefore:
    The relation can be made and is valid.
    (XML schema can be saved.) implies (No exception will be throw when loading the XML schema.) which is contradicting with (Exception is throw when loading the XML schema.)
    One of the statement is contradicting.

    Therefore:
    The assumption is false.

    Therefore:
    The DataSet contains bugs.

        Sub dataSetReadXMLError()
            Dim ds As New DataSet
            Dim dtP As DataTable
            Dim dtC As DataTable
            Dim dtPCol1 As DataColumn
            Dim dtPCol2 As DataColumn
            Dim dtCCol1 As DataColumn
            Dim dtCCol2 As DataColumn
            Dim parentPrimaryKey(1) As DataColumn
            Dim parentCols(1) As DataColumn
            Dim childCols(1) As DataColumn
    
            dtP = ds.Tables.Add("ParentTable")
            dtC = ds.Tables.Add("ChildTable")
            dtPCol1 = dtP.Columns.Add("Column1", GetType(Integer))
            dtPCol2 = dtP.Columns.Add("Column2", GetType(Decimal))
            dtCCol1 = dtC.Columns.Add("Column1", GetType(Integer))
            dtCCol2 = dtC.Columns.Add("Column2", GetType(Decimal))
    
            parentPrimaryKey(0) = dtPCol2
            parentPrimaryKey(1) = dtPCol1
            dtP.PrimaryKey = parentPrimaryKey
            parentCols(0) = dtPCol1
            parentCols(1) = dtPCol2
            childCols(0) = dtCCol1
            childCols(1) = dtCCol2
            ds.Relations.Add("ValidRelation", parentCols, childCols)
            ds.WriteXmlSchema("UnableToLoadSchema.xml")
            Dim dsAnother As New DataSet
            dsAnother.ReadXmlSchema("UnableToLoadSchema.xml")
        End Sub
    

    5. Are you sure after "Reset" all the tables still exist? Trying the following:

        Sub dataSetReset()
            Dim ds As New DataSet
            Dim dtP As DataTable
            Dim dtC As DataTable
            Dim dtPCol1 As DataColumn
            Dim dtPCol2 As DataColumn
            Dim dtCCol1 As DataColumn
            Dim dtCCol2 As DataColumn
            Dim parentPrimaryKey(1) As DataColumn
            Dim parentCols(1) As DataColumn
            Dim childCols(1) As DataColumn
    
            dtP = ds.Tables.Add("ParentTable")
            dtC = ds.Tables.Add("ChildTable")
            dtPCol1 = dtP.Columns.Add("Column1", GetType(Integer))
            dtPCol2 = dtP.Columns.Add("Column2", GetType(Decimal))
            dtCCol1 = dtC.Columns.Add("Column1", GetType(Integer))
            dtCCol2 = dtC.Columns.Add("Column2", GetType(Decimal))
    
            parentPrimaryKey(0) = dtPCol2
            parentPrimaryKey(1) = dtPCol1
            dtP.PrimaryKey = parentPrimaryKey
            parentCols(0) = dtPCol1
            parentCols(1) = dtPCol2
            childCols(0) = dtCCol1
            childCols(1) = dtCCol2
            ds.Relations.Add("ValidRelation", parentCols, childCols)
            ds.WriteXmlSchema("UnableToLoadSchema.xml")
            ds.Reset()
            MsgBox("Table Count: " & ds.Tables.Count)
            MsgBox("Relation Count: " & ds.Relations.Count)
        End Sub

    Saturday, June 20, 2009 4:42 PM
  • So I think what you are saying is that you can add the relation initially, but then a schema that it outputs it cannot read back in. Is this correct? So yes this is techincally a bug.

    I understand your frustration here. I'm sorry the process took me this long to understand the issue. DataSet has a long set of issues that we are tackling. Given there is a simple workaround for this issue I would simply use this. We are focused on fixing issues that have no simple workarounds and major pain points for customers.

    Thanks
    Chris Robinson
    Program Manager - DataSet
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Sunday, June 21, 2009 2:11 AM
  • Yes that is what I am trying to say and why I report that to Microsoft Connect...

    Sorry but I think this bug is a major pain points for customers. The reason is show in the following code:

        Sub dataSetWithErrorData()
            Dim ds As New DataSet
            Dim dtP As DataTable
            Dim dtC As DataTable
            Dim dtPColHome As DataColumn
            Dim dtPColAddr As DataColumn
            Dim dtCColHome As DataColumn
            Dim dtCColAddr As DataColumn
            Dim parentPrimaryKey(1) As DataColumn
            Dim parentCols(1) As DataColumn
            Dim childCols(1) As DataColumn
    
            dtP = ds.Tables.Add("ParentTable")
            dtC = ds.Tables.Add("ChildTable")
            dtPColHome = dtP.Columns.Add("House Name", GetType(String))
            dtPColAddr = dtP.Columns.Add("Road Name", GetType(String))
            dtCColHome = dtC.Columns.Add("House Name", GetType(String))
            dtCColAddr = dtC.Columns.Add("Road Name", GetType(String))
    
            parentPrimaryKey(0) = dtPColAddr
            parentPrimaryKey(1) = dtPColHome
            dtP.PrimaryKey = parentPrimaryKey
            parentCols(0) = dtPColHome
            parentCols(1) = dtPColAddr
            childCols(0) = dtCColHome
            childCols(1) = dtCColAddr
            ds.Relations.Add("ValidRelation", parentCols, childCols)
            ds.WriteXmlSchema("ProblemSchema.xml")
            addRowToProblemSchema()
        End Sub
    
        Sub addRowToProblemSchema()
            Dim ds As New DataSet
    
            ds.ReadXmlSchema("ProblemSchema.xml")
            With ds.Tables("ParentTable").Rows
                .Add("Lucky House", "ABC Road")
                .Add("Farm House", "Farm Road")
            End With
            With ds.Tables("ChildTable").Rows
                .Add("Farm Road", "Farm House")
            End With
            printDataSet(ds)
        End Sub
    
        Sub printDataSet(ByVal ds As DataSet)
            For Each table As DataTable In ds.Tables
                Debug.Print("-------- " & table.TableName & " --------")
                Dim line As String = ""
                For Each column As DataColumn In table.Columns
                    line &= column.ColumnName & vbTab & "|" & vbTab
                Next
                Debug.Print(line)
                Debug.Print("============================")
                For Each row As DataRow In table.Rows
                    line = ""
                    For Each column As DataColumn In table.Columns
                        line &= row(column) & vbTab & "|" & vbTab
                    Next
                    Debug.Print(line)
                Next
            Next
        End Sub
    

    The output of the above code:

    -------- ParentTable --------
    House Name	|	Road Name	|	
    ============================
    Lucky House	|	ABC Road	|	
    Farm House	|	Farm Road	|	
    -------- ChildTable --------
    House Name	|	Road Name	|	
    ============================
    Farm Road	|	Farm House	|	

    For the above code:
    1. No exception is thrown.
    2. Relation can be created, and matching the "dtPColHome" to "dtCColHome" and "dtPColAddr" to "dtCColAddr".
    3. Invalid data is successfully added to the child DataSet at code ".Add("Farm Road", "Farm House")".
    4. Obviously in the child table, "Farm Road" is not a "House Name", and "Farm House" is not a "Raod Name"

    The workaround certainly works. But are you going to ask the customers take all the pain to figure out why the data is incorrect? Customers may not even know the the data is wrong if the columns is containing very similar data!

    Is that enough to convince that the bug should be fixed?

    I suggest that for each bug reported, the consequence of the bug should be analysis. A simple bug looks insignificant to one program may cause disaster in another program.
    Sunday, June 21, 2009 3:01 AM
  • Analyzing it further it appears the bug is more complex than you have indicated
        Sub addRowToProblemSchema()
            Dim ds As New DataSet

            ds.ReadXmlSchema("ProblemSchema.xml")
            With ds.Tables("ParentTable").Rows
                .Add("Lucky House", "ABC Road")
                .Add("Farm House", "Farm Road")
            End With
            With ds.Tables("ChildTable").Rows
                .Add("Farm Road", "Farm House")
                .Add("Farm House", "Farm Road")
            End With
            'printDataSet(ds)
        End Sub

    If you change the code to the following an exception will be thrown on the second insert to the ChildTable because it violates the constraint. It doesn't really violate the constraint assuming in the add that House Name is first and Road Name is second, somehow it has it switched around. This first operation should however.

    So from your connect bug there are two bugs then, the first is the schema related issue where it could not have been read back in from what it was set, this had a simple workaround, and then a second bug which is a constraint error with the data. I haven't looked into the code yet to analyze why this is occuring. So the original reason for the connect bug to me is not an issue (the schema issue) it has a simple workaround, the second part with the value is definitely a bug that needs to be reviewed, but that wasn't specified in the bug report. Its hard to do analysis on something unless its explicitly outlined like you did in this forum post.

    Thanks
    Chris Robinson
    Program Manager - DataSet


    This posting is provided "AS IS" with no warranties, and confers no rights.
    Monday, June 22, 2009 3:57 AM
  • Sorry to tell but it is not 2 bugs, just only 1. Why? Because the source of the problem is the same.

    The first problem I encountered is the bug that I posted in Microsoft Connect. I looked into the problem, and I know the cause of the problem and I can guess how to fix it in the DataSet. Because I know the cause of the problem, I know how it can be reproduced in what situation.

    I have high expectation and I was expecting a careful and completed investigation to the bug to locate the bug, estimate the serious level of the bug and fix the bug. So far I am disappointed.

    The reason why I did not report the "second part" of the bug is that I have already have a code that can produce the bug. I don't see any reason why I should write another code which can produce the same bug.

    Sorry but do I need to tell you where the bug is and my guess on how to fix the DataSet as well?
    Monday, June 22, 2009 12:17 PM
  • Actually I disagree, this is 2 bugs, there are 2 specific issues. If we decided to fix them there are two places in the code that would need to be fixed.

    Now that being said clearly I could have done a better job investigating this issue. I'm sorry for your disappointment in this matter. If you would like to take this up further we me, just review my profile and send me a message. If you are working on this app as part of a business and they have a relationship with Microsoft you can submit this problem to Customer support as a request for change.

    Thanks,
    Chris Robinson
    Program Manager
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Tuesday, June 23, 2009 4:30 PM
  • What is your bases of your disagreement? If you have investigated the two cases and concludes that there are two places in the code that need to be fixed, I have nothing much I can say as I cannot view the source code.

    For the follow up of the second bug, maybe I will create another bug report on Microsoft Connect.
    Wednesday, June 24, 2009 12:13 PM
  • Actually you can view the source code. Look around the net for a tool called .net Reflector. You can disassemble the code and just view the code directly. Perhaps you can try this. It can be difficult to follow though.

    File the connect bug and it will be put through our triage process.

    Thanks
    Chris Robinson,
    Program Manager - DataSet


    This posting is provided "AS IS" with no warranties, and confers no rights.
    Wednesday, June 24, 2009 5:11 PM
  • Well I already spent enough time for this so I am not going to look for the disassembled code. However still I believe that they are the same bug.

    Bug report filed on Microsoft Connect.
    Friday, June 26, 2009 3:38 PM
  • Well you will likely run into other issues not just with DataSet but in other areas, this is a helpful resource to me and would likely be a good resource for you as well.

    Thanks,
    Chris
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Friday, June 26, 2009 4:33 PM
  • Well although I did not use the .NET Reflector to look at the disassembled code of DataSet I used it on something else in my work. Well thanks for the suggestion.
    Saturday, December 5, 2009 4:44 AM