Thursday, December 17, 2009

Linq2SQL Bug with derived classes and Calculated fields

Today I discovered a bug in Linq2SQL. When you define a class hierarchy in dbml, where you derive a class from a base Class, and both use the same underlying table, and a discriminator property, as shown below:

derived_dbml

If you then wish to expose a calculated field in the derived class, (and trust me I have come across situations where this is a requirement), you will find that Linq2SQL throws an exception when you attempt to insert or update items of the derived class to the database.

The exception is as follows

Test method DerivedClassTest.DerivedClassTest.TestInsert threw exception:  System.ArgumentException: Property 'System.String CalculatedField' is not defined for type 'DerivedClassTest.BaseCLass'.

This bug occurs deep within the Linq2SQL logic, and is to do with the AutoSync functionality where Linq2SQL attempts to create a select statement to return the values of AutoSync fields at the same time as it performs the insert.

You may be able to work around this by setting the AutoSync property on the Column Attribute to “Never” as shown below

[Column(Storage="_CalculatedField", AutoSync=AutoSync.Never, DbType="NVarChar(61)", IsDbGenerated=true, UpdateCheck=UpdateCheck.Never)]
        public string CalculatedField

And note that setting this in the designer doesn’t seem to work either, it just removes the AutoSync parameter all together, but still fails. You manually have to set it in the generated code (another bug perhaps?).

Of course this means that you won’t get the new value of the field after an insert or update to the table, and you’ll have to re-query the table if you need it.

The alternative workaround is to ensure that all calculated fields are placed on the base class.

No comments:

Post a Comment