Wednesday, February 15, 2012

Why Can't LINQ Tell Me Where It Hurts?

I ran into an interesting issue with Linq to SQL today. Apparently if a table doesn't have a primary key, the data context can't write updates to it. This makes sense, of course, given that without a unique identifier the entity has no way to uniquely identify a record. That part didn't bother me. (The fact that the data modeler has tables without keys, or without constraints of any kind bothers me. But that's immaterial to this discussion.)

What bothered me was that the Linq entity code just silently failed. No errors, no nothing. The value was 1. I set it to 2. I checked that it's now 2. I submitted changes. Nothing. SQL Profiler shows that no UPDATE command was sent to the database. No error. Nothing.

What the crap, Microsoft?

After tracking down the bug and getting a primary key added to the table, I did a diff on the old auto-generated entity code vs. the new auto-generated entity code to see how the properties changed.  For comparison...

Entity property without a primary key:
public string Name
{
  get
  {
    return this._Name;
  }
  set
  {
    if ((this._Name!= value))
    {
      this._Name= value;
    }
  }
}

Entity property with a primary key:
public string Name
{
  get
  {
    return this._Name;
  }
  set
  {
    if ((this._Name!= value))
    {
      this.OnNameChanging(value);
      this.SendPropertyChanging();
      this._Name = value;
      this.SendPropertyChanged("Name");
      this.OnNameChanged();
    }
  }
}

So the code generator knows that there's no primary key. It uses a different template for the properties in response to this fact. So why can't they take it a step further and make the property a little more informative of this knowledge?

Something like this:
public string Name
{
  get
  {
    return this._Name;
  }
}

Or perhaps this:
public string Name
{
  get
  {
    return this._Name;
  }
  set
  {
    throw new SomeKindOfException("Can not update values on a read-only entity collection.");
  }
}

Or even this would be a step in the right direction:
/// 
/// Gets or sets the Name property.
/// NOTE: Entity collection is read-only, so updated property values
///       will NOT be saved to the underlying data source.
/// 
public string Name
{
  get
  {
    return this._Name;
  }
  set
  {
    if ((this._Name!= value))
    {
      this._Name= value;
    }
  }
}

Again... What the crap, Microsoft?

No comments:

Post a Comment