I recently had the opportunity to try out LINQ for SQL beta 2 in a real world (though still small scale) enterprise solution. It’s been a while since I took an early CTP for a spin, so I was excited to finally have a go.
I used the Domain Model tool integrated into VS 2008 to have tables mapped into partial classes automatically. That worked like a charm. If any of my observations apply only to the Domain Modelling tool, and not to LINQ2SQL in general, I apoligize in advance. I’m not (yet) a LINQ expert…
I’m often concerned about the restrictions that different O/R mappers impose on your freedom to keep a clean, simple and efficient class design (otherwise known as POCO / Plain Old Clr Objects). My first impressions of LINQ in this regard, are these:
1. I love the embedded query language, and the code completion is good.
2. Association properties cannot be read only, thus preventing immutable properties. Immutable classes or immutable properties are fundamental to creating a clean, domain driven design.
3. You cannot add [Attributes] to the autogenerated properties, since partial properties are not supported in C#3. So you cannot use Enterprise Library’s attribute based validation framework, or some custom framework that uses attributes as the only interface. Xml serialisation can be tricky as well.
4. Autogenerated fields do not follow MS naming conventions which says fields should be camel cased. A property called Horse will have a corrensponding field named _Horse. Not critical but not very pretty either.
5. Associations require an additional property to hold the foreign key value. It can be private, but not omitted. One to many associations always have a parent property, only the child collection is optional. This forces the domain model to include something, which is not an intrinsical part of the domain: Foreign key values. They are there only to satisfy LINQ, so the domain object end up not being very Persistence Ignorant.
6. Even non lazy loadable associations are wrapped in an EntityRef
7. The same goes for collections, which are always of a specific type, EntityCollection
8. Objects that are constructed within a query are tracked automatically. It took me a while to realize why too many rows were being inserted in the database: I had created some of them to be temporary, but LINQ tracked them all and found them to be transient, therefore inserting them into the database.
9. In order for tracking to work, your classes must implement INotifyPropertyChange. Yet another restriction on my classes. They started out pretty POCO, but it all adds up to a very non-POCO feel.
Conclusion: That’s all for the first day with LINQ 2 SQL. Possibly, more issues will surface along the way, without doubt. These first issues are worth being aware of, as O/R mappers can make your life easier (particularly in small scale projects.) And a lot more difficult (typically in larger projects.)