October 07, 2003
Designing Typed DataSets in Visual C#'s XML Designer

These are my personal notes for designing typed datasets in Visual C#.NET's XML Designer.

Naming Conventions


  • Name your dataset file and your dataSetName with the "Set" postfix, e.g. CustomerSet.xsd
  • Pluralize the name of your Table elements, e.g. Customers
  • Capitalize the names of your elements, which corresponds to DB Schema conventions although XML elements tend to be lower-cased.

Inserting New Rows Into a Typed DataSet


The Visual Studio documentation is incorrect where it explains how to insert new rows into a typed dataset.
It gives the example:
// C#
DataRow anyRow = DatasetName.ExistingTable.NewRow();
anyRow.FirstName = "Jay";
anyRow.LastName = "Stevens";
ExistingTable.Rows.Add(anyRow);
But this is incorrect as the DataRow type is generic and does not contain the FirstName or LastName fields. A more specific type and a cast are necessary, as in:
// C#
ExistingDataSet.ExistingTableRow anyRow =
(ExistingDataSet.ExistingTableRow) DatasetName.ExistingTable.NewRow();
anyRow.FirstName = "Jay";
anyRow.LastName = "Stevens";
ExistingTable.Rows.Add(anyRow);
But if it's going to be this complicated, you might as well follow the alternative instructions that work for both untyped and typed datasets. See the documentation.

Inserting Related Rows Into Related Tables


If you create an XML Schema that has 2 tables in a parent-child relationship, then a DataRelation will be automatically created for you by Designer. You won't see it, but a column in the child table will automatically be created for a foreign key to match up with the primary key in the parent table. The question is: how do you insert a new row into both tables so that the relationship is maintained? Do the following in the specific order:
  1. Create the parent row, set the column values, and add it to the parent table
  2. Create the child row, set the column values
  3. Call SetParent() on the child row with the parent as the argument, e.g. childRow.SetParent(parentRow)
  4. Add the child row

I could not find how to do this in the documentation either.

Assigning a DataSource to a DataView at run-time


If a DataSource is created at run-time in the Text Editor as opposed to design time in the Designer, and you want to have a DataView associated with it, this DataView should also be initialized at run-time. The problem is if you assign the source to the DataView after its EndInit() method is called, then RowFilter won't work.

Posted by juliob at 01:54 AM
October 04, 2003
Visual C# .NET Gotchas

Design Gotchas


  • Properties of New project: When creating a new project that will be referred to by the main project in your solution, you might wonder what properties can be customized so as to keep the projects more cohesive. The following might be obvious to you but not to a novice like me: the default namespace property can be set to be the same as the main project's; however, the assembly name has to be unique.
  • Typed DataSet in a Separate Project: Separating your code into separate projects can have unexpected consequences. When you create a typed dataset by designing an XML Schema using the built-in XML Designer, you would expect your dataset to be listed as a referenced Typed DataSet when dragging the Dataset icon from the Toolbox onto a form. This does happen if the dataset and the form are in the same project. But if they're in separate projects, you won't be able to find it, even after you've properly added a reference to the dataset's project. What is not explained in the documentation is that you will need to build the dataset's project first, before it will listed by "Referenced Datasets..." in the drop-down.
  • Disappearing User Controls from Separate Project: If you define a user control in a separate project, you might suffer from disappearing control instances when building. Take the situation where you define a new user control in a project separate from your main form's project. Assume you already had a proper reference from the main form's project to this separate control project. If your main form contains an instance of your new user control and you rebuild, you might see the control instance disappear in front of your eyes. What you need to do to fix this problem is delete the reference and re-create it. This might even be considered a bug.
  • Missing Form Resize Handles: If you have a user control that takes up all the space of your form, you won't be able to find the resize handles of either the form or the occupying control. So how do you resize them? No idea. Just avoid letting controls take up all the space in the form in the first place; leave a bit of margin at least on one side.

Visual Studio .NET 2002 Bugs


These are some of the annoying bugs that I encountered when using this 7.0 version of Microsoft Visual Studio .NET.
  • Intelli-non-sense: As you're typing code into the text editor, Visual Studio (VS) sometimes seems to lose track of how to parse it. What happens is that all the syntax coloring disappears and Intellisense's completion features stop functioning. I'm not exactly sure what triggers this annoying behavior.
  • Designer code corruption: Once in a while, VS will actually corrupt code. Stupidly, but fortunately, it seems to only corrupt its own designer-generated code. For example,
    this.button2.Anchor = (System.Windows.Forms.AnchorStyles.Bottom |
    System.Windows.Forms.AnchorStyles.Right);

    will become
    this.button2.Anchor = (System.Windows.Forms.AnchorStyles.Bottom |
    stem.Windows.Forms.AnchorStyles.Right);

    You find out when you compile and get a syntax error.
  • TabControl in Designer: Designer has the nice feature that allows you to click on TabPages of a TabControl as it would behave at run-time. You can even click on the left and right arrows. But somtimes, the TabControl stops working and you can no longer scroll through or click on the tabs.
  • Failed compilation due to locked DLL: Sometimes it takes two consecutive compilations to get the solution buil because the compiler says that the DLL is lockedt. This can happen if the Object Browser is opened. So just close it.

Posted by juliob at 10:01 PM
C# Language Notes

Exploring C# from a background of C++ and Java, I found that most C# language features are fairly intuitive. Here's a list of issues that I found to be exceptions.

Confusing Distinctions


  • readonly vs. const: The difference between readonly and const is not explained clearly in the VS.NET documentation. It makes more sense once you realize that const is inlined at compile-time while readonly is evaluated at run-time. See the excellent Comparative Overview of C#.
  • event vs. delegate: Another distinction is not made clear by the documentation, this time between an event and a delegate-typed object. The article C# events vs. delegates does a great job of clarifying the differences.
  • Destructors vs. Finalize(): I'm still not sure of the exact difference between a destructor and the Finalize() method. One functional distinction is that the destructor automatically invokes the base's destructor. In light of that, it makes sense that a Finalize() method can be found on the Object class since the Object class has no base class. But are we supposed to write destructors or a Finalize() in our classes?
    It seems that the recommendation for user classes is to write destructors. But I notice that the Finalize() method is mentioned in classes other than the Object class. So which is it?

C# vs. Java Quick Reference


Here are some comparisons between the two similar languages that are not mentioned by the article Comparative Overview of C#.
  • Types:In Java, to get a Class object, you use either Class.forName("ClassNameString") or object.GetClass(). You can then call getName() or toString() on the Class object to get the name in string form. In C#, to get a Type object, you use either typeof(ClassNameString) or object.GetType(), which unlike Java work on primitive types as well. You can then reference properties Name or FullName or call ToString() on the Type object to get the name in string form.
  • As:From the documentation:
    The as operator is like a cast except that it yields null on conversion failure instead of raising an exception. More formally, an expression of the form:
    expression as type
    is equivalent to:
    expression is type ? (type)expression : (type)null
    except that expression is evaluated only once.

Posted by juliob at 09:36 PM
License:
Creative Commons License