Search code examples
c#sql-serverforeign-keysnullreferenceexceptionone-liner

Is there a oneliner for ForeinKeyConstraint constructor?


I have this piece of code that I need to repeat a lot of times (dt_Areas and dt_Locations are DataTable objects):

ForeignKeyConstraint fkC = 
  new ForeignKeyConstraint(dt_Areas.Columns["Id"],
                           dt_Locations.Columns["AreaId"]);
fkC.DeleteRule = Rule.None;
fkC.UpdateRule = Rule.None;

In all cases, my DeleteRule and UpdateRule must be the same.

So I thought, let's look for a constructor, containing rule definitions too, which led me to this piece of code:

dt_Locations.Constraints.Add(
  new ForeignKeyConstraint("Location_Areas", 
                           "Areas",
                           "",
                           new string[]{ "AreaId" },
                           new string[] {"Id" }, 
                           AcceptRejectRule.None,
                           Rule.None,
                           Rule.None));

This does not work, due to a NullReferenceException referring to the Constraints property, so let's solve that issue:

dt_Locations.Constraints = new ConstraintCollection();
...

But this seems not to be allowed, as you can see from this build result:

error CS0200: Property or indexer 'DataTable.Constraints' cannot be assigned to --
it is read only

First of all, I don't understand where this is coming from: pressing F12 leads me to this piece of code:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[ResCategoryAttribute("DataCategory_Data")]
[ResDescriptionAttribute("DataTableConstraintsDescr")]
public ConstraintCollection Constraints { get; }

The property is public and the switches in the preceding lines don't show "read-only" (at least not that I understand).

So my question is: as I have quite a lot of tables to cover, how can I add a constraint at runtime, preferably using a one-liner?


Solution

  • To turn that code into a single statement, you just need an object initialiser:

    var fkC = 
      new ForeignKeyConstraint(dt_Areas.Columns["Id"],dt_Locations.Columns["AreaId"])
        { 
            DeleteRule = Rule.None, 
            UpdateRule = Rule.None 
        };
    

    ... and this piece of code makes it possible to add that constraint to the DataTable.Constraints property:

    dt_Locations.Constraints.Add(
      new ForeignKeyConstraint(dt_Areas.Columns["Id"], 
                               dt_Locations.Columns["AreaId"])
        { DeleteRule = Rule.None, 
          UpdateRule = Rule.None });
    

    (This is split over multiple lines for readability reasons, but it can be written as a one-liner very easy.)