(when migrating from SQL Designer)
History:
For the past 1.5 years our team has developed HIT (Healthcare IT) LOB (line of business) software using DLINQ SQL Designer. The experience has been pleasant from a tooling perspective except for the reasons that are frequently blogged about, namely DBDesigner results in SVN conflicts when 2 people make changes to the model.
We have a few large DB’s – one is about 9 years old and has hundreds of tables (600+) and even more views plus hundreds if not thousands of SPROC’s (many of which are complex)
We have 3 such DB’s. (each w/ their own pain)
Consider a common use:
More than 1 developer is making changes to a shared relational database (adding/changing tables, sprocs or functions). Changes are made by Developer A & Developer B and then both try to check in. SVN detects a conflict – given that the code is generated, resolving the conflict is *not* easy to resolve.
Primary Issue:
When a checking in DLINQ Designer DLinq DBML generated files a conflict occurs.
Solution? Move from using the DLINQ Designer to using SQLMetal. (We could use Entity Framework, but that would require significant changes. So we want to stick with DLINQ (LINQ to SQL)).
SQLMetal does not generate what SQL Designer does!
Obviously, if you are on a green field project, this is not as big of an issue. If you are on an existing (brown field) project that has used SQL Designer, this hurts (a lot).
A) SQLMetal does not handle complex stored procedures (in same way)
What is a complex stored procedure?
- Uses control flow logic (If/Else) that results in different result sets.
- Uses temporary tables (#TmpTable )
#1 results in a IMultipleResults being returned by SQLMetal even though SQL Designer results in a ISingleResult. So migrating from SQL Designer to SQLMetal results in compilation errors.
#2 SQLMetal does not generate these sort of sprocs (at all) though SQL Designer does (ugh!)
#2 is particularly difficult to cope with, assuming you need a #Temp Table. SQLMetal just isn’t going to work.
SET FMTONLY OFF; — explicitly in the SPROC
http://msdn.microsoft.com/en-us/library/ms173839.aspx
– what does this do? Results in the **ACTUAL** execution of the sproc and not just returning the meta data about what the SPROC result will be.
– in other words, when you run SQLMetal, your sprocs (that have FMTONLY OFF) will be executed. There could be side effects (assuming your SPROC does something & doesn’t just return information)
– This was *NOT* an option for us
B) SQLMetal does not support manual tweaking of DBML as SQL Designer does.
- Can not add associations between DTO (Data Transfer Objects) that do *not* exist in DB. [ SQL Designer allows this ]
- Can not map a SPROC to a DTO/Entity (easily done in DBML Designer by simply dragging the SPROC to an existing entity (table)
C) Not easy to change the inheritance hierarchy of the generated DataContext?
If you need to change the class that the datacontext inherits from the change must be made each time SQLMetal is run.
e.g.
MyDataContext : System.Data.Linq.DataContext // generated by SQLMetal each time
// but we want
MyDataCongext : BaseDataContext
// where
BaseDataContext : System.Data.Linq.DataContext
D) SQLMetal DBML or Code generation is VERY SLOW for large DB (15 min !)
Can you imagine adding a table and then waiting 15 minutes before you can start coding using that new table b/c SQLMetal takes that long to generate the DBML or DataContext.cs?
Me neither b/c this is totally unacceptable
E) SQLMetal generates the entire database model! (ugh)
The only filtering that can be done using SQLMetal is at the SPROC / View / Function level. What happens if you only want a specific schema, a limited number of tables or certain functions? SOL.
F) SQLMetal generates a DataContext file so large that Visual Studio crashes (esp. with Resharper)
Essentially this is an extension of the (E) issue, but it is a very different issue. Where E may result in too many things being generated, the fact that Visual Studio crashes may make exploring the DataContext file impossible. Our DataContext.cs file was over 13MB. The DBML was 4MB.
Solutions:
A) Use a different ORM + CodeSmith
This was not a consideration for us. We love LINQ. We drink the MSFT cool aid, and we weren’t about to move to NHibernate or LLBGEN (though I had a history w/ Hibernate). We have too much invested in LINQ. ( I suspect many are in this camp ).
B) Hand code the DBML
Not an option for us, as there we had a very green OOP / ORM team. We needed something convenient that could work with several very large DB’s with a very diverse set of objects (functions, SPROCs, Tables, Views).
C) Move to Entity FrameWork
This doesn’t provide much shelter from the issues outlined above, not to mention that we have a large amount of existing LINQ code. (we’re vested / locked in)
D) Mix the advantages of SQLMetal & SQL Designer
This is the choice we took. But it required the building of a utility tool that provided a mixture of functionality of SQLMetal & SQL Designer. We were in DBML Hell, and thus only DBMLGod could set us free! (tongue in cheek, but I named the tool just that DBMLGod).
DBMLGod ( SQL Designer + SQLMetal + Hand Coded DBML )
The idea was to take the strengths of SQL Designer and that of SQLMetal and merge them into a hybrid that has all the positive qualities but none of the negative. Plus we need the ability to HAND code very complicated SPROC’s that even SQL Designer doesn’t generate correctly. This succeeded, but it does require a us to develop in a certain way.
SQL Designer
Strengths:
- Handles Complex Sprocs better than SQLMetal (often times)
- Allows SPROCs return types to be mapped to entities
- Can add associations that do not exist in the DB / ER
- Quick additions of new DB objects (See issue #D above)
Primary weakness: SVN Conflicts
Hand generated DBML
Strengths:
- Full control over what is generated & how
Primary weakness: Must hand code / Must understand the DSL.
SQLMetal
Strengths:
- Reduces conflicts (on par with Hand generated DBML)
- Generates required classes
Weaknesses: See above (A-F)
Ideally we should be able to accumulate strengths without suffering weaknesses.
Implementation of DBMLGod
(Hopefully to be a open source project) – requires my companies sign off.)
In a green field project we might be able to avoid weaknesses of SQLMetal, but given real world scenarios of large existing databases with complex SPROC’s this isn’t possible (for us).
Requirements:
- Support complex SPROCs (use SQL Designer / hand coded DBML) [ Issue A ]
- Add associations not defined in DB / ER [ Issue B ]
- Map SPROC return types to Entities [ [ Issue B ]
- Change generated SQLMetal DataContext code (support inheritance from custom DataContext Object) [ Issue C ]
- Quick addition of new DB objects (no waiting 15 minutes for regen of DBML / DataContext file) [ Issue D ]
- Decrease the size of the generated DBML / DataContext [ Issue E ]
- Generated DataContext must not be unnecessarily large (make things as simple (small) as necessary but no smaller) [ Issue F ]
How do we do that?

And so the idea is to take the SLOW SQLMetal Generation of the DBML (for large DB) and the faster FILTER / MERGE / SQLMetal Code Gen process and make it fast.
DBMLGod does just that. It gets us out of hell by filtering the Generated DBML, merging those into Hand/Designed DBML files (preferring elements in the latter), generating the code and then replacing code elements in the generated DataContext to get the desired result.
Step 1) Gets value of SLQ Metal DBML Gen but allows us to filter resolving issues E & F
Step 2) Leverages value of Hand/SQL Designer to resolve issue A & B
Step 3) Generate the Code
Step 4) Allows us to resolve isssue C & D
How well does this work?
Addition of DB objects has performance on par with SQL Designer (fast)
SVN conflicts are minimized.
Generation of DBML by SQLMetal (SLOW) can be left to END OF DAY process!
Unresolved issues
SQLMetal capitalizes properties on entity clasess and SPROCs. Default behavior of SQL Designer is to *NOT* do this.
Thus you have 2 choices:
1) Change the SQL Designer generated Sprocs/Entities to conform with SQLMetal generation
2) Use SQL Designer & correct/deal with compilation errors as they occur
Can you believe that MSFT uses different strategies depending on the tool? (UGH, SIGH, HORROR)
But thanks for LINQ! Love it!
Related Post: Unfortunate differences between SQL Metal and SQL Designer
alan.huffman Architecture, C#, Development Infrastructure, LINQ .NET, Coding Practices, LINQ, Microsoft, ORM