Skip to main content
  1. Posts/

LINQ to SQL - code generation bug

··2 mins

The code generation performed by MSLinqToSQLGenerator or SQLMetal generates odd property code. For example, in AdventureWorks, the table Product has a column ProductLine. Using the tools that come with LINQ to SQL, this column translates to a property:

[Column(Storage="_ProductLine", DbType="NChar(2)")]
public string ProductLine
{
  get
  {
    return this._ProductLine;
  }
  set
  {
    if ((this._ProductLine != value)) {
      this.OnProductLineChanging(value);
      this.SendPropertyChanging();
      this._ProductLine = value;
      this.SendPropertyChanged("ProductLine");
      this.OnProductLineChanged();
    }
  }
}

The odd code involves the SendPropertyChanging() method call. This method call should pass the name of the property, just like the SendPropertyChanged() method call, according to the documentation. Another interesting detail: The OnProductLineChanging and OnProductLineChanged partial method calls are out of order:

  1. Call OnProductLineChanging() partial method
  2. Raise PropertyChanging event, but don’t tell which property is changing — send an empty string instead
  3. Set the property’s field’s value to the specified new value
  4. Raise PropertyChanged event and specify which property is changing
  5. Call OnProductLineChanged() partial method

Why is the PropertyChanged event raised before calling the OnProductLineChanged partial method?

All classes created by LINQ to SQL add the following protected methods:

protected virtual void SendPropertyChanging() {
  if ((this.PropertyChanging != null)) {
    this.PropertyChanging(this, emptyChangingEventArgs);
  }
}
protected virtual void SendPropertyChanged(String propertyName) {
  if ((this.PropertyChanged != null)) {
    this.PropertyChanged(this,
        new PropertyChangedEventArgs(propertyName));
  }
}

What’s odd is that SendPropertyChanging() has no property name parameter and sends an emptyChangingEventArgs field reference rather than creating a new instance like SendPropertyChanged() does. Here is the field passed to all invocations of the event:

private static PropertyChangingEventArgs emptyChangingEventArgs =
  new PropertyChangingEventArgs(String.Empty);

As you can see, the property that is changing is an empty string. Given that this is a private field that should not be modified by extension methods, it’s odd that this field is not static readonly.

My guess is that the code is generated incorrectly to account for a data-binding or allocation problem. The emptyChangingEventArgs field reduces object instance creation in half for each property change when there are event consumers for the changing event. The big disadvantage is that event consumers don’t know which property is changing.

One alternative is to use PLINQO, which creates the properties correctly.

UPDATE: I have found that this has already been reported. Unfortunately, Microsoft has closed this bug as by design, even though the generated code does not follow Microsoft’s documentation for the PropertyChangingEventArgs class.

George Tsiokos
Author
George Tsiokos

Leave a comment

Preview

Comments are reviewed before publishing.