<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4155628149386914837</id><updated>2011-11-29T21:51:05.566+07:00</updated><category term='Visual Studio'/><category term='EF4'/><category term='Linq to SQL'/><category term='SQL Server'/><category term='Linq-to-SQL'/><category term='VS2010'/><category term='SQL Azure'/><category term='EDMX'/><category term='EFv4'/><category term='performance'/><category term='Model Comparer'/><category term='Azure'/><category term='profiling'/><category term='HuagatiEDMXTools'/><category term='Entity Framework'/><title type='text'>KristoferA's blog</title><subtitle type='html'>I'm a software developer. This blog covers some of the stuff I work on and/or things that I find interesting.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>20</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-1509139116224645107</id><published>2011-05-19T18:08:00.001+07:00</published><updated>2011-05-26T15:30:32.590+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='EFv4'/><category scheme='http://www.blogger.com/atom/ns#' term='EDMX'/><category scheme='http://www.blogger.com/atom/ns#' term='EF4'/><category scheme='http://www.blogger.com/atom/ns#' term='VS2010'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><title type='text'>Entity Framework Model Creation beyond ‘Database First’ / ‘Model First’</title><content type='html'>&lt;p&gt;The built in tools for Entity Framework 4 in Visual Studio forces users to make a distinct choice between the “Database First”, “Model First”, or “Code First” model creation and update strategies. &lt;a href="http://msdn.microsoft.com/en-us/magazine/hh148150.aspx"&gt;A recent MSDN Magazine article&lt;/a&gt; by &lt;a href="http://thedatafarm.com/blog/"&gt;Julie Lerman&lt;/a&gt; describes the options and choices that has to be made on which approach to use for updating the model.&lt;/p&gt; &lt;p&gt;I think those three choices are a bit limiting in that not being able to continually evolve both the model and the underlying database is not an ideal situation for many projects. Applications evolve and so do the underlying databases, often with changes made by several people using different tools. That is the reason why I created the &lt;a href="http://huagati.blogspot.com/2010/07/introducing-model-comparer-for-entity.html"&gt;Model Comparer for EF4&lt;/a&gt; in the first place.&lt;/p&gt; &lt;p&gt;Even if the model is based on an existing database, a.k.a. ‘Database First’, I think it should be possible to use the EF designer built into Visual Studio to update the model and add/remove/change entities/tables, members/columns, associations/foreign keys etc. &lt;/p&gt; &lt;p&gt;Likewise, if the model is designed from scratch in the EF designer (‘Model First’), it should be possible to make incremental changes with SQL-DDL diff scripts, as well as making schema changes directly in the database and sync those changes back to the model.&lt;/p&gt; &lt;p&gt;I made a short (4½ minute long) screencast illustrating how this is possible to do with the EFv4 visual designer together with the model comparer. In this video I make changes both to the database in SQL Server Management Studio and to the model in Visual Studio and then sync it up to replicate the changes into both the database and the model.&lt;/p&gt; &lt;p&gt;Enjoy:&lt;/p&gt; &lt;div id="media"&gt;&lt;object id="csSWF" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="800" height="618" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,115,0"&gt;                 &lt;param name="src" value="http://www.huagati.com/edmxtools/DBFirstModelFirst/DBFirstModelFirst_controller.swf" /&gt;                 &lt;param name="bgcolor" value="#1a1a1a" /&gt;                 &lt;param name="quality" value="best" /&gt;                 &lt;param name="allowScriptAccess" value="always" /&gt;                 &lt;param name="allowFullScreen" value="true" /&gt;                 &lt;param name="scale" value="showall" /&gt;                 &lt;param name="flashVars" value="autostart=false#&amp;amp;thumb=http://huagati.com/edmxtools/DBFirstModelFirst/FirstFrame.png&amp;amp;thumbscale=45&amp;amp;color=0x000000,0x000000" /&gt;                 &lt;embed name="csSWF" src="http://huagati.com/edmxtools/DBFirstModelFirst/DBFirstModelFirst_controller.swf" width="800" height="618" bgcolor="#1a1a1a" quality="best" allowScriptAccess="always" allowFullScreen="true" scale="showall" flashVars="autostart=false&amp;thumb=http://huagati.com/edmxtools/DBFirstModelFirst/FirstFrame.png&amp;thumbscale=45&amp;color=0x000000,0x000000" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"&gt;&lt;/embed&gt;             &lt;/object&gt;&lt;/div&gt; &lt;p&gt;The video above is also available on youtube at &lt;a href="http://www.youtube.com/watch?v=doqYOlcEAZM"&gt;http://www.youtube.com/watch?v=doqYOlcEAZM&lt;/a&gt; , although the youtube version is lower resolution and has more MPEG compression artifacts than the one embedded above.&lt;br&gt;&lt;br&gt;Oh, and if you want to try it out yourself, you can download the add-in that makes this possible from &lt;a href="http://huagati.com/dbmltools/"&gt;http://huagati.com/dbmltools/&lt;/a&gt; and get a free trial license from the same site.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-1509139116224645107?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/1509139116224645107/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2011/05/entity-framework-model-creation-beyond.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/1509139116224645107'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/1509139116224645107'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2011/05/entity-framework-model-creation-beyond.html' title='Entity Framework Model Creation beyond ‘Database First’ / ‘Model First’'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-7769308586641408181</id><published>2011-01-18T19:53:00.001+07:00</published><updated>2011-01-18T19:53:13.365+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HuagatiEDMXTools'/><category scheme='http://www.blogger.com/atom/ns#' term='EFv4'/><category scheme='http://www.blogger.com/atom/ns#' term='EDMX'/><category scheme='http://www.blogger.com/atom/ns#' term='EF4'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><title type='text'>Redistribution licenses for the HuagatiEDMXTools.dll EDMX file object model</title><content type='html'>&lt;p&gt;In an earlier blog post, &lt;a href="http://huagati.blogspot.com/2010/12/creating-or-modifying-entity-framework.html"&gt;Creating or modifying Entity Framework EDMX files from code: an introduction to HuagatiEDMXTools.dll&lt;/a&gt;, I wrote about the EDMX file wrapper that is used by the &lt;a href="http://huagati.com/dbmltools/" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt; add-in for parsing, updating, creating, and writing EDMX files. HuagatiEDMXTools adds an easy to use object model on top of EDMX files &lt;font size="1"&gt;(see documentation at &lt;/font&gt;&lt;a href="http://huagati.com/edmxtools/help"&gt;&lt;font size="1"&gt;http://huagati.com/edmxtools/help&lt;/font&gt;&lt;/a&gt;&lt;font size="1"&gt; )&lt;/font&gt;, making it a lot easier to create/read/update EDMX files, and to write LINQ queries against Entity Framework 4 metadata. It also has a number of built-in queries and lookup functions that make it a breeze to work with Entity Framework 4 EDMX files from code.&lt;/p&gt;  &lt;p&gt;Previously, using the &lt;a href="http://huagati.com/edmxtools/help/" target="_blank"&gt;HuagatiEDMXTools&lt;/a&gt; runtime library required an end-user license for &lt;a href="http://huagati.com/dbmltools/" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt;. As of the latest version (v 2.20) this has been extended with a new redistributable license option, allowing third party applications to use and include &lt;a href="http://huagati.com/edmxtools/help/" target="_blank"&gt;HuagatiEDMXTools&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Redistribution licenses are divided into three categories:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;b&gt;Non-development tool license&lt;/b&gt;: allows redistribution of &lt;a href="http://huagati.com/edmxtools/help/" target="_blank"&gt;HuagatiEDMXTools.dll&lt;/a&gt; together with software products not primarily targeted at software developers and whose primary purpose is not to develop software. This may be line-of-business applications that need to generate, update, or read EDMX data to fulfill some functional requirement.&lt;/li&gt;    &lt;li&gt;&lt;b&gt;Development tool license&lt;/b&gt;: allows redistribution of &lt;a href="http://huagati.com/edmxtools/help/" target="_blank"&gt;HuagatiEDMXTools.dll&lt;/a&gt; together with software products whose primary purpose is to assist software development. This may be a tool specifically for working with Entity Framework 4 EDMX files, such as a new model editor or EF model designer.&lt;/li&gt;    &lt;li&gt;&lt;b&gt;Source code license&lt;/b&gt;: Source code licenses includes the source code for the &lt;a href="http://huagati.com/edmxtools/help/"&gt;HuagatiEDMXTools runtime library&lt;/a&gt;. The source code can not be redistributed, and any libraries/assemblies based on or derived from it may only be distributed as part of another software product that is not substantially similar to or competitive with HuagatiEDMXTools. (It may however be used for products competitive with the &lt;a href="http://huagati.com/dbmltools/" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt; add-in.)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Pricing and additional details are available at &lt;a href="http://huagati.com/dbmltools/"&gt;http://huagati.com/dbmltools/&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-7769308586641408181?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/7769308586641408181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2011/01/redistribution-licenses-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/7769308586641408181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/7769308586641408181'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2011/01/redistribution-licenses-for.html' title='Redistribution licenses for the HuagatiEDMXTools.dll EDMX file object model'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-1302245417983271550</id><published>2010-12-28T17:43:00.001+07:00</published><updated>2010-12-28T17:43:06.058+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='EFv4'/><category scheme='http://www.blogger.com/atom/ns#' term='EDMX'/><category scheme='http://www.blogger.com/atom/ns#' term='EF4'/><category scheme='http://www.blogger.com/atom/ns#' term='VS2010'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='Model Comparer'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Inferring Foreign Key Constraints in Entity Framework Models (Part 2)</title><content type='html'>&lt;p&gt;In my last blog entry, &lt;a href="http://huagati.blogspot.com/2010/12/inferring-foreign-key-constraints-in.html"&gt;Inferring Foreign Key Constraints in Entity Framework Models&lt;/a&gt;, I wrote about a new feature in the &lt;a href="http://huagati.blogspot.com/2010/07/introducing-model-comparer-for-entity.html" target="_blank"&gt;Model Comparer for EFv4&lt;/a&gt; that allow foreign key constraints to be inferred and added to an Entity Framework model even if some or all FKs are missing in the database. The inferred FKs can then be used to generate associations and navigation properties in Entity Framework models.&lt;/p&gt;  &lt;p&gt;In the latest release of &lt;a href="http://huagati.com/dbmltools/" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt;, the FK inference feature has been improved with a new regex match-and-replace feature for matching foreign key columns to primary key columns. This allows FKs to be inferred even if the FK/PK columns to be matched use inconsistent naming and/or are named with special prefixes/suffixes etc.&lt;/p&gt;  &lt;p&gt;Of course, the basic name matching feature described in the previous article is still there, and can be used under many (if not most) common scenarios. However, when the PK/FK naming is more complex then using Regex match+replace comes in handy for resolving what columns in one table can be mapped to the PK in another table.&lt;/p&gt;  &lt;p&gt;The following screenshot shows the settings dialog with the new settings for RegExp-based column matching:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_9F0FMyBvxXA/TRm_MdnWcZI/AAAAAAAAAYY/KHjUMWKLy6Y/s1600-h/inferFK2_001_newSettings%5B3%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="inferFK2_001_newSettings" border="0" alt="inferFK2_001_newSettings" src="http://lh5.ggpht.com/_9F0FMyBvxXA/TRm_Nx_4MqI/AAAAAAAAAYg/5Y0v9xsC_T0/inferFK2_001_newSettings_thumb%5B1%5D.png?imgmax=800" width="654" height="544" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;In addition to allowing the standard &lt;a href="http://msdn.microsoft.com/en-us/library/az24scfc.aspx" target="_blank"&gt;regular expression language elements&lt;/a&gt; to be used in the &lt;em&gt;Match&lt;/em&gt; field, and the &lt;a href="http://msdn.microsoft.com/en-us/library/az24scfc.aspx#substitutions" target="_blank"&gt;substitution elements&lt;/a&gt; to be used in the &lt;em&gt;Replace&lt;/em&gt; field, there are two reserved keywords that can be used in the replacements as well; &lt;strong&gt;%pktable%&lt;/strong&gt; which is replaced with the name of the primary-key-side table and &lt;strong&gt;%fktable%&lt;/strong&gt; which is replaced with the name of the foreign key table when the match is evaluated.&lt;/p&gt;  &lt;p&gt;The above screenshot shows how regular expression replacements plus the %pktable% substitution keyword can be used to match two tables even if the PK column is named “id” and the FK column in another table is named using the PK table’s name followed by “_key”; if the result of the Match+Replace on both sides evaluate to the same value, a foreign key constraint is inferred and will be displayed in the diff-tree and diff-reports in the Model Comparer’s main window.&lt;/p&gt;  &lt;h4&gt;The Model Comparer&lt;/h4&gt;  &lt;p&gt;If you want to read more about the Model Comparer and the other features for Entity Framework contained in the &lt;a href="http://huagati.com/dbmltools" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt; add-in for Visual Studio, see the following links:&lt;/p&gt;  &lt;h5&gt;&lt;a href="http://huagati.blogspot.com/2010/07/introducing-model-comparer-for-entity.html"&gt;Introducing the Model Comparer for Entity Framework v4&lt;/a&gt;&lt;/h5&gt;  &lt;h5&gt;&lt;a href="http://huagati.blogspot.com/2010/08/whats-new-in-model-comparer-for-entity.html"&gt;What’s new in the latest version of the Model Comparer for Entity Framework 4&lt;/a&gt;&lt;/h5&gt;  &lt;h5&gt;&lt;a href="http://huagati.blogspot.com/2010/08/using-model-comparer-to-generate.html"&gt;Using the Model Comparer to generate difference reports for Entity Framework v4 models&lt;/a&gt;&lt;/h5&gt;  &lt;h5&gt;&lt;a href="http://huagati.blogspot.com/2010/10/mixing-inheritance-strategies-in-entity.html"&gt;Mixing inheritance strategies in Entity Framework models&lt;/a&gt;&lt;/h5&gt;  &lt;h5&gt;&lt;a href="http://huagati.blogspot.com/2010/12/sql-azure-support-in-huagati-dbmledmx.html"&gt;SQL Azure support in Huagati DBML/EDMX Tools&lt;/a&gt;&lt;/h5&gt;  &lt;h5&gt;&lt;a href="http://huagati.blogspot.com/2010/12/inferring-foreign-key-constraints-in.html"&gt;Inferring Foreign Key Constraints in Entity Framework Models&lt;/a&gt;&lt;/h5&gt;  &lt;h5&gt;&lt;a href="http://huagati.blogspot.com/2010/07/simplify-entity-framework-v4-models.html"&gt;Simplify Entity Framework v4 models with complex types&lt;/a&gt;&lt;/h5&gt;  &lt;p&gt;…and of course, there is a brief summary of the add-in’s supported features for both Entity Framework and Linq-to-SQL at the product page: &lt;a href="http://huagati.com/dbmltools/"&gt;http://huagati.com/dbmltools/&lt;/a&gt; where you can also download the add-in and get a free 30-day trial license.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-1302245417983271550?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/1302245417983271550/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2010/12/inferring-foreign-key-constraints-in_28.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/1302245417983271550'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/1302245417983271550'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2010/12/inferring-foreign-key-constraints-in_28.html' title='Inferring Foreign Key Constraints in Entity Framework Models (Part 2)'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_9F0FMyBvxXA/TRm_Nx_4MqI/AAAAAAAAAYg/5Y0v9xsC_T0/s72-c/inferFK2_001_newSettings_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-6374702515512721726</id><published>2010-12-21T18:35:00.001+07:00</published><updated>2010-12-21T18:35:07.728+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='EFv4'/><category scheme='http://www.blogger.com/atom/ns#' term='EDMX'/><category scheme='http://www.blogger.com/atom/ns#' term='EF4'/><category scheme='http://www.blogger.com/atom/ns#' term='VS2010'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='Model Comparer'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><title type='text'>Inferring Foreign Key Constraints in Entity Framework Models</title><content type='html'>&lt;p&gt;Foreign key constraints are one of the most important components of relational database models. At the database level they are key to maintaining data integrity and prevents applications and users from writing invalid data or from orphaning data by inadvertently deleting data referenced from other tables.&lt;/p&gt;  &lt;p&gt;When reverse-engineering entity relationships in modelling tools and OR mappers, foreign key constraints serve yet another important role; they also describe the relationship between tables/entities. Without foreign key constraints, OR mappers can’t generate navigation properties between entities, and will not know in what order* it should process inserts, updates, and deletes for various tables.&lt;/p&gt;  &lt;p&gt;* = e.g. generating order detail records before the main order record has been created.&lt;/p&gt;  &lt;h4&gt;Databases with no FK constraints&lt;/h4&gt;  &lt;p&gt;Unfortunately, there are lots of real-world databases that - although they are created and deployed in RDBMSes – lack foreign key constraints. The reasons for omitting FK constraints vary, but it is not uncommon that the reasons stated are based on misconceptions, misunderstandings, or lack of information. Sometimes they are omitted by programmers that can’t get their head around proper order of inserts/deletes, sometimes they are omitted “for performance reasons”, sometimes noone can remember anymore why they were omitted. Whatever the reason, relational databases with some or all FK constraints missing are out there and they’re fairly common.&lt;/p&gt;  &lt;h4&gt;Adding FK constraints to legacy databases&lt;/h4&gt;  &lt;p&gt;One way to tackle FK-less databases is simply to add the missing FK constraints. Simple solution to data integrity issues, and makes OR mappes happy, right? Unfortunately it is not that simple. The real problem with FK-less databases is the applications behind them. If there are tens-of-thousands, hundreds-of-thousands, or millions of lines of code that interact with those databases you can be certain that some of it will break if you just add all the missing FK constraints. There’s almost certainly code that do inserts/deletes in the wrong order, and there’s a fairly good chance that there is junk data or orphaned data that will break the FK constraint already during creation, and so on.&lt;/p&gt;  &lt;h4&gt;Inferring FK constraints&lt;/h4&gt;  &lt;p&gt;Since FK constraints are key to generating the associations in OR mappers such as Entity Framework, I decided to add a feature to infer FKs. Instead of creating them in the database, I use table and column names and types to deduce what might be a FK candidate in the database. After that, the inferred FKs are displayed in the Model Comparer’s list of missing FK constraints.&lt;/p&gt;  &lt;p&gt;The user can choose and pick both real and inferred foreign key constraints and add them to the model selectively, and generate model-level associations and navigation properties without actually creating the FKs in the database.&lt;/p&gt;  &lt;p&gt;The tool also allows inferred FK constraints to be materialized into SQL-DDL scripts, but that part is entirely optional.&lt;/p&gt;  &lt;h4&gt;Demonstration&lt;/h4&gt;  &lt;p&gt;The following set of screenshots demonstrate how the FK inference feature in the Model Comparer for EFv4 can be used to infer FKs in a database and to add selected keys to the EF4 model.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt; – open a EFv4 model in Visual Studio 2010, and bring up the &lt;a href="http://huagati.blogspot.com/2010/07/introducing-model-comparer-for-entity.html" target="_blank"&gt;Model Comparer&lt;/a&gt;:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_9F0FMyBvxXA/TRCQYZrwlkI/AAAAAAAAAXE/EtHnCrZ86gE/s1600-h/inferFK001_modelComparer%5B4%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="The Huagati Model Comparer for Entity Framework 4" border="0" alt="The Huagati Model Comparer for Entity Framework 4" src="http://lh6.ggpht.com/_9F0FMyBvxXA/TRCQahYXcnI/AAAAAAAAAXI/_V0c841Hqqg/inferFK001_modelComparer_thumb%5B2%5D.png?imgmax=800" width="804" height="604" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt; – Click on &lt;em&gt;Settings&lt;/em&gt; to open the settings dialog. Go to the &lt;em&gt;Infer Foreign Keys&lt;/em&gt; tab.    &lt;br /&gt;    &lt;br /&gt;Select the type of objects you want to infer FKs for; tables and/or views. Although views can not have FK constraints in the database it is perfectly fine to infer FKs and use them to add associations to views. This makes it possible to have navigation properties to/from views.    &lt;br /&gt;    &lt;br /&gt;There are four different name matching options controlled by two checkboxes: whether PK members contain the name of the entity or not, whether entity names and member names are separated with underscores or not. Changing the checkboxes updates the table example in the middle of the dialog between the four different naming conventions, to make it easy to verify that the settings match the desired naming conventions.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_9F0FMyBvxXA/TRCQcGh94FI/AAAAAAAAAXM/wWU6xcGpLu0/s1600-h/inferFK002_inferrenceOptions%5B3%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Model Comparer settings for inferring keys" border="0" alt="Model Comparer settings for inferring keys" src="http://lh6.ggpht.com/_9F0FMyBvxXA/TRCQd7YOqZI/AAAAAAAAAXQ/VnyAT2njYLs/inferFK002_inferrenceOptions_thumb%5B1%5D.png?imgmax=800" width="804" height="604" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt; – with the &lt;em&gt;Infer Foreign Key Constraints for Tables&lt;/em&gt; setting and/or the &lt;em&gt;Infer Foreign Key Constraints for Views&lt;/em&gt; setting enabled, the model comparer will infer FK constraints where they don’t exist in the database. Inferred FK constraints start with the FKI prefix and has a different icon than existing FK constraints to make it easy to differentiate between inferred and real FK constraints.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_9F0FMyBvxXA/TRCQffAgmyI/AAAAAAAAAXU/35Yu-baFXFQ/s1600-h/inferFK003_inferredFKs%5B3%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Model Comparer with Inferred FKs" border="0" alt="Model Comparer with Inferred FKs" src="http://lh4.ggpht.com/_9F0FMyBvxXA/TRCQhkqVW6I/AAAAAAAAAXY/QnWEixUlBw8/inferFK003_inferredFKs_thumb%5B1%5D.png?imgmax=800" width="804" height="604" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Step 4&lt;/strong&gt; (optional) – The &lt;em&gt;Report&lt;/em&gt; view also show all inferred keys. If generating a lot of keys the report view is a more eye-friendly way to go through them in order to determine which ones are valid/desired in the model.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_9F0FMyBvxXA/TRCQjJ81jhI/AAAAAAAAAXc/rz8dLkULLK8/s1600-h/inferFK004_inferredFKs%5B3%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Huagati Model Comparer Reports View" border="0" alt="Huagati Model Comparer Reports View" src="http://lh4.ggpht.com/_9F0FMyBvxXA/TRCQlXXif6I/AAAAAAAAAXg/olShvktaevc/inferFK004_inferredFKs_thumb%5B1%5D.png?imgmax=800" width="804" height="604" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Step 5&lt;/strong&gt; – Select the FK constraints that you want to use for generating associations in the model. Click &lt;em&gt;Update SSDL&lt;/em&gt; to add them to the storage model (SSDL) in the Entity Framework 4 model.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_9F0FMyBvxXA/TRCQmt41HoI/AAAAAAAAAXk/xvL5hwNKmM8/s1600-h/inferFK005_inferredKeySelected%5B3%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Inferred Foreign Key Constraints" border="0" alt="Inferred Foreign Key Constraints" src="http://lh3.ggpht.com/_9F0FMyBvxXA/TRCQoIQyIaI/AAAAAAAAAXo/j5DZZVTEnso/inferFK005_inferredKeySelected_thumb%5B1%5D.png?imgmax=800" width="363" height="563" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Step 6&lt;/strong&gt; (optional) – The SSDL-to-DB tree will now show the newly added association. This allows inferred FKs to be materialized as SQL-DDL-scripts if desired. If not, select them and click &lt;em&gt;Ignore&lt;/em&gt;. If you want to generate a SQL-DDL script, allowing the inferred FKs to be added to the database, select the FKs and click on &lt;em&gt;Update Database&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_9F0FMyBvxXA/TRCQqjugNaI/AAAAAAAAAXs/f6Q55EK4FY4/s1600-h/inferFK006_inferredKeyMissingInDB%5B4%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Huagati Model Comparer" border="0" alt="Huagati Model Comparer" src="http://lh6.ggpht.com/_9F0FMyBvxXA/TRCQs-K2ygI/AAAAAAAAAXw/AcufAlxvQ0s/inferFK006_inferredKeyMissingInDB_thumb%5B2%5D.png?imgmax=800" width="804" height="604" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Step 7&lt;/strong&gt; (optional) – If you generated SQL-DDL in Step 6, the SQL-DDL script will appear in a separate SQL editor in the Visual Studio instance that the Model Comparer belongs to. This allows you to review, edit, and save the script before applying to the database.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_9F0FMyBvxXA/TRCQuyi7GZI/AAAAAAAAAX0/tiQgWfLnpaA/s1600-h/inferFK007_inferredKeySQLDDL%5B3%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Huagati Model Comparer with generated SQL-DDL script in the background" border="0" alt="Huagati Model Comparer with generated SQL-DDL script in the background" src="http://lh4.ggpht.com/_9F0FMyBvxXA/TRCQwv-NcMI/AAAAAAAAAX4/R2gHi0QFKXg/inferFK007_inferredKeySQLDDL_thumb%5B1%5D.png?imgmax=800" width="923" height="584" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Step 8&lt;/strong&gt; – Select the new association(s) in the SSDL-to-CSDL tree and click &lt;em&gt;Update CSDL&lt;/em&gt; to add them to the conceptual layer of the model. This will result in navigation properties added between the involved entities.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_9F0FMyBvxXA/TRCQy3HmEPI/AAAAAAAAAX8/bJg-dXZDp30/s1600-h/inferFK008_inferredKeySSDLtoCSDL%5B3%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Huagati Model Comparer" border="0" alt="Huagati Model Comparer" src="http://lh4.ggpht.com/_9F0FMyBvxXA/TRCQ0tUhp8I/AAAAAAAAAYA/NUxRhvybU4k/inferFK008_inferredKeySSDLtoCSDL_thumb%5B1%5D.png?imgmax=800" width="804" height="604" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Step 9&lt;/strong&gt; – Close the model comparer and return to Visual Studio. Continue coding. Enjoy. &lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://lh3.ggpht.com/_9F0FMyBvxXA/TRCQ1tMIu_I/AAAAAAAAAYE/kg0kxFaYtTw/wlEmoticon-smile%5B2%5D.png?imgmax=800" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_9F0FMyBvxXA/TRCQ39-_juI/AAAAAAAAAYI/D9YDlP5SnHI/s1600-h/inferFK009_inferredKeyInCSDL%5B3%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Entity Framework model with inferred association (in AdventureWorks)" border="0" alt="Entity Framework model with inferred association (in AdventureWorks)" src="http://lh3.ggpht.com/_9F0FMyBvxXA/TRCQ6DyadwI/AAAAAAAAAYM/kntS8_QIgqA/inferFK009_inferredKeyInCSDL_thumb%5B1%5D.png?imgmax=800" width="1027" height="771" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;The Huagati Model Comparer&lt;/h4&gt;  &lt;p&gt;The Model Comparer is a feature in the Huagati DBML/EDMX Tools add-in for Visual Studio 2010. The add-in can be downloaded from &lt;a href="http://huagati.com/dbmltools/"&gt;http://huagati.com/dbmltools/&lt;/a&gt; , and time-limited free trial licenses are available from the same site.&lt;/p&gt;  &lt;p&gt;Screencasts showcasing some of the basic functionality in the Model Comparer for EFv4 is available at &lt;a href="http://huagati.blogspot.com/2010/07/introducing-model-comparer-for-entity.html"&gt;http://huagati.blogspot.com/2010/07/introducing-model-comparer-for-entity.html&lt;/a&gt; and &lt;a href="http://huagati.blogspot.com/2010/08/using-model-comparer-to-generate.html"&gt;http://huagati.blogspot.com/2010/08/using-model-comparer-to-generate.html&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-6374702515512721726?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/6374702515512721726/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2010/12/inferring-foreign-key-constraints-in.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/6374702515512721726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/6374702515512721726'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2010/12/inferring-foreign-key-constraints-in.html' title='Inferring Foreign Key Constraints in Entity Framework Models'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_9F0FMyBvxXA/TRCQahYXcnI/AAAAAAAAAXI/_V0c841Hqqg/s72-c/inferFK001_modelComparer_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-7496877748540165834</id><published>2010-12-13T12:38:00.001+07:00</published><updated>2010-12-13T12:45:21.248+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='EFv4'/><category scheme='http://www.blogger.com/atom/ns#' term='Linq to SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='EF4'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Azure'/><category scheme='http://www.blogger.com/atom/ns#' term='Azure'/><category scheme='http://www.blogger.com/atom/ns#' term='Linq-to-SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><category scheme='http://www.blogger.com/atom/ns#' term='profiling'/><title type='text'>Query Profiling SQL Azure when using Entity Framework or Linq-to-SQL</title><content type='html'>&lt;p&gt;One slight shortcoming in &lt;a href="https://sql.azure.com" target="_blank"&gt;Microsoft’s SQL Azure&lt;/a&gt; (the SQL Server 2008 flavor that is hosted&amp;#160; in Microsoft’s cloud platform) is that users don’t have the trace privileges needed to use SQL Profiler to profile query and performance behavior. Fortunately there are &lt;a href="http://social.technet.microsoft.com/wiki/contents/articles/gaining-performance-insight-into-sql-azure.aspx" target="_blank"&gt;other ways&lt;/a&gt; to extract performance data for individual queries; SQL Azure exposes IO statistics, timings, and execution plans in the same way as normal non-cloud editions of SQL Server.&lt;/p&gt;  &lt;p&gt;I have recently done some testing against SQL Azure using my tools. Huagati DBML/EDMX Tools needed some minor adjustments to work against SQL Azure as outlined in a previous blog post: &lt;a title="http://huagati.blogspot.com/2010/12/sql-azure-support-in-huagati-dbmledmx.html" href="http://huagati.blogspot.com/2010/12/sql-azure-support-in-huagati-dbmledmx.html"&gt;http://huagati.blogspot.com/2010/12/sql-azure-support-in-huagati-dbmledmx.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Next up was testing the profiling / logging components for &lt;a href="http://huagati.blogspot.com/2010/06/entity-framework-support-in-huagati.html" target="_blank"&gt;Entity Framework 4&lt;/a&gt; and &lt;a href="http://huagati.blogspot.com/2009/06/profiling-linq-to-sql-applications.html" target="_blank"&gt;Linq-to-SQL&lt;/a&gt; in &lt;a href="http://huagati.com/L2SProfiler" target="_blank"&gt;Huagati Query Profiler&lt;/a&gt; against SQL Azure. Fortunately I can announce that it works just fine; the techniques used by the &lt;a href="http://huagati.com/L2SProfiler" target="_blank"&gt;Huagati Query Profiler&lt;/a&gt;’s logging components for capturing server-side timings, I/O statistics, query execution plans are all supported in SQL Azure. The log entries will look the same and the same performance data and filtering options that work against local SQL Server instances can be used against SQL Server in the cloud.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_9F0FMyBvxXA/TQWxXyX9ZgI/AAAAAAAAAWo/CfJEA8Heqe4/s1600-h/queryProfilerAzure%5B4%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="queryProfilerAzure" border="0" alt="queryProfilerAzure" src="http://lh5.ggpht.com/_9F0FMyBvxXA/TQWxaL-Xj1I/AAAAAAAAAWs/sqNySJxlsXo/queryProfilerAzure_thumb%5B2%5D.png?imgmax=800" width="644" height="369" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;One interesting thing I noticed while testing is that the roundtrip times against the SQL Azure instance I am accessing is only 100-150ms above accessing a database on my local LAN. That is impressive considering I am in Thailand and the SQL Azure instance is in Singapore, and faster than what I have seen mentioned in some forums and blog posts from US SQL Azure users.&lt;/p&gt;  &lt;p&gt;To get started, download and install the &lt;a href="http://huagati.com/l2sprofiler/" target="_blank"&gt;Huagati Query Profiler&lt;/a&gt; from &lt;a href="http://huagati.com/l2sprofiler/"&gt;http://huagati.com/l2sprofiler/&lt;/a&gt; and take a look at these blog posts and/or the sample code that is installed together with the profiler:     &lt;br /&gt;    &lt;br /&gt;Linq-to-SQL: &lt;a title="http://huagati.blogspot.com/2009/06/profiling-linq-to-sql-applications.html" href="http://huagati.blogspot.com/2009/06/profiling-linq-to-sql-applications.html"&gt;http://huagati.blogspot.com/2009/06/profiling-linq-to-sql-applications.html&lt;/a&gt;     &lt;br /&gt;Entity Framework: &lt;a title="http://huagati.blogspot.com/2010/06/entity-framework-support-in-huagati.html" href="http://huagati.blogspot.com/2010/06/entity-framework-support-in-huagati.html"&gt;http://huagati.blogspot.com/2010/06/entity-framework-support-in-huagati.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Next, you can either try the sample projects that ship with the profiler against your own SQL Azure instance, or add profiling support to your own Entity Framework 4 or Linq-to-SQL based projects against a SQL Azure database.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-7496877748540165834?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/7496877748540165834/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2010/12/query-profiling-sql-azure-when-using.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/7496877748540165834'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/7496877748540165834'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2010/12/query-profiling-sql-azure-when-using.html' title='Query Profiling SQL Azure when using Entity Framework or Linq-to-SQL'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_9F0FMyBvxXA/TQWxaL-Xj1I/AAAAAAAAAWs/sqNySJxlsXo/s72-c/queryProfilerAzure_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-3690004895051172954</id><published>2010-12-02T09:50:00.001+07:00</published><updated>2010-12-02T09:50:39.736+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='EFv4'/><category scheme='http://www.blogger.com/atom/ns#' term='EDMX'/><category scheme='http://www.blogger.com/atom/ns#' term='EF4'/><category scheme='http://www.blogger.com/atom/ns#' term='VS2010'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><title type='text'>Creating or modifying Entity Framework EDMX files from code: an introduction to HuagatiEDMXTools.dll</title><content type='html'>&lt;p&gt;Microsoft’s Entity Framework stores models as xml-based EDMX files. Within the EDMX file, the model is divided up into the conceptual layer (CSDL) which describes the C# or VB entity classes and methods, the storage layer (SSDL) which describes the database tables/keys/views/procedures etc, the mapping layer (MSL) which describes how everything in the conceptual model maps to the storage model, and finally one portion describing the designer diagram layout.&lt;/p&gt;  &lt;p&gt;The EDMX files are typically generated and modified by the designer in Visual Studio, by edmgen.exe/edmgen2.exe, or by third party tools such as the &lt;a href="http://huagati.blogspot.com/2010/07/introducing-model-comparer-for-entity.html" target="_blank"&gt;model comparer&lt;/a&gt; in &lt;a href="http://huagati.com/dbmltools" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt;.&lt;/p&gt;  &lt;h4&gt;Reading/writing EDMX files&lt;/h4&gt;  &lt;p&gt;Sometimes people look for ways to generate, modify, or parse EDMX files &lt;a href="http://stackoverflow.com/questions/3795241/create-edmx-from-c-code-not-from-database" target="_blank"&gt;from code&lt;/a&gt;. The straightforward answer to that is usually to use an XML parser; XmlDocument, XmlReader/XmlWriter, Linq-to-XML etc. Using XML parsers to read and write EDMX files works fine, but it also requires a fair bit of time spent on reading the &lt;a href="http://msdn.microsoft.com/en-us/library/bb399604.aspx" target="_blank"&gt;CSDL, SSDL, and MSL specifications&lt;/a&gt; as well as some manual work figuring out some of the things not clearly spelt out in the specification such as how different common or uncommon mapping scenarios are best described in the MSL.&lt;/p&gt;  &lt;h4&gt;The HuagatiEDMXTools.dll library&lt;/h4&gt;  &lt;p&gt;Before developing the new Entity Framework 4 features in &lt;a href="http://huagati.com/dbmltools/" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt;, I decided to step away from directly using an XML parser and instead add an intermediate abstraction layer. That makes it a lot easier to work with the models and separates out most of the quirky mapping logic. The result was a separate wrapper library called HuagatiEDMXTools.dll . Underneath it still uses a XML parser, but all model artifacts are exposed as classes, properties, IEnumerables, IQueryables etc. Some related object types such as associationsets and associations are merged together, related objects available as properties, and &lt;a href="http://huagati.com/edmxtools/help/html/AllMembers_T_HuagatiEDMXTools_ConceptualModelQueries.htm" target="_blank"&gt;useful queries&lt;/a&gt; and lookups are exposed as simple &lt;a href="http://huagati.com/edmxtools/help/html/P_HuagatiEDMXTools_ModelEntityType_BaseTypes.htm" target="_blank"&gt;lookup properties&lt;/a&gt; and IQueryables/functions.&lt;/p&gt;  &lt;p&gt;Although HuagatiEDMXTools was written to support the EFv4-related functionality in &lt;a href="http://huagati.com/dbmltools/" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt;, I decided to &lt;a href="http://huagati.com/edmxtools/help/" target="_blank"&gt;document it&lt;/a&gt; to allow add-in users to write their own code to create/modify/read EDMX models for scenarios that are not covered by the add-in or other tools. Although the library has been around and exposed since version 1.90 and for the most part fairly self-explanatory, the documentation for it wasn’t released until version 2.11. The documentation is in MSDN format (thanks, &lt;a href="http://sandcastle.codeplex.com/" target="_blank"&gt;Sandcastle&lt;/a&gt; and &lt;a href="http://shfb.codeplex.com/" target="_blank"&gt;SHFB&lt;/a&gt;), and is available online at &lt;a href="http://huagati.com/edmxtools/help/"&gt;http://huagati.com/edmxtools/help/&lt;/a&gt; as well as in the form of a HTML help file that is installed together with the &lt;a href="http://huagati.com/dbmltools/" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt; add-in. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_9F0FMyBvxXA/TPcJQkQnxLI/AAAAAAAAAVQ/UwAdCsv2Mvo/s1600-h/helpScreenshot%5B5%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Online help screenshot" border="0" alt="Online help screenshot" src="http://lh4.ggpht.com/_9F0FMyBvxXA/TPcJTD5gvzI/AAAAAAAAAVU/6RU_hJM8iLA/helpScreenshot_thumb%5B3%5D.png?imgmax=800" width="804" height="584" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;To use the HuagatiEDMXTools library from a VS project, simply add a reference to the file HuagatiEDMXTools.dll from the project references:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_9F0FMyBvxXA/TPcJUOaNZrI/AAAAAAAAAVY/Lu6T0FY2Ea8/s1600-h/addref%5B3%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Adding a reference to HuagatiEDMXTools.dll" border="0" alt="Adding a reference to HuagatiEDMXTools.dll" src="http://lh6.ggpht.com/_9F0FMyBvxXA/TPcJVyPXckI/AAAAAAAAAVc/dVrNHkKQfcQ/addref_thumb%5B1%5D.png?imgmax=800" width="644" height="356" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;When using the library, start by initializing the licensing module by passing the license data from the add-in’s license file ( \users\[username]\Documents\Visual Studio 2010\Addins\HuagatiDBMLTools2010.dll.lic ) to the license class:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_9F0FMyBvxXA/TPcJYRUkESI/AAAAAAAAAVg/3BTXRWco2l4/s1600-h/licenseInfo%5B3%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Setting license data in Huagati EDMX Tools&amp;#39; license class" border="0" alt="Setting license data in Huagati EDMX Tools&amp;#39; license class" src="http://lh5.ggpht.com/_9F0FMyBvxXA/TPcJZ9diheI/AAAAAAAAAVk/YE-LYkWBJEA/licenseInfo_thumb%5B1%5D.png?imgmax=800" width="644" height="204" /&gt;&lt;/a&gt;&lt;/p&gt;      &lt;h4&gt;Samples&lt;/h4&gt;  &lt;p&gt;Next, you can use the library to create, modify, read EDMX files, or simply to query for various model metrics using some of the built-in queries, or by writing new ones against the many IEnumerables and IQueryables exposed by the library.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_9F0FMyBvxXA/TPcJam_yyHI/AAAAAAAAAVo/YKTQ7hOpwDo/s1600-h/readEDMX%5B9%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Sample showing how to read and query metrics from an existing EDMX file" border="0" alt="Sample showing how to read and query metrics from an existing EDMX file" src="http://lh5.ggpht.com/_9F0FMyBvxXA/TPcJb_1uW6I/AAAAAAAAAVs/pJJNJ7QQtHs/readEDMX_thumb%5B5%5D.png?imgmax=800" width="812" height="560" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_9F0FMyBvxXA/TPcJc_1OjHI/AAAAAAAAAVw/jzRKaJCWYw8/s1600-h/createEDMX01%5B4%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Sample 1/2 showing how to create a new EDMX file from scratch" border="0" alt="Sample 1/2 showing how to create a new EDMX file from scratch" src="http://lh6.ggpht.com/_9F0FMyBvxXA/TPcJdsT0m7I/AAAAAAAAAV0/PAKnsdNCQ78/createEDMX01_thumb%5B2%5D.png?imgmax=800" width="608" height="436" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_9F0FMyBvxXA/TPcJefR9DUI/AAAAAAAAAV4/4DHKYBO0Ciw/s1600-h/createEDMX02%5B3%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Sample 2/2 showing how to create a new EDMX file from scratch" border="0" alt="Sample 2/2 showing how to create a new EDMX file from scratch" src="http://lh3.ggpht.com/_9F0FMyBvxXA/TPcJfVnSnII/AAAAAAAAAV8/dWOE8AFpbWk/createEDMX02_thumb%5B1%5D.png?imgmax=800" width="613" height="601" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;h4&gt;Download&lt;/h4&gt;  &lt;p&gt;As I mentioned above, the HuagatiEDMXTools library ships with Huagati DBML/EDMX Tools. You can download the latest version of Huagati DBML/EDMX Tools from &lt;a href="http://huagati.com/dbmltools/"&gt;http://huagati.com/dbmltools/&lt;/a&gt; and get a license (free trial, or a full paid license) from the same site.&lt;/p&gt;  &lt;p&gt;The online help for the library is available at &lt;a href="http://huagati.com/edmxtools/help/"&gt;http://huagati.com/edmxtools/help/&lt;/a&gt; as well as in a .chm file that is installed together with Huagati DBML/EDMX Tools.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-3690004895051172954?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/3690004895051172954/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2010/12/creating-or-modifying-entity-framework.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/3690004895051172954'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/3690004895051172954'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2010/12/creating-or-modifying-entity-framework.html' title='Creating or modifying Entity Framework EDMX files from code: an introduction to HuagatiEDMXTools.dll'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_9F0FMyBvxXA/TPcJTD5gvzI/AAAAAAAAAVU/6RU_hJM8iLA/s72-c/helpScreenshot_thumb%5B3%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-6886091955991943901</id><published>2010-12-01T18:16:00.001+07:00</published><updated>2010-12-01T18:16:39.767+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='EFv4'/><category scheme='http://www.blogger.com/atom/ns#' term='Linq to SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='EF4'/><category scheme='http://www.blogger.com/atom/ns#' term='VS2010'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Azure'/><category scheme='http://www.blogger.com/atom/ns#' term='Azure'/><category scheme='http://www.blogger.com/atom/ns#' term='Linq-to-SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='Model Comparer'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>SQL Azure support in Huagati DBML/EDMX Tools</title><content type='html'>&lt;p&gt;Recently I have been asked by several users if &lt;a href="http://huagati.com/dbmltools/" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt; supports SQL Azure. Until now, the answer was no; SQL Azure has some limitations compared to normal SQL Server 2008/2005/2000. However, after the question was asked again in the support forum this morning I decided to take another look at it.&lt;/p&gt;  &lt;p&gt;I came across two minor obstacles:&lt;/p&gt;  &lt;p&gt;1) SQL Azure supports &lt;a href="http://msdn.microsoft.com/en-us/library/ee336238.aspx" target="_blank"&gt;only a subset&lt;/a&gt; of SQL Server’s system views. The add-in rely on several of these to extract schema data, documentation, indexes etc from the database.&lt;/p&gt;  &lt;p&gt;2) SQL Azure is technically not available from Thailand until August 2011, and being based in Thailand I couldn’t directly sign up for it.&lt;/p&gt;  &lt;p&gt;The first one is simple to solve in code, if connecting to SQL Azure the add-in simply have to avoid using some SQL Server features such as extended properties until those are supported in SQL Azure. This means the documentation sync feature in the add-in will not be able to retrieve documentation information from SQL Azure, since SQL Azure can not store it.&lt;/p&gt;  &lt;p&gt;The second one was solved by Microsoft Thailand’s developer evangelist, Khun Ekaraj, who was nice enough to set me up with a one month SQL Azure trial pass. That allowed me to validate that the add-in worked against SQL Azure with the necessary changes applied.&lt;/p&gt;  &lt;p&gt;As of today’s release, version 2.12, SQL Azure is now supported from &lt;a href="http://huagati.com/dbmltools/" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt; when running under Visual Studio 2010.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-6886091955991943901?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/6886091955991943901/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2010/12/sql-azure-support-in-huagati-dbmledmx.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/6886091955991943901'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/6886091955991943901'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2010/12/sql-azure-support-in-huagati-dbmledmx.html' title='SQL Azure support in Huagati DBML/EDMX Tools'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-866692233496445286</id><published>2010-10-14T13:15:00.001+07:00</published><updated>2010-10-14T13:15:52.572+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='EFv4'/><category scheme='http://www.blogger.com/atom/ns#' term='EF4'/><category scheme='http://www.blogger.com/atom/ns#' term='VS2010'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='Model Comparer'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><title type='text'>Mixing inheritance strategies in Entity Framework models</title><content type='html'>&lt;p&gt;The Microsoft Entity Framework v4 runtime supports three entity inheritance models: TPT, TPH, and TPC. When using the built-in EF designer and tools in Microsoft Visual Studio 2010, the default inheritance strategy in model-first scenarios is TPT. TPH inheritance can be manually mapped in the designer, and TPC requires editing the mapping (MSL) in the EDMX file manually or using third party tools.&lt;/p&gt;  &lt;h4&gt;TPT, TPH, and TPC explained&lt;/h4&gt;  &lt;p&gt;&lt;strong&gt;TPT&lt;/strong&gt; is short for Table Per Type. In TPT inheritance, there is one central table containing all the base class members and then one table per subclass containing the key and the members that are immediate (non-inherited) members of the subclass. In database terms this can be described as a normalized model, with additional tables for members that are not always present. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_9F0FMyBvxXA/TLaf7DI4aMI/AAAAAAAAAUY/W3JfNB-hjN0/s1600-h/tptIllustration%5B4%5D.png" target="_blank"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="tptIllustration" border="0" alt="tptIllustration" src="http://lh5.ggpht.com/_9F0FMyBvxXA/TLaf8eyhLQI/AAAAAAAAAUc/HEvE4AVaRaA/tptIllustration_thumb%5B2%5D.png?imgmax=800" width="804" height="504" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;TPH&lt;/strong&gt; is short for Table Per Hierarchy. In TPH inheritance there is only one table representing the base class and all subclasses. Members must be nullable to avoid errors when a subclass don't contain members of another subclass. In database terms TPH can be described as a denormalized model, since one wide table is used to represent all of the types in the hierarchy with columns that are left with a null value if they are not members of the entity type.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_9F0FMyBvxXA/TLaf9FEjAYI/AAAAAAAAAUg/M4A01Uhubvw/s1600-h/tphIllustration%5B4%5D.png" target="_blank"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="tphIllustration" border="0" alt="tphIllustration" src="http://lh6.ggpht.com/_9F0FMyBvxXA/TLaf-AQnWUI/AAAAAAAAAUk/EGf00GljULQ/tphIllustration_thumb%5B2%5D.png?imgmax=800" width="732" height="504" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;TPC&lt;/strong&gt; is short for Table Per Concrete type. In TPC inheritance, every class in a inheritance hierarchy will have their own table. The inheritance hierarchy masks the fact that there are several independent underlying tables, representing each subtype.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_9F0FMyBvxXA/TLaf_J5WLJI/AAAAAAAAAUo/1HZ2_LZ39is/s1600-h/tpcIllustration%5B4%5D.png" target="_blank"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="tpcIllustration" border="0" alt="tpcIllustration" src="http://lh5.ggpht.com/_9F0FMyBvxXA/TLagAKba12I/AAAAAAAAAUs/t2n9uakqHCs/tpcIllustration_thumb%5B2%5D.png?imgmax=800" width="804" height="504" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h4&gt;Choosing inheritance strategy in Entity Framework&lt;/h4&gt;  &lt;p&gt;Choosing an inheritance strategy when using the VS2010 built-in tools often means making a model-wide decision on what type of entity inheritance to use. If you work in a 'Model First' pattern, where you create your entity classes in the model designer and then generate SSDL and the database from that, the designer will by default use TPT inheritance for all hierarchies. Microsoft have some plugins that can add model-first TPH support to the designer, and if you want to use TPC inheritance you need to do your mappings by hand using an XML editor or third-party tools.&lt;/p&gt;  &lt;p&gt;Microsoft's &lt;a href="http://blogs.msdn.com/b/alexj" target="_blank"&gt;Alex James&lt;/a&gt; has written a nice blog post on how to choose inheritance strategy, that describes the differences and merits to each of the inheritance strategies supported by Entity Framework:    &lt;br /&gt;&lt;a href="http://blogs.msdn.com/b/alexj/archive/2009/04/15/tip-12-choosing-an-inheritance-strategy.aspx"&gt;http://blogs.msdn.com/b/alexj/archive/2009/04/15/tip-12-choosing-an-inheritance-strategy.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;However, I don't think the decision of what inheritance strategy to use should be a model-level decision. Each of the inheritance strategies have their merits and drawbacks:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;TPT&lt;/strong&gt; inheritance is sleek storage wise, the tables involved contain only the valid members. However, the SQL queries generated for complex TPT hierarchies can easily become very large and complex even for simple hierarchies. For complex hierarchies there can be a noticeable overhead in generating the queries, when SQL Server generates execution plans, and in cost of executing the queries.      &lt;br /&gt;      &lt;br /&gt;Even with a handful of subtypes, TPT hierarchies require EF to create all possible joins and then create a big UNIONed query covering all options, unless the query specifically asks for a single type within the hierarchy.      &lt;br /&gt;      &lt;br /&gt;Some of the performance considerations related to TPT are outlined in a &lt;a href="http://blogs.msdn.com/b/adonet/archive/2010/08/17/performance-considerations-when-using-tpt-table-per-type-inheritance-in-the-entity-framework.aspx" target="_blank"&gt;blog post&lt;/a&gt; in the &lt;a href="http://blogs.msdn.com/b/adonet/" target="_blank"&gt;EF team’s blog&lt;/a&gt;:      &lt;br /&gt;&lt;a title="http://blogs.msdn.com/b/adonet/archive/2010/08/17/performance-considerations-when-using-tpt-table-per-type-inheritance-in-the-entity-framework.aspx" href="http://blogs.msdn.com/b/adonet/archive/2010/08/17/performance-considerations-when-using-tpt-table-per-type-inheritance-in-the-entity-framework.aspx"&gt;http://blogs.msdn.com/b/adonet/archive/2010/08/17/performance-considerations-when-using-tpt-table-per-type-inheritance-in-the-entity-framework.aspx&lt;/a&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;TPH&lt;/strong&gt; inheritance results in wider tables with many nullable columns, since all types within a inheritance hierarchy maps to the same table. Nullable columns opens up the possibility for missing values going undetected (bad data), and wide tables will use more storage space than narrower tables.      &lt;br /&gt;      &lt;br /&gt;However, the SQL queries generated for TPH hierarchies are more simple and TPH inheritance can have a performance advantage over TPT both when generating queries and when running the queries. (Although it is worth noting that it doesn’t always have a performance advantage; pulling a few fields from a very wide table with many records can result in a lot of unnecessary I/O).      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;TPC&lt;/strong&gt; inheritance is also good storage-wise since each type has its own table with no redundant columns. However, due to having multiple tables, TPC adds some constraints on the choice of keys.      &lt;br /&gt;      &lt;br /&gt;Using SQL Server’s &lt;em&gt;int identity&lt;/em&gt; columns don't work very well together with TPC since there will be duplicate entity keys when inserting in different tables all having their own identity seed, so either a spread seed (where each table has its’ own initial seed value) will be needed, or a mechanism other than SQL Server’s identity keyword is needed. Some other RDBMSes have other mechanisms allowing a sequence to be shared by multiple tables, and something similar can be achieved with customized default constraints in SQL Server. Using GUID keys, or int identity keys with different starting ranges solves that problem.      &lt;br /&gt;      &lt;br /&gt;TPC is not supported by the VS2010 EFv4 designer’s mapping editor, so mapping TPC requires using an XML editor or third-party tools.      &lt;br /&gt;      &lt;br /&gt;Queries against TPC hierarchies, like TPT hiearchies, makes EF generate UNIONed queries, although the queries for TPC hierarchies are typically less complex than the queries generated for TPT inheritance hierarchies since all tables are self-contained and no joins are needed between base- and subtype tables, and no additional unions when the inheritance hierarchy is more than one level deep.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Depending on complexity of the inheritance hierarchy, the shape and volume of the data, the type of queries, etc., there are often good reasons to use different inheritance strategies within one model. Instead of a model-level decision, I think it is necessary to allow inheritance strategy to be decided on a case-by-case basis for each inheritance hierarchy within a model.&lt;/p&gt;  &lt;h4&gt;New inheritance strategy settings in the Model Comparer&lt;/h4&gt;  &lt;p&gt;Enter the third party tools. The latest version of the Model Comparer for EFv4 in &lt;a href="http://www.huagati.com/dbmltools/" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt; has added support for all three inheritance strategies supported by Entity Framework: TPT, TPH, and TPC. The settings dialog for the model comparer has a new setting allowing users to pick the default inheritance strategy used in model first scenarios; when creating SSDL/MSL/SQL-DDL from CSDL.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_9F0FMyBvxXA/TLagAwW2EfI/AAAAAAAAAUw/rIp7xC7HDDg/s1600-h/modelComparerOptions197%5B4%5D.png" target="_blank"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="modelComparerOptions197" border="0" alt="modelComparerOptions197" src="http://lh4.ggpht.com/_9F0FMyBvxXA/TLagB2eCmlI/AAAAAAAAAU0/uHTT-vt9rqE/modelComparerOptions197_thumb%5B2%5D.png?imgmax=800" width="644" height="530" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;In addition to allowing a model-level default inheritance strategy for model-first scenarios, there is a fourth inheritance strategy setting called &amp;quot;Mixed&amp;quot;.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_9F0FMyBvxXA/TLagCxWjAQI/AAAAAAAAAU4/Dg4G26KE9F8/s1600-h/inheritanceStrategyDropdown%5B4%5D.png" target="_blank"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="inheritanceStrategyDropdown" border="0" alt="inheritanceStrategyDropdown" src="http://lh6.ggpht.com/_9F0FMyBvxXA/TLagDShCeCI/AAAAAAAAAU8/mzqTmnYY3Tg/inheritanceStrategyDropdown_thumb%5B2%5D.png?imgmax=800" width="201" height="121" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;When the inheritance strategy setting is set to Mixed, a dropdown for choosing inheritance strategy is displayed in the conceptual model tools area in the model comparer. This enable developers to pick inheritance strategy on-the-fly when adding new inheritance hierarchies to the model. The SSDL and MSL generated by the model comparer's &amp;quot;Update SSDL&amp;quot; feature will then be structured based on what is selected in the dropdown.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_9F0FMyBvxXA/TLagECiWUqI/AAAAAAAAAVA/WxdZqqn9ZPA/s1600-h/mixedModeDropdown%5B4%5D.png" target="_blank"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="mixedModeDropdown" border="0" alt="mixedModeDropdown" src="http://lh4.ggpht.com/_9F0FMyBvxXA/TLagFTYUGaI/AAAAAAAAAVE/JrIQ3H6wOLE/mixedModeDropdown_thumb%5B2%5D.png?imgmax=800" width="644" height="484" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h4&gt;Caveats&lt;/h4&gt;  &lt;ul&gt;   &lt;li&gt;Does this mean inheritance strategies can be mixed within one inheritance hierarchy? No, it doesn't. Each inherited tree of entity types must stick to one inheritance strategy, but independent inherited hierarchy of entities within the model can use different inheritance strategies. To enforce this, the model comparer stores the selected inheritance strategy for each CSDL entity set when generating SSDL, and will reuse the same inheritance strategy if e.g. a new subtype is added within a hierarchy.&lt;/li&gt;    &lt;li&gt;Does this make it easier to choose what inheritance strategy to use? No, it doesn't. Choosing inheritance strategy should be done on a case-by-case basis, and based on facts. Will you have a lot of data or just a handful of records? How complex is your inheritance strategy? Look at the queries generated by EF for your particular model, &lt;a href="http://huagati.blogspot.com/2010/06/entity-framework-support-in-huagati.html" target="_blank"&gt;profile the queries&lt;/a&gt;, generate sample data corresponding or exceeding the amount of data you expect your application will generate and profile again.&lt;/li&gt;    &lt;li&gt;Does this make it a good idea to use entity inheritance in every corner of the model? No, it doesn't. Entity inheritance is a nice feature from a code and object-orientation perspective. However, in many scenarios it is not &lt;em&gt;really&lt;/em&gt; needed. Don't make your model more complex than necessary. There are always tradeoffs on one side or the other: going berzerk with object-orientation can add database-side complexities such as performance issues, so try to find the right balance between object orientation and a clean database that keep both developers, DBAs, and end-users happy.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;h4&gt;The Model Comparer for Entity Framework v4&lt;/h4&gt;  &lt;p&gt;The Model Comparer is part of the &lt;a href="http://www.huagati.com/dbmltools/" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt; add-in for VS2010. If you want to try it out, you can download it from &lt;a href="http://huagati.com/dbmltools/"&gt;http://huagati.com/dbmltools/&lt;/a&gt; and get a trial license from the same site.&lt;/p&gt;  &lt;p&gt;If you want to learn more about the basic features in the Model Comparer, and how it improves the EFv4 designer experience in Visual Studio 2010 with new options and features, please watch the screencasts in the following blog posts:   &lt;br /&gt;&lt;a href="http://huagati.blogspot.com/2010/07/introducing-model-comparer-for-entity.html"&gt;http://huagati.blogspot.com/2010/07/introducing-model-comparer-for-entity.html&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://huagati.blogspot.com/2010/08/using-model-comparer-to-generate.html"&gt;http://huagati.blogspot.com/2010/08/using-model-comparer-to-generate.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The Model Comparer and other features in the &lt;a href="http://www.huagati.com/dbmltools/" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt; add-in keep evolving, so keep an eye out for the new features that we keep adding to it. Release cycles are generally very short and we try to get new features, improvements, and of course also bugfixes out to users quickly.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-866692233496445286?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/866692233496445286/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2010/10/mixing-inheritance-strategies-in-entity.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/866692233496445286'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/866692233496445286'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2010/10/mixing-inheritance-strategies-in-entity.html' title='Mixing inheritance strategies in Entity Framework models'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_9F0FMyBvxXA/TLaf8eyhLQI/AAAAAAAAAUc/HEvE4AVaRaA/s72-c/tptIllustration_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-6884628825853109237</id><published>2010-08-26T11:42:00.001+07:00</published><updated>2010-08-26T11:43:41.912+07:00</updated><title type='text'>Getting started with Linq-to-SQL or Entity Framework</title><content type='html'>&lt;p&gt;Although they were released in 2007 (Linq-to-SQL) and 2008 (EFv1), these two data access technologies and the tools, frameworks, and language features surrounding them are new to lots of people who are just about to start using them.&lt;/p&gt;  &lt;p&gt;The following blog post covers some resources (books, blogs, forums) that contain everything you need to get started with and/or understand how Entity Framework, Linq-to-Entities, Linq-to-SQL, or LINQ in general works. &lt;/p&gt;  &lt;h4&gt;Books and Blogs&lt;/h4&gt;  &lt;h5&gt;&lt;a href="http://www.amazon.com/Professional-ADO-NET-Entity-Framework-Programmer/dp/047018261X/" target="_blank"&gt;Professional ADO.NET 3.5 with LINQ and the Entity Framework and Oakleafblog&lt;/a&gt;&lt;/h5&gt;  &lt;p&gt;&lt;a href="http://www.amazon.com/Professional-ADO-NET-Entity-Framework-Programmer/dp/047018261X/" target="_blank"&gt;Professional ADO.NET 3.5 with LINQ and the Entity Framework&lt;/a&gt; by &lt;a href="http://oakleafblog.blogspot.com/" target="_blank"&gt;Roger Jennings&lt;/a&gt; covers all the new data access technologies that were introduced with .net 3.5. Roger has written 30+ books on everything from operating systems, databases, programming, data access etc. Nowadays he is covering cloud computing in his &lt;a href="http://oakleafblog.blogspot.com/" target="_blank"&gt;blog&lt;/a&gt; and in his &lt;a href="http://www.wrox.com/WileyCDA/WroxTitle/Cloud-Computing-with-the-Windows-Azure-Platform.productCd-0470506385.html." target="_blank"&gt;latest book&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Before his interest for cloud computing took over completely, Roger covered just about everything that happened in the .net data access world (Linq-to-SQL, Linq-to-[everything else], Entity Framework, ADO, etc) with daily updates in &lt;a href="http://oakleafblog.blogspot.com/" target="_blank"&gt;his blog&lt;/a&gt;,    &lt;br /&gt;&lt;a href="http://oakleafblog.blogspot.com/"&gt;http://oakleafblog.blogspot.com/&lt;/a&gt;. All those L2S/EF/ADO articles are still there if you scroll down a bit, and links to lots of useful code samples and tips and tricks.&lt;/p&gt;  &lt;h5&gt;&lt;a href="http://oreilly.com/catalog/9780596807252" target="_blank"&gt;Programming Entity Framework, Second Edition&lt;/a&gt; and The Data Farm&lt;/h5&gt;  &lt;p&gt;&lt;a href="http://thedatafarm.com/blog/" target="_blank"&gt;Julie Lerman&lt;/a&gt; has written two books on Entity Framework. The first one covered EFv1, the first version of Entity Framework that shipped with .net 3.5 SP1. &lt;/p&gt;  &lt;p&gt;Her latest book, &lt;a href="http://oreilly.com/catalog/9780596807252" target="_blank"&gt;Programming Entity Framework, Second Edition&lt;/a&gt;, is for Entity Framework 4 or EFv4 that shipped with .net 4 / Visual Studio 2010. Programming Entity Framework, Second Edition is 914 pages covering every little corner and aspect of EFv4.    &lt;br /&gt;&lt;a href="http://oreilly.com/catalog/9780596807252"&gt;http://oreilly.com/catalog/9780596807252&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Julie has a couple of blogs to go with the book:   &lt;br /&gt;&lt;a href="http://thedatafarm.com/blog/"&gt;http://thedatafarm.com/blog/&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://learnentityframework.com/learnentityframework/"&gt;http://learnentityframework.com/learnentityframework/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;…and she also writes the Data Points column in &lt;a href="http://msdn.microsoft.com/en-us/magazine/default.aspx" target="_blank"&gt;MSDN Magazine&lt;/a&gt;.&lt;/p&gt;  &lt;h5&gt;&lt;a href="http://www.amazon.com/gp/product/1933988169" target="_blank"&gt;Linq in Action&lt;/a&gt; and ThinqLinq&lt;/h5&gt;  &lt;p&gt;&lt;a href="http://www.amazon.com/gp/product/1933988169" target="_blank"&gt;Linq in Action&lt;/a&gt; by Jim Wooley, Fabrice Marguerie, and Steve Eichert dives into the details of all flavors of LINQ.    &lt;br /&gt;&lt;a href="http://www.amazon.com/gp/product/1933988169"&gt;http://www.amazon.com/gp/product/1933988169&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.thinqlinq.com/" target="_blank"&gt;Jim Wooley&lt;/a&gt; also has a blog with lots of useful Linq tips, tricks, and solutions at &lt;a href="http://www.thinqlinq.com/"&gt;http://www.thinqlinq.com/&lt;/a&gt; . His blog also has a page with links to various third party tools for L2S and EF:    &lt;br /&gt;&lt;a href="http://www.thinqlinq.com/default/LINQ-Tools.aspx"&gt;http://www.thinqlinq.com/default/LINQ-Tools.aspx&lt;/a&gt;&lt;/p&gt;  &lt;h5&gt;&lt;a href="http://damieng.com" target="_blank"&gt;Damien Guard’s blog&lt;/a&gt;&lt;/h5&gt;  &lt;p&gt;&lt;a href="http://damieng.com" target="_blank"&gt;Damien Guard&lt;/a&gt; used to work with the Linq-to-SQL and Entity Framework team at Microsoft. Now he is working with some other team at Microsoft (XBox..?). His blog has a lot of L2S and EF goodies, among those a neat one-page reference to the most commonly used Linq syntax. Very handy to have on the wall when writing code against Linq-to-SQL or Linq-to-Entities: &lt;a href="http://damieng.com/blog/2009/08/12/linq-to-sql-cheat-sheet"&gt;http://damieng.com/blog/2009/08/12/linq-to-sql-cheat-sheet&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Damien also has some links to various Linq-to-SQL resources; tools, blogs etc:   &lt;br /&gt;&lt;a href="http://damieng.com/blog/2009/06/04/linq-to-sql-resources"&gt;http://damieng.com/blog/2009/06/04/linq-to-sql-resources&lt;/a&gt;&lt;/p&gt;  &lt;h5&gt;&lt;a href="http://blogs.msdn.com/b/alexj/" target="_blank"&gt;Alex James’ blog&lt;/a&gt;&lt;/h5&gt;  &lt;p&gt;Nowadays focused more on OData, Microsoft’s &lt;a href="http://blogs.msdn.com/b/alexj/" target="_blank"&gt;Alex James&lt;/a&gt; has a lot of &lt;a href="http://blogs.msdn.com/b/alexj/archive/tags/ef+4-0/" target="_blank"&gt;EF tips and tricks&lt;/a&gt; and useful code samples that can be used with both EF and L2S in his blog:    &lt;br /&gt;&lt;a title="http://blogs.msdn.com/b/alexj/" href="http://blogs.msdn.com/b/alexj/"&gt;http://blogs.msdn.com/b/alexj/&lt;/a&gt;&lt;/p&gt;  &lt;h5&gt;MSDN blogs&lt;/h5&gt;  &lt;p&gt;The ADO.net team has two blogs, one covering EF in general and one with articles about future features in EF:   &lt;br /&gt;&lt;a title="http://blogs.msdn.com/b/adonet/" href="http://blogs.msdn.com/b/adonet/"&gt;http://blogs.msdn.com/b/adonet/&lt;/a&gt;    &lt;br /&gt;&lt;a title="http://blogs.msdn.com/b/efdesign/" href="http://blogs.msdn.com/b/efdesign/"&gt;http://blogs.msdn.com/b/efdesign/&lt;/a&gt;&lt;/p&gt;  &lt;h4&gt;Forums &lt;/h4&gt;  &lt;h5&gt;MSDN forums&lt;/h5&gt;  &lt;p&gt;The MSDN forums, run by Microsoft, is a gold mine of useful information on both &lt;a href="http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/threads" target="_blank"&gt;EF&lt;/a&gt; and &lt;a href="http://social.msdn.microsoft.com/Forums/en-US/linqtosql/threads" target="_blank"&gt;L2S&lt;/a&gt;. Just browsing/searching these forums can reveal a lot of useful information, best practices, tips and tricks etc. If you can't find what you're looking for, post a question and you will probably have a solution within a day.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/threads"&gt;http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/threads&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://social.msdn.microsoft.com/Forums/en-US/linqtosql/threads"&gt;http://social.msdn.microsoft.com/Forums/en-US/linqtosql/threads&lt;/a&gt;&lt;/p&gt;  &lt;h5&gt;&lt;a href="http://stackoverflow.com/" target="_blank"&gt;StackOverflow&lt;/a&gt;&lt;/h5&gt;  &lt;p&gt;&lt;a href="http://stackoverflow.com/" target="_blank"&gt;StackOverflow&lt;/a&gt; also has a lot of useful information and helpful people answering questions, whether newbie/beginner questions or advanced stuff. Check out the EF and L2S-related tags:    &lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/tagged/entity-framework"&gt;http://stackoverflow.com/questions/tagged/entity-framework&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/tagged/linq-to-entities"&gt;http://stackoverflow.com/questions/tagged/linq-to-entities&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/tagged/linq-to-sql"&gt;http://stackoverflow.com/questions/tagged/linq-to-sql&lt;/a&gt;&lt;/p&gt;  &lt;h4&gt;Did I miss something?&lt;/h4&gt;  &lt;p&gt;The above are just a handful of the resources available, but should be good starting points. In all the blogs and forums I have linked to you will come across links to hundreds of other resources with useful information.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-6884628825853109237?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/6884628825853109237/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2010/08/getting-started-with-linq-to-sql-or.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/6884628825853109237'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/6884628825853109237'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2010/08/getting-started-with-linq-to-sql-or.html' title='Getting started with Linq-to-SQL or Entity Framework'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-5209156985358911571</id><published>2010-08-17T15:31:00.001+07:00</published><updated>2010-08-17T15:31:44.195+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='EFv4'/><category scheme='http://www.blogger.com/atom/ns#' term='EF4'/><category scheme='http://www.blogger.com/atom/ns#' term='VS2010'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='Model Comparer'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Using the Model Comparer to generate difference reports for Entity Framework v4 models</title><content type='html'>&lt;p&gt;In the previous two blog entries, &lt;a href="http://huagati.blogspot.com/2010/07/introducing-model-comparer-for-entity.html" target="_blank"&gt;Introducing the Model Comparer for Entity Framework v4&lt;/a&gt;, and &lt;a href="http://huagati.blogspot.com/2010/08/whats-new-in-model-comparer-for-entity.html" target="_blank"&gt;What’s new in the latest version of the Model Comparer for Entity Framework 4&lt;/a&gt; I covered the basics of using the Model Comparer to keep EFv4 models in sync within the model and with the underlying database without replacing or losing customizations made to the model. &lt;/p&gt;  &lt;p&gt;Now the turn has come to show the latest feature in the Model Comparer: &lt;strong&gt;Reports&lt;/strong&gt;. &lt;/p&gt;  &lt;p&gt;The main work area in the model comparer shows &lt;em&gt;database &amp;lt;=&amp;gt; SSDL&lt;/em&gt; differences, &lt;em&gt;SSDL &amp;lt;=&amp;gt; database&lt;/em&gt;,&lt;em&gt; SSDL &amp;lt;=&amp;gt; CSDL&lt;/em&gt;, and &lt;em&gt;CSDL =&amp;gt; SSDL&lt;/em&gt; differences broken down in three treeviews and allows users to sync (or ignore) individual/selected (or all) differences. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_9F0FMyBvxXA/TGpIqB76jSI/AAAAAAAAAQ4/47Xk56xnTY0/s1600-h/modelComparerDiffTab%5B5%5D.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Model Comparer / Differences tab" border="0" alt="Model Comparer / Differences tab" src="http://lh6.ggpht.com/_9F0FMyBvxXA/TGpIt410pJI/AAAAAAAAAQ8/MDncRSuStVI/modelComparerDiffTab_thumb%5B3%5D.png?imgmax=800" width="804" height="604" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;In some situations it may be more useful to generate simple diff reports listing all differences in a readable format; printable/mailable reports come in handy when emailing to colleagues, for use during meetings, to review differences in more detail before applying changes, etc. &lt;/p&gt;  &lt;p&gt;The newest feature added to the Model Comparer for EF4 is a &amp;quot;Reports&amp;quot; tab made just for creating reports from EF4 models: &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_9F0FMyBvxXA/TGpIvlRwZPI/AAAAAAAAARA/MXTwi1XwdVE/s1600-h/modelComparerReportTab01%5B6%5D.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="modelComparerReportTab01" border="0" alt="modelComparerReportTab01" src="http://lh4.ggpht.com/_9F0FMyBvxXA/TGpIyHIJSgI/AAAAAAAAARE/OQ2YRk0SmHA/modelComparerReportTab01_thumb%5B4%5D.png?imgmax=800" width="804" height="604" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The diff reports are generated from the same model diff comparison as the diff data shown in the treeviews in the &lt;em&gt;differences&lt;/em&gt; tab, but the report format allows a lot more details pertaining to unmapped and changed objects can be shown; from database column attributes to SQL Server extended property descriptions, and in-model documentation.&lt;/p&gt;  &lt;p&gt;Each type of difference get a section in the report detailing all differences of that specific type:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_9F0FMyBvxXA/TGpIz1qC2nI/AAAAAAAAARI/zOzjfJOSQf8/s1600-h/modelComparerReportTab02%5B4%5D.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="modelComparerReportTab02" border="0" alt="modelComparerReportTab02" src="http://lh3.ggpht.com/_9F0FMyBvxXA/TGpI2q-GXoI/AAAAAAAAARM/u_5U4ZEgK3c/modelComparerReportTab02_thumb%5B2%5D.png?imgmax=800" width="804" height="604" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The Model Comparer compares all available attributes; from entity level down to data types, max size, precision/scale, nullability, default values, default constraints and just about everything else that is reflected in both the database, and the SSDL and CSDL layers of the EFv4 model:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_9F0FMyBvxXA/TGpI4G2hyKI/AAAAAAAAARQ/6b1Ntmo92LE/s1600-h/modelComparerReportTab03%5B6%5D.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="modelComparerReportTab03" border="0" alt="modelComparerReportTab03" src="http://lh5.ggpht.com/_9F0FMyBvxXA/TGpI7TrlJCI/AAAAAAAAARU/fL3OFKUmXvA/modelComparerReportTab03_thumb%5B4%5D.png?imgmax=800" width="804" height="604" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h4&gt;&amp;#160;&lt;/h4&gt;  &lt;h4&gt;Screencast / Video&lt;/h4&gt;  &lt;p&gt;I have created a &lt;a href="http://www.huagati.com/edmxTools/reports/ModelComparerReports.html" target="_blank"&gt;short video/screencast&lt;/a&gt; demonstrating the basics of the Model Comparer's new report-generator feature: &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div id="media"&gt;&lt;object id="csSWF" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="800" height="618" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,115,0"&gt;   &lt;param name="src" value="http://www.huagati.com/edmxTools/reports/ModelComparerReports_controller.swf" /&gt;   &lt;param name="bgcolor" value="#1a1a1a" /&gt;   &lt;param name="quality" value="best" /&gt;   &lt;param name="allowScriptAccess" value="always" /&gt;   &lt;param name="allowFullScreen" value="true" /&gt;   &lt;param name="scale" value="showall" /&gt;   &lt;param name="flashVars" value="autostart=false#&amp;amp;thumb=http://www.huagati.com/edmxTools/reports/FirstFrame.png&amp;amp;thumbscale=45&amp;amp;color=0x000000,0x000000" /&gt;   &lt;embed name="csSWF" src="http://www.huagati.com/edmxTools/reports/ModelComparerReports_controller.swf" width="800" height="618" bgcolor="#1a1a1a" quality="best" allowScriptAccess="always" allowFullScreen="true" scale="showall" flashVars="autostart=false&amp;thumb=http://www.huagati.com/edmxTools/reports/FirstFrame.png&amp;thumbscale=45&amp;color=0x000000,0x000000" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"&gt;&lt;/embed&gt;  &lt;/object&gt;&lt;/div&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h4&gt;&amp;#160;&lt;/h4&gt;  &lt;h4&gt;Want to try it out?&lt;/h4&gt;  &lt;p&gt;If you want to try out the Model Comparer, you can download Huagati DBML/EDMX Tools and get a trial license from &lt;a href="http://www.huagati.com/dbmltools/"&gt;http://www.huagati.com/dbmltools/&lt;/a&gt; . &lt;em&gt;(The model comparer is just one of many features for Entity Framework and Linq-to-SQL contained within the add-in. The report viewer was added in version 1.93.) &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Keep an eye on this blog for new features; we’re rapidly adding new EFv4-related features to the &lt;a href="http://www.huagati.com/dbmltools/" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt; Add-in. Note that the EFv4-related feature set only works under Visual Studio 2010.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-5209156985358911571?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/5209156985358911571/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2010/08/using-model-comparer-to-generate.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/5209156985358911571'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/5209156985358911571'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2010/08/using-model-comparer-to-generate.html' title='Using the Model Comparer to generate difference reports for Entity Framework v4 models'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_9F0FMyBvxXA/TGpIt410pJI/AAAAAAAAAQ8/MDncRSuStVI/s72-c/modelComparerDiffTab_thumb%5B3%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-8167324904043567811</id><published>2010-08-10T13:37:00.001+07:00</published><updated>2010-08-10T13:57:49.508+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='EFv4'/><category scheme='http://www.blogger.com/atom/ns#' term='EF4'/><category scheme='http://www.blogger.com/atom/ns#' term='VS2010'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='Model Comparer'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>What’s new in the latest version of the Model Comparer for Entity Framework 4</title><content type='html'>&lt;p&gt;The following is a brief description of some of the new functionality that was just added to the Model Comparer for EF4.&lt;/p&gt;  &lt;p&gt;An &lt;a href="http://www.huagati.com/edmxtools/intro/HuagatiModelComparer.html" target="_blank"&gt;introduction video&lt;/a&gt; to the model comparer is available in the previous blog entry: “&lt;a title="Introducing the Model Comparer for Entity Framework v4" href="http://huagati.blogspot.com/2010/07/introducing-model-comparer-for-entity.html"&gt;Introducing the Model Comparer for Entity Framework v4&lt;/a&gt;”.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_9F0FMyBvxXA/TGDzKHm5kRI/AAAAAAAAAPU/bgB7zZ77tpk/s1600-h/modelComparer192%5B4%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="modelComparer192" border="0" alt="modelComparer192" src="http://lh4.ggpht.com/_9F0FMyBvxXA/TGDzNIN74wI/AAAAAAAAAPY/We7k05xduKU/modelComparer192_thumb%5B2%5D.png?imgmax=800" width="644" height="484" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h4&gt;New Version – new features&lt;/h4&gt;  &lt;p&gt;Yesterday I released a new version of &lt;a href="http://www.huagati.com/dbmltools/" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt;, and with it a new version of the Model Comparer with a pile of fixes, improvements, and some new features.&lt;/p&gt;  &lt;p&gt;The goal of the Model Comparer is to give developers using Entity Framework 4.0 in Visual Studio 2010 better control over differences between the conceptual model (CSDL) and storage model (SSDL), and between the database and the storage model in EFv4 models. It does that by comparing the three layers and showing detected differences in three treeviews. The user can then select individual differences (or all) and either bring them across to the opposite layer or tell the Model Comparer to ignore differences.&lt;/p&gt;  &lt;p&gt;The core functionality in the Model Comparer is described in more detail in the intro video in “&lt;a title="Introducing the Model Comparer for Entity Framework v4" href="http://huagati.blogspot.com/2010/07/introducing-model-comparer-for-entity.html"&gt;Introducing the Model Comparer for Entity Framework v4&lt;/a&gt;”. If you haven’t used the model comparer or watched the intro video you may want to start with that one to get an idea of what the Model Comparer itself can do and how it works.&lt;/p&gt;  &lt;p&gt;To give users even more control over what the Model Comparer takes into account when determining differences between the layers, it has a number of user-controllable settings. In the first version (add-in version 1.91) those settings were stored in XML files but not readily accessible from the UI.&lt;/p&gt;  &lt;p&gt;As of version 1.92 there are UI dialogs exposing the most common settings. The settings dialogs are accessible through two new buttons in the lower left corner of the Model Comparer dialog:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_9F0FMyBvxXA/TGDzOsx4tZI/AAAAAAAAAPc/u1MivtUocpI/s1600-h/modelComparer192SettingsButtons%5B3%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="modelComparer192SettingsButtons" border="0" alt="modelComparer192SettingsButtons" src="http://lh4.ggpht.com/_9F0FMyBvxXA/TGDzQOXHnKI/AAAAAAAAAPg/--xZDHpykh8/modelComparer192SettingsButtons_thumb%5B1%5D.png?imgmax=800" width="448" height="604" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The first button, “Settings” controls the behavior of the model comparer, and the second one, “CSDL Name Rules” define the naming rules used when creating CSDL entities and members from SSDL objects.&lt;/p&gt;  &lt;h4&gt;Model Comparer Settings&lt;/h4&gt;  &lt;p&gt;Most of these settings are simple on-off options so the settings dialog &lt;strike&gt;are cluttered with&lt;/strike&gt; has a lot of checkboxes. (&lt;em&gt;Yes, I know, checkbox-hell, but hopefully the settings themselves are self-explanatory enough to make it survivable on the rare occasions that these settings may need to be tweaked. It was really down to a choice between checkbox-hell and property-grid-hell and I think checkbox-hell is still easier to get an overview over.&lt;/em&gt;)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_9F0FMyBvxXA/TGDzSWkR7WI/AAAAAAAAAPk/FZlqUg6qPxw/s1600-h/edmxCompareOptions%5B3%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="edmxCompareOptions" border="0" alt="edmxCompareOptions" src="http://lh4.ggpht.com/_9F0FMyBvxXA/TGDzUF7DX-I/AAAAAAAAAPo/y9nPtA3sWJQ/edmxCompareOptions_thumb%5B1%5D.png?imgmax=800" width="644" height="530" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;So, let’s break it down. The settings are grouped by the model area that they correspond to: Database, SSDL, CSDL.&lt;/p&gt;  &lt;p&gt;Additionally there is one shared group of settings for SSDL/CSDL member differences, and one group that define what – if any - database default constraints should translate into &lt;em&gt;store generated patterns&lt;/em&gt; in the model.&lt;/p&gt;  &lt;h5&gt;Database-to-SSDL difference settings&lt;/h5&gt;  &lt;p&gt;The first group of checkboxes controls if the model comparer should detect tables, views, columns, FK constraints, procedures and functions that exist in the database but has no representation in the SSDL:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_9F0FMyBvxXA/TGDzVuCqlwI/AAAAAAAAAPs/vmPsDJwvk18/s1600-h/dbDiffSettings001%5B3%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="dbDiffSettings001" border="0" alt="dbDiffSettings001" src="http://lh3.ggpht.com/_9F0FMyBvxXA/TGDzXKK2ZxI/AAAAAAAAAPw/Eywwfhf4Hro/dbDiffSettings001_thumb%5B1%5D.png?imgmax=800" width="229" height="486" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The next group of checkboxes control what types of differences between database columns and SSDL member properties should be included in the database tree as DB-&amp;gt;SSDL differences:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_9F0FMyBvxXA/TGDzYkc7MlI/AAAAAAAAAP0/t0GbhECpLgU/s1600-h/dbDiffSettings002%5B3%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="dbDiffSettings002" border="0" alt="dbDiffSettings002" src="http://lh6.ggpht.com/_9F0FMyBvxXA/TGDzZybC1gI/AAAAAAAAAP4/RlNncyhwtr8/dbDiffSettings002_thumb%5B1%5D.png?imgmax=800" width="229" height="486" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Finally, the last group of database diff settings are for stored procedures and functions; these settings control what type of differences should land stored procedures and database functions on the list of procedures with differences between the database and SSDL:&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_9F0FMyBvxXA/TGDzbpUqq4I/AAAAAAAAAP8/tgB2DjircaM/s1600-h/dbDiffSettings003%5B3%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="dbDiffSettings003" border="0" alt="dbDiffSettings003" src="http://lh5.ggpht.com/_9F0FMyBvxXA/TGDzcuzyPJI/AAAAAAAAAQA/I0bWKAFlaOI/dbDiffSettings003_thumb%5B1%5D.png?imgmax=800" width="229" height="486" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h5&gt;SSDL difference settings&lt;/h5&gt;  &lt;p&gt;The second portion of the settings dialog, SSDL settings, controls what types of objects present in the SSDL should be shown in the SSDL tree if not present in the database or CSDL.&lt;/p&gt;  &lt;p&gt;The first five settings control the SSDL-to-database missing-objects comparison:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_9F0FMyBvxXA/TGDzdljBDwI/AAAAAAAAAQE/-y9JV8petaQ/s1600-h/ssdlDiffSettings001%5B2%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="ssdlDiffSettings001" border="0" alt="ssdlDiffSettings001" src="http://lh4.ggpht.com/_9F0FMyBvxXA/TGDzexZktsI/AAAAAAAAAQI/yGuN8pZnzxE/ssdlDiffSettings001_thumb.png?imgmax=800" width="209" height="234" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;…and the following four settings controls the SSDL-to-CSDL missing-objects comparison:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_9F0FMyBvxXA/TGDzfniIULI/AAAAAAAAAQM/XC-MZfxIT0Q/s1600-h/ssdlDiffSettings002%5B2%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="ssdlDiffSettings002" border="0" alt="ssdlDiffSettings002" src="http://lh5.ggpht.com/_9F0FMyBvxXA/TGDzg-Q5HVI/AAAAAAAAAQQ/Dz4FoWVRIWQ/ssdlDiffSettings002_thumb.png?imgmax=800" width="209" height="234" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h5&gt;CSDL difference settings&lt;/h5&gt;  &lt;p&gt;The next portion of the settings dialog, CSDL, controls if CSDL objects not present in the SSDL portion of the model should be displayed in the Model Comparer’s CSDL tree:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_9F0FMyBvxXA/TGDzhjsZ14I/AAAAAAAAAQU/ip63j_V-pUQ/s1600-h/csdlDiffSettings001%5B2%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="csdlDiffSettings001" border="0" alt="csdlDiffSettings001" src="http://lh3.ggpht.com/_9F0FMyBvxXA/TGDzisXgX5I/AAAAAAAAAQY/9D9t3MQal5Q/csdlDiffSettings001_thumb.png?imgmax=800" width="206" height="129" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h5&gt;CSDL-to-SSDL difference settings&lt;/h5&gt;  &lt;p&gt;The CSDL to SSDL settings portion controls what types of differences at entity member level should land entities and their members on the diff list in the CSDL and SSDL trees. These settings are shared between both portions since differences in this area are shown in both trees:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_9F0FMyBvxXA/TGDzjUZeOhI/AAAAAAAAAQc/0kS-KS2rzfA/s1600-h/csdlSSDLDiffSettings%5B3%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="csdlSSDLDiffSettings" border="0" alt="csdlSSDLDiffSettings" src="http://lh3.ggpht.com/_9F0FMyBvxXA/TGDzkrUsOnI/AAAAAAAAAQg/hBCqgiqpfWM/csdlSSDLDiffSettings_thumb%5B1%5D.png?imgmax=800" width="408" height="82" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h5&gt;Database constraint settings&lt;/h5&gt;  &lt;p&gt;The final portion of the Model Comparer’s settings dialog controls which – if any – database default constraints should be treated as &lt;em&gt;StoreGeneratedPattern: Identity&lt;/em&gt; or &lt;em&gt;StoreGeneratedPattern: Computed&lt;/em&gt; instead of the default &lt;em&gt;StoreGeneratedPattern: None&lt;/em&gt;. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_9F0FMyBvxXA/TGDzlnhPMsI/AAAAAAAAAQk/j17SLedsq-0/s1600-h/constraintSettings%5B3%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="constraintSettings" border="0" alt="constraintSettings" src="http://lh5.ggpht.com/_9F0FMyBvxXA/TGDznONkwHI/AAAAAAAAAQo/Wf7xURZhHO8/constraintSettings_thumb%5B1%5D.png?imgmax=800" width="407" height="132" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This comes in handy if primary key values are generated database-side by a default constraint like NewID or NewSequentialID, or if a table has ‘created date/time’ fields that are populated by the database rather than the client application.&lt;/p&gt;  &lt;p&gt;There is also one field that control what the default constraint should be set to if generating SQL-DDL from the model comparer for tables with GUID PKs marked as &lt;em&gt;StoreGeneratedPattern: Identity&lt;/em&gt; in the model. The default value is &lt;em&gt;NewSequentialID&lt;/em&gt; but it can be changed to &lt;em&gt;NewID&lt;/em&gt; or a user-defined function, as needed.&lt;/p&gt;  &lt;h4&gt;CSDL name rules&lt;/h4&gt;  &lt;p&gt;The second settings button available in the Model Comparer controls how CSDL entities and CSDL members generated from SSDL artifacts should be named. It allows you to e.g. strip underscores, apply ProperCase/pascal casing to class and member names, control pluralization and singularization, remove (or add) prefixes/suffixes and apply a whole set of other naming rules to ensure that the final classes and member properties conform to .net naming conventions (or your own naming conventions) even if the database objects don’t.&lt;/p&gt;  &lt;h4&gt;&lt;a href="http://lh6.ggpht.com/_9F0FMyBvxXA/TGDzpAjNLOI/AAAAAAAAAQs/4QMaioqxtow/s1600-h/nameRules%5B3%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="nameRules" border="0" alt="nameRules" src="http://lh4.ggpht.com/_9F0FMyBvxXA/TGDzqp7txVI/AAAAAAAAAQw/DnFgl9VP9ek/nameRules_thumb%5B1%5D.png?imgmax=800" width="654" height="514" /&gt;&lt;/a&gt; &lt;/h4&gt;  &lt;p&gt;The naming rule settings are applied by the Model Comparer only when adding entities or members to the CSDL portion of the model. For renaming existing CSDL entities and members, the add-in has a separate feature that use the same set of settings but allows renaming existing entities and entity members.&lt;/p&gt;  &lt;h4&gt;What’s next?&lt;/h4&gt;  &lt;p&gt;The Model Comparer is a brand new feature in &lt;a href="http://www.huagati.com/dbmltools/" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt;, and it will get new features and improvements in various areas in the near (and far) future. Besides general usability improvements, the next version (1.93) will introduce new reporting features. More on this when 1.93 is released.&lt;/p&gt;  &lt;h4&gt;Want to try it?&lt;/h4&gt;  &lt;p&gt;If you want to try out the Model Comparer, all you need to do is head over to &lt;a href="http://www.huagati.com/dbmltools/"&gt;http://www.huagati.com/dbmltools/&lt;/a&gt; and download the &lt;a href="http://www.huagati.com/dbmltools/" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt; add-in.&lt;/p&gt;  &lt;p&gt;After downloading, click on the ‘&lt;a href="http://apps.huagati.com/license/getlicense.aspx" target="_blank"&gt;trial license&lt;/a&gt;’ link to get a trial license, fill out your details, and you will receive a license key that will enable you to use the add-in for free for 20 days. If you’re happy with it and want to continue using it after that, please buy a license (or subscribe for only $15/month/user) to support further development of this and other features.&lt;/p&gt;  &lt;p&gt;The add-in includes the Model Comparer for EF4 as well as a whole lot of other useful extensions to the Entity Framework and Linq-to-SQL designers in Visual Studio 2010 and 2008. (Note: &lt;em&gt;Some add-in features such as the EF4 Model Comparer are only available under VS2010&lt;/em&gt;)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-8167324904043567811?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/8167324904043567811/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2010/08/whats-new-in-model-comparer-for-entity.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/8167324904043567811'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/8167324904043567811'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2010/08/whats-new-in-model-comparer-for-entity.html' title='What’s new in the latest version of the Model Comparer for Entity Framework 4'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_9F0FMyBvxXA/TGDzNIN74wI/AAAAAAAAAPY/We7k05xduKU/s72-c/modelComparer192_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-5562003146866658343</id><published>2010-07-30T17:16:00.001+07:00</published><updated>2010-07-30T18:36:30.466+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='EFv4'/><category scheme='http://www.blogger.com/atom/ns#' term='VS2010'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Introducing the Model Comparer for Entity Framework v4</title><content type='html'>&lt;p&gt;This is a brief intro to the just-released Model Comparer for Entity Framework. The model comparer is part of the &lt;a href="http://www.huagati.com/dbmltools/" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt; add-in for VS2010, and was added in version 1.91 released on 29 July 2010. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;The problem &lt;/h4&gt;  &lt;p&gt;The Entity Framework designer in Visual Studio 2010 has a lot of improvements over earlier versions. Like its' predecessor in VS2008 it has the ability to update the model from the database, but like its predecessor it gives the user a rather limited choice over what to update. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Developers often need a more fine-grained control over the diffs and updates; there may be hand-tweaked parts of the EF model that they don't want to change and there may be database changes that should not be propagated over to the model. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;The model comparer &lt;/h4&gt;  &lt;p&gt;The model comparer is an attempt to give developers more control over the EF4 designer in Visual Studio 2010 in terms of handling db-model differences and intra-model-differences.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The add-in doesn't replace the EF designer and doesn't remove anything that is part of Visual Studio. It does however give a more detailed overview over differences between each of the layers; database, storage model, and conceptual model. The differences are displayed in three treeviews, and there are a number options for bringing individual or all differences across as well as for ignoring differences. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.huagati.com/edmxtools/screenshots/modelcomparer.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="The Huagati Model Comparer" border="0" alt="The Huagati Model Comparer" src="http://lh3.ggpht.com/_9F0FMyBvxXA/TFKmeYcLPFI/AAAAAAAAAPI/HOnjYh-MJEc/modelComparer%5B4%5D.png?imgmax=800" width="635" height="484" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Whenever a model is updated using the model comparer, only the relevant portions of the SSDL, MSL and CSDL are updated. Entities with no changes are left untouched along with any customizations that may have been made to them. This is unlike the VS built in &amp;quot;update model&amp;quot; wizard that often overwrite manual changes to the model when only a specific change should have been brought across. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;I have made a &lt;a href="http://www.huagati.com/edmxtools/intro/HuagatiModelComparer.html" target="_blank"&gt;short intro video&lt;/a&gt; showing the model comparer in action in VS2010 against the Microsoft AdventureWorks database. Enjoy!&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;          &lt;div id="media"&gt;             &lt;object id="csSWF" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="800" height="618" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,115,0"&gt;                 &lt;param name="src" value="http://www.huagati.com/edmxtools/intro/HuagatiModelComparer_controller.swf" /&gt;                 &lt;param name="bgcolor" value="#1a1a1a" /&gt;                 &lt;param name="quality" value="best" /&gt;                 &lt;param name="allowScriptAccess" value="always" /&gt;                 &lt;param name="allowFullScreen" value="true" /&gt;                 &lt;param name="scale" value="showall" /&gt;                 &lt;param name="flashVars" value="autostart=false#&amp;amp;thumb=http://www.huagati.com/edmxtools/intro/FirstFrame.png&amp;amp;thumbscale=45&amp;amp;color=0x000000,0x000000" /&gt;                 &lt;embed name="csSWF" src="http://www.huagati.com/edmxtools/intro/HuagatiModelComparer_controller.swf" width="800" height="618" bgcolor="#1a1a1a" quality="best" allowScriptAccess="always" allowFullScreen="true" scale="showall" flashVars="autostart=false&amp;thumb=http://www.huagati.com/edmxtools/intro/FirstFrame.png&amp;thumbscale=45&amp;color=0x000000,0x000000" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"&gt;&lt;/embed&gt;             &lt;/object&gt;         &lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-5562003146866658343?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/5562003146866658343/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2010/07/introducing-model-comparer-for-entity.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/5562003146866658343'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/5562003146866658343'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2010/07/introducing-model-comparer-for-entity.html' title='Introducing the Model Comparer for Entity Framework v4'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_9F0FMyBvxXA/TFKmeYcLPFI/AAAAAAAAAPI/HOnjYh-MJEc/s72-c/modelComparer%5B4%5D.png?imgmax=800' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-1534340480843905227</id><published>2010-07-01T16:49:00.001+07:00</published><updated>2010-07-02T16:40:15.679+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='EFv4'/><category scheme='http://www.blogger.com/atom/ns#' term='VS2010'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><title type='text'>Simplify Entity Framework v4 models with complex types</title><content type='html'>&lt;p&gt;One neat feature in Microsoft’s Entity Framework is support for complex types in the model. Complex types allow you to group together a bunch of properties in their own type and reuse that type from multiple entities. Complex types have been supported by Entity Framework from v1 although the v1 designer in Visual Studio 2008 didn’t support complex types, so until Visual Studio 2010 models using complex types had to be hand-edited in an XML editor.&lt;/p&gt;  &lt;p&gt;The EFv4 designer in Visual Studio 2010 does support complex types, but it still involves a fair bit of manual work to define them, add them to entities and create mappings when working with multiple entities. There is a “Refactor into New Complex Type” feature in the VS2010 EF designer, but it unfortunately only works with one entity at a time.&lt;/p&gt;  &lt;p&gt;To remedy this I looked into simplifying complex type creation and usage from multiple entity classes by adding a feature to &lt;a href="http://www.huagati.com/dbmltools/" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt; . The goal is to make generating and using complex types in EFv4 easier for EF models generated from existing databases.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_9F0FMyBvxXA/TCxkho1Di0I/AAAAAAAAAOU/zCYTdITBPMU/s1600-h/complexTypeMenu%5B7%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="EDMX Tools menu in VS2010" border="0" alt="EDMX Tools menu in VS2010" src="http://lh3.ggpht.com/_9F0FMyBvxXA/TCxkjtdYsII/AAAAAAAAAOY/-m3EuaRKr20/complexTypeMenu_thumb%5B5%5D.png?imgmax=800" width="434" height="241" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The new feature is quite simple, it lists all seemingly identical entity members in a model, ordered by number of occurrences in the model. A user can then select the members they want to generate a complex type from, and give the new type a name.&lt;/p&gt;  &lt;p&gt;While selecting members, the add-in shows which model entities share the selected members. When adding a complex type this way, the underlying entities and the conceptual-to-storage mapping will be automatically updated to incorporate the complex types and map to the correct storage members.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_9F0FMyBvxXA/TCxklxgEpQI/AAAAAAAAAOc/HsvWsTqU9t8/s1600-h/complexTypeDialog%5B8%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Complex type generator dialog" border="0" alt="Complex type generator dialog" src="http://lh4.ggpht.com/_9F0FMyBvxXA/TCxknwywfNI/AAAAAAAAAOg/VbVOUKw4qxg/complexTypeDialog_thumb%5B6%5D.png?imgmax=800" width="434" height="326" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;The process can then be repeated as many times as wanted, leading to a less cluttered model diagram with less repeated-over-and-over-again member properties.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_9F0FMyBvxXA/TCxkpPxNDtI/AAAAAAAAAOk/T1KqFQyAwxU/s1600-h/entitiesWithoutComplexTypes%5B4%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Entities without complex types" border="0" alt="Entities without complex types" src="http://lh5.ggpht.com/_9F0FMyBvxXA/TCxkqXJndmI/AAAAAAAAAOo/LM5mm5WH1Po/entitiesWithoutComplexTypes_thumb%5B2%5D.png?imgmax=800" width="391" height="466" /&gt;&lt;/a&gt;     &lt;br /&gt;…entities without complex types…&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;a href="http://lh6.ggpht.com/_9F0FMyBvxXA/TCxkrnMvkpI/AAAAAAAAAOs/JDdvw174DvI/s1600-h/entitiesWithComplexTypes%5B4%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Entities with complex types" border="0" alt="Entities with complex types" src="http://lh3.ggpht.com/_9F0FMyBvxXA/TCxks7VTWuI/AAAAAAAAAOw/VJep1Wwn49o/entitiesWithComplexTypes_thumb%5B2%5D.png?imgmax=800" width="383" height="376" /&gt;&lt;/a&gt;     &lt;br /&gt;…and the same entities after adding complex types…&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;This feature will be part of &lt;a href="http://www.huagati.com/dbmltools/" target="_blank"&gt;Huagati DBML/EDMX Tools&lt;/a&gt; version 1.90, together with some other new EFv4-specific features. The EFv4 specific features will only be available when using the add-in from Visual Studio 2010. Previously existing features will still work in both VS2008 and VS2010.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-1534340480843905227?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/1534340480843905227/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2010/07/simplify-entity-framework-v4-models.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/1534340480843905227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/1534340480843905227'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2010/07/simplify-entity-framework-v4-models.html' title='Simplify Entity Framework v4 models with complex types'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_9F0FMyBvxXA/TCxkjtdYsII/AAAAAAAAAOY/-m3EuaRKr20/s72-c/complexTypeMenu_thumb%5B5%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-5670967901968273594</id><published>2010-06-09T17:30:00.001+07:00</published><updated>2010-11-01T15:13:24.805+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><category scheme='http://www.blogger.com/atom/ns#' term='profiling'/><title type='text'>Entity Framework support in Huagati Query Profiler (formerly known as Huagati Linq-to-SQL profiler)</title><content type='html'>&lt;p&gt;When I &lt;a href="http://huagati.blogspot.com/2009/06/profiling-linq-to-sql-applications.html" target="_blank"&gt;first introduced the Huagati Linq-to-SQL Profiler&lt;/a&gt; nearly a year ago, I mentioned that it would eventually support other data access technologies than just Linq-to-SQL. Second up was support for &lt;a href="http://huagati.blogspot.com/2009/10/query-profiling-for-llblgen-pro-based.html" target="_blank"&gt;LLBLGen profiling released in October 2009&lt;/a&gt;. Now the turn has finally come to Microsoft’s Entity Framework 4.0. &lt;/p&gt;  &lt;p&gt;The concept is the same, the packaging is the same, and existing licensed users of the profiler can simply install the latest version to add support for Entity Framework query profiling in addition to the already existing Linq-to-SQL and LLBLGen profilers. &lt;/p&gt;  &lt;h4&gt;Why? Why not use SQL Profiler instead?&lt;/h4&gt;  &lt;p&gt;Database performance, and conserving db-side resources is often key to app performance in database driven applications. There are many tools around for profiling, and there can sometimes be an overlap between what they do. &lt;/p&gt;  &lt;p&gt;The Huagati Query Profiler bridges the gap between SQL Server and OR-mapper code. It collects important information about queries executed by Linq-to-SQL, Entity Framework, and LLBLGen and combines that information with stack traces and other details that make it easier to find out what code in an application is responsible for the most expensive or most long-running database queries. It overlaps with the SQL Server Profiler in collecting query information, with Visual Studio, and with SQL Server Management Studio, but adds the benefit of linking information otherwise available separately in each of the three applications together. &lt;/p&gt;  &lt;h4&gt;What does it do? How does it work? &lt;/h4&gt;  &lt;p&gt;The profiler consists of two main parts:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;A redistributable runtime DLL that you can reference from and include with your applications. There is one runtime logging DLL for each of EFv4, L2S, and LLBLGen. The runtime logging DLL collects information about what queries are executed against the database along with useful information such as timings, I/O cost, execution plans, and various feedback from SQL Server's query optimizer. &lt;/li&gt;    &lt;li&gt;The profiler log explorer application that is used for exploring logs generated by the runtime DLL, and examining individual log entries in more detail. &lt;/li&gt; &lt;/ol&gt;  &lt;h4&gt;Filters&lt;/h4&gt;  &lt;p&gt;Filters can be set up in both layers; in the runtime component to avoid logging non-costly queries or to narrow down on specific types of query behavior, and in the log explorer to narrow down specific types of queries when examining existing logs.&lt;/p&gt;  &lt;p&gt;The logging components have several built-in filters, and custom filters can easily be added if needed. &lt;/p&gt;  &lt;h4&gt;Code samples &lt;/h4&gt;  &lt;p&gt;After installing the profiler, Windows Programs menu will get a new program group called Huagati Query Profiler: &lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.huagati.com/l2sprofiler/screenshots/EFProfiler/ProgramsMenu.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Huagati Query Profiler program group" border="0" alt="Huagati Query Profiler program group" src="http://lh4.ggpht.com/_9F0FMyBvxXA/TA9syzBhZ3I/AAAAAAAAALk/NhXfocsK2Eg/ProgramsMenu%5B4%5D.png?imgmax=800" width="238" height="138" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The first entry, &lt;em&gt;Code Samples (zip)&lt;/em&gt; will open up a zip file containing a handful of sample Visual Studio projects in C# and VB. The sample projects shows how to integrate the runtime component with an existing application, and includes sample queries showing some typical operations. The Entity Framework 4 sample is called AdventureWorksEF and it uses the Microsoft AdventureWorks sample database. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.huagati.com/l2sprofiler/screenshots/EFProfiler/sampleProjectEDMX.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="AdventureWorks EF model in Visual Studio 2010" border="0" alt="AdventureWorks EF model in Visual Studio 2010" src="http://lh5.ggpht.com/_9F0FMyBvxXA/TA9s0TQUdOI/AAAAAAAAAMo/Y9VjSCE31uI/sampleProjectEDMX_small%5B5%5D.png?imgmax=800" width="409" height="286" /&gt;&lt;/a&gt;&lt;em&gt;&lt;font size="1"&gt;        &lt;br /&gt;AdventureWorks EF model in VS2010 (click for larger image)&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="Sample ObjectContext with profiler logging" href="http://www.huagati.com/l2sprofiler/screenshots/EFProfiler/sampleProjectObjectContext.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Sample EFv4 ObjectContext with profiler logging" border="0" alt="Sample EFv4 ObjectContext with profiler logging" src="http://lh4.ggpht.com/_9F0FMyBvxXA/TA9s2D9EAbI/AAAAAAAAAMw/JBlxequ5pGY/sampleProjectObjectContext_small%5B7%5D.png?imgmax=800" width="409" height="286" /&gt;       &lt;br /&gt;&lt;/a&gt;&lt;em&gt;&lt;font size="1"&gt;Sample ObjectContext with EF Profiling support added (click for larger image)&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;The UI of the sample project is simple, a small form with a single button. Behind the button are several sample queries, some doing a simple primary key lookup, others doing group/aggregate queries etc. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.huagati.com/l2sprofiler/screenshots/EFProfiler/SampleQueries.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Sample query in the EFv4 profiler logging code sample" border="0" alt="Sample query in the EFv4 profiler logging code sample" src="http://lh5.ggpht.com/_9F0FMyBvxXA/TA9s3_j2BDI/AAAAAAAAAM0/Lns2-PLH7Jg/SampleQueries_small%5B5%5D.png?imgmax=800" width="409" height="290" /&gt;&lt;/a&gt;&lt;em&gt;&lt;font size="1"&gt;        &lt;br /&gt;Query in the code samples project (click for larger image)&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;To generate some sample log entries for the log explorer, run the sample project and click on the Test! button.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.huagati.com/l2sprofiler/screenshots/EFProfiler/TestProjectUI.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="TestProjectUI" border="0" alt="TestProjectUI" src="http://lh5.ggpht.com/_9F0FMyBvxXA/TA9s5ML9ZuI/AAAAAAAAAL0/hrKyRdJ7sAE/TestProjectUI%5B4%5D.png?imgmax=800" width="307" height="164" /&gt;&lt;/a&gt;     &lt;br /&gt;&lt;em&gt;&lt;font size="1"&gt;Code sample project UI: a single button &lt;/font&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Before running the sample project, ensure that the connection string in app.config is pointing to where you have installed the &lt;a href="http://sqlserversamples.codeplex.com/" target="_blank"&gt;Microsoft AdventureWorks sample database&lt;/a&gt;. &lt;/p&gt;  &lt;h4&gt;The profiler log explorer&lt;/h4&gt;  &lt;p&gt;After generating log entries, start up the Profiler Log Explorer (Start/All Programs/Huagati Query Profiler/Huagati Query Profiler-Log Explorer). &lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.huagati.com/l2sprofiler/screenshots/EFProfiler/ProfilerLogViewer001.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="The Huagati Profiler Log Explorer main window" border="0" alt="The Huagati Profiler Log Explorer main window" src="http://lh4.ggpht.com/_9F0FMyBvxXA/TA9s7Vy7zRI/AAAAAAAAAM8/yJcpEpBu1dg/ProfilerLogViewer001_small%5B5%5D.png?imgmax=800" width="409" height="257" /&gt;&lt;/a&gt;&lt;em&gt;&lt;font size="1"&gt;        &lt;br /&gt;The Huagati Query Profiler Log Explorer main window (click for larger image)&lt;/font&gt;&lt;/em&gt; &lt;/p&gt;  &lt;p&gt;The log explorer's main window is divided in a few different sections: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The top portion of the screen contains a grid listing all queries in the log or all queries passing the criteria set under the Filters option in the toolbar): &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://www.huagati.com/l2sprofiler/screenshots/EFProfiler/ProfilerLogViewer001b_grid.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="List of queries" border="0" alt="List of queries" src="http://lh5.ggpht.com/_9F0FMyBvxXA/TA9s8qcfVRI/AAAAAAAAANA/LuhySGh1eT8/ProfilerLogViewer001b_grid_small%5B5%5D.png?imgmax=800" width="409" height="321" /&gt;&lt;/a&gt;&lt;em&gt;&lt;font size="1"&gt;        &lt;br /&gt;Query list (click for larger image)&lt;/font&gt;&lt;/em&gt; &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;In the lower left portion of the screen it shows the query behind the currently selected log entry, along with visual indicators for I/O, timings, and feedback from SQL Server's optimizer: &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://www.huagati.com/l2sprofiler/screenshots/EFProfiler/ProfilerLogViewer001c_queryInfo.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Lower right corner: Query Information" border="0" alt="Lower right corner: Query Information" src="http://lh3.ggpht.com/_9F0FMyBvxXA/TA9s91IouxI/AAAAAAAAANE/xiSZSjVA1Ck/ProfilerLogViewer001c_queryInfo_small%5B5%5D.png?imgmax=800" width="409" height="201" /&gt;&lt;/a&gt;&lt;em&gt;&lt;font size="1"&gt;        &lt;br /&gt;Query details (click for larger image)&lt;/font&gt;&lt;/em&gt; &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;In the lower right portion of the screen it shows the call stack that led to the query being executed. If symbols (pdb) were present when the log entry was created, the call stack will contain convenient hyperlinks that can be used to open up the corresponding source code file on a developer machine. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://www.huagati.com/l2sprofiler/screenshots/EFProfiler/ProfilerLogViewer001d_callStack.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Call Stack" border="0" alt="Call Stack" src="http://lh3.ggpht.com/_9F0FMyBvxXA/TA9s_t1JblI/AAAAAAAAANQ/sRp9Ekfv-ok/ProfilerLogViewer001d_callStack_small%5B5%5D.png?imgmax=800" width="409" height="239" /&gt;&lt;/a&gt;     &lt;br /&gt;&lt;em&gt;&lt;font size="1"&gt;Call stack (click for larger image)&lt;/font&gt;&lt;/em&gt; &lt;/p&gt;  &lt;h4&gt;Query information details&lt;/h4&gt;  &lt;p&gt;Many of the elements in the Query Information portion of the log explorer window will show additional details when hovered over, and/or when clicked on: &lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.huagati.com/l2sprofiler/screenshots/EFProfiler/missingIndexes.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Missing Indexes hover popup" border="0" alt="Missing Indexes hover popup" src="http://lh3.ggpht.com/_9F0FMyBvxXA/TA9tBZuubXI/AAAAAAAAANY/h_4lRTW8ZE4/missingIndexes_small%5B11%5D.png?imgmax=800" width="409" height="219" /&gt;&lt;/a&gt;     &lt;br /&gt;&lt;em&gt;&lt;font size="1"&gt;“Missing Indexes” alert with details in hover-popup (click for larger image)&lt;/font&gt;&lt;/em&gt;&amp;#160; &lt;br /&gt;    &lt;br /&gt;&lt;a href="http://www.huagati.com/l2sprofiler/screenshots/EFProfiler/tableScanAlert.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Table Scan alert with tooltip" border="0" alt="Table Scan alert with tooltip" src="http://lh4.ggpht.com/_9F0FMyBvxXA/TA9tCvQa3aI/AAAAAAAAAMM/AQkVSFbFWWw/tableScanAlert%5B4%5D.png?imgmax=800" width="463" height="138" /&gt;       &lt;br /&gt;&lt;/a&gt;&lt;em&gt;&lt;font size="1"&gt;Table scan alert with accompanying tooltip (click for larger image)&lt;/font&gt;&lt;/em&gt;&amp;#160; &lt;br /&gt;    &lt;br /&gt;&lt;a href="http://www.huagati.com/l2sprofiler/screenshots/EFProfiler/queryIOStats.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Query I/O cost" border="0" alt="Query I/O cost" src="http://lh3.ggpht.com/_9F0FMyBvxXA/TA9tD7o0wtI/AAAAAAAAANc/S2s6YoCPKlw/queryIOStats%5B5%5D.png?imgmax=800" width="377" height="397" /&gt;&lt;/a&gt;&lt;em&gt;&lt;font size="1"&gt;        &lt;br /&gt;I/O statistics are shown when hovering over any of the I/O numbers or info bars         &lt;br /&gt;&lt;/font&gt;&lt;/em&gt;    &lt;br /&gt;&lt;a href="http://www.huagati.com/l2sprofiler/screenshots/EFProfiler/queryTimings.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Query Timings" border="0" alt="Query Timings" src="http://lh5.ggpht.com/_9F0FMyBvxXA/TA9tFUcwjnI/AAAAAAAAANk/Hi-lE9Cr_1k/queryTimings%5B5%5D.png?imgmax=800" width="384" height="397" /&gt;&lt;/a&gt;&lt;em&gt;&lt;font size="1"&gt;        &lt;br /&gt;Timings are available by hovering over the timing numbers or indicator bars&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Some of the links, such as the execution plan link or source code links will start up other applications such as SQL Server Management Studio or Visual Studio.&lt;/p&gt;  &lt;p&gt;Clicking on the Execution Plan link for example will open up the logged execution plan for the query in SSMS: &lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.huagati.com/l2sprofiler/screenshots/EFProfiler/executionPlan.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Query execution plan in SSMS" border="0" alt="Query execution plan in SSMS" src="http://lh5.ggpht.com/_9F0FMyBvxXA/TA9tHV88R9I/AAAAAAAAANs/u-Tp7kbhDHA/executionPlan_small%5B5%5D.png?imgmax=800" width="409" height="287" /&gt;       &lt;br /&gt;&lt;/a&gt;&lt;em&gt;&lt;font size="1"&gt;Clicking on the “execution plan” link brings up SSMS with the logged execution plan (click for larger image)&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;  &lt;h4&gt;Missing indexes sample&lt;/h4&gt;  &lt;p&gt;The particular sample query shown in the screenshots above has a missing index alert: &lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.huagati.com/l2sprofiler/screenshots/EFProfiler/missingIndexes.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Missing index alert" border="0" alt="Missing index alert" src="http://lh6.ggpht.com/_9F0FMyBvxXA/TA9tJir4YYI/AAAAAAAAAN0/Jz95l4wLxBI/missingIndexes_small%5B12%5D.png?imgmax=800" width="409" height="219" /&gt;       &lt;br /&gt;&lt;/a&gt;&lt;em&gt;&lt;font size="1"&gt;Missing indexes alert (click for larger image)&lt;/font&gt;&lt;/em&gt; &lt;/p&gt;  &lt;p&gt;A missing index alert means that SQL Server's optimizer determined that the query in question can be made more efficient by adding indexes to one or more tables involved. Hovering over the index alert will display the optimizer's suggested indexes. &lt;/p&gt;  &lt;p&gt;In this case, the optimizer suggested three new indexes: &lt;/p&gt;  &lt;p&gt;&lt;font face="Courier"&gt;create index IX_SalesOrderHeader_ShipToAddressID on [AdventureWorks].[Sales].[SalesOrderHeader] ([ShipToAddressID], [OrderDate]) include ([Status], [TotalDue]);      &lt;br /&gt;      &lt;br /&gt;create index IX_SalesOrderHeader_OrderDate on [AdventureWorks].[Sales].[SalesOrderHeader] ([OrderDate], [Status]) include ([ShipToAddressID], [TotalDue]);       &lt;br /&gt;      &lt;br /&gt;create index IX_Address_PostalCode on [AdventureWorks].[Person].[Address] ([PostalCode]) include ([AddressID]); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;However, looking closer at the optimizer's suggestions, two of the indexes can be combined into one to avoid overlap: &lt;/p&gt;  &lt;p&gt;&lt;font face="Courier"&gt;create index IX_Address_PostalCode on [Person].[Address] ([PostalCode]) &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier"&gt;create index IX_SalesOrderHeader_ShipToAddressID on [Sales].[SalesOrderHeader] ([ShipToAddressID], [OrderDate], [Status]) include ([TotalDue]); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;After re-running the sample app and hitting Refresh in the log explorer we can see what the result of the new indexes were - in this case the query went from 919 reads and a table scan, down to to 54 and index seeks: &lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.huagati.com/l2sprofiler/screenshots/EFProfiler/ProfilerLogViewer002b_IO.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Sample Query #1 I/O after adding indexes" border="0" alt="Sample Query #1 I/O after adding indexes" src="http://lh3.ggpht.com/_9F0FMyBvxXA/TA9tK0AoupI/AAAAAAAAAN8/msVx06GHjTg/ProfilerLogViewer002b_IO%5B5%5D.png?imgmax=800" width="409" height="397" /&gt;&lt;/a&gt;&lt;em&gt;&lt;font size="1"&gt;        &lt;br /&gt;Query I/O for sample #1 after adding indexes as per above&lt;/font&gt;&lt;/em&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;Where do I get it, how do I get started? &lt;/h4&gt;  &lt;p&gt;The Entity Framework 4 logging component for the &lt;a href="http://www.huagati.com/L2SProfiler/" target="_blank"&gt;Huagati Query Profiler&lt;/a&gt; is included as of version 1.31, and is included in the installer that can be downloaded from &lt;a href="http://huagati.com/L2SProfiler/"&gt;http://huagati.com/L2SProfiler/&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;If you have an existing license for Huagati Linq-to-SQL Profiler or Huagati Query Profiler, you can simply install the latest version to get the EF logging component in addition to the Linq-to-SQL and LLBLGen logging components. If you don't have a license you can request a trial license key from:    &lt;br /&gt;&lt;a href="http://www.huagati.com/l2sprofiler/"&gt;http://www.huagati.com/l2sprofiler/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Additionally, during the beta period - if you become a beta tester and the provide feedback from your testing you will get a full license key for the final released version. To apply to become a beta tester, send an email to support (at) huagati.com.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Feedback and questions are always welcome, you can send your feedback or questions to support (at) huagati.com, or post it in the &lt;a href="http://forum.huagati.com/forum4-huagati-linqtosql-profiler-support.aspx" target="_blank"&gt;support forum&lt;/a&gt;, or post a comment in this blog.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-5670967901968273594?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/5670967901968273594/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2010/06/entity-framework-support-in-huagati.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/5670967901968273594'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/5670967901968273594'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2010/06/entity-framework-support-in-huagati.html' title='Entity Framework support in Huagati Query Profiler (formerly known as Huagati Linq-to-SQL profiler)'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_9F0FMyBvxXA/TA9syzBhZ3I/AAAAAAAAALk/NhXfocsK2Eg/s72-c/ProgramsMenu%5B4%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-29530441831068541</id><published>2009-10-05T11:13:00.004+07:00</published><updated>2009-10-05T11:58:23.222+07:00</updated><title type='text'>Query Profiling for LLBLGen Pro-based applications</title><content type='html'>When I &lt;a href="http://huagati.blogspot.com/2009/06/profiling-linq-to-sql-applications.html"&gt;introduced the first release&lt;/a&gt; of the Huagati Linq-to-SQL Profiler back in August, I mentioned that there would be additional profiler runtime logging providers besides the initial one for Linq-to-SQL; "&lt;em&gt;Additional logging providers; if there is enough interest I may extend the runtime logging component to also support Entity Framework, plain ADO.NET, or other data access technologies such as 3rd party OR/Ms.&lt;/em&gt;".&lt;br /&gt;&lt;br /&gt;The profiler's log file format and the profiler log viewer is not tied in any way to Linq-to-SQL specifically. Although the choice of name for the tool may not be ideal, it was designed to be used with other OR mappers and data access technologies as well.&lt;br /&gt;&lt;br /&gt;A few weeks ago I contacted &lt;a href="http://weblogs.asp.net/fbouma/"&gt;Frans Bouma&lt;/a&gt;, author of the popular &lt;a href="http://www.llblgen.com/"&gt;LLBLGen Pro O/R Mapper Generator&lt;/a&gt;. LLBLGen Pro has been around for six years and is packed with great functionality; no doubt the market leading OR mapper for .net. Frans was enthusiastic about the idea, so we exchanged a couple of emails to determine the best approach to integrate profiler logging into LLBLGen based projects without requiring too much of an effort of work by end-users. Frans suggested using a partial class implementation of LLBLGen's DataAccessAdapter class, so that's the direction I went.&lt;br /&gt;&lt;br /&gt;Due to some time constraints in other projects I had to suspend work on the LLBLGen profiler logging component for a couple of weeks, but it is now ready for release.&lt;br /&gt;&lt;br /&gt;To enable query profiling in a LLBLGen based project, some minor additions are needed in the application to be profiled. A reference to the profiler logging assembly must be added, and a new partial class implementation of the LLBLGen Pro DataAccessAdapter containing calls to the profiler logger need to be included in the same project as the LLBLGen generated code.&lt;br /&gt;&lt;br /&gt;The following screenshots shows step-by-step how to enable query profiling in the &lt;a href="http://www.llblgen.com/pages/files/Example_NorthwindCS1_Adapter_06062008.zip"&gt;LLBLGen Northwind Adapter&lt;/a&gt; sample project (downloadable from http://www.llblgen.com/pages/files/Example_NorthwindCS1_Adapter_06062008.zip ). Click on the individual screenshots for a full-size version.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Add a reference to the profiler logging assembly (HuagatiLLBLGenProfiler.dll) (A), include LoggingAdapter.cs (B) &lt;em&gt;(both are installed together with the profiler itself under C:\Program Files [(x86)]\Huagati Systems Co Ltd\Huagati Linq-to-SQL Profiler\redist )&lt;/em&gt;. Next, change the namespace in LoggingAdapter.cs to match the namespace of the application's own DataAccessAdapter class (C).&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_9F0FMyBvxXA/Ssl3aKayCBI/AAAAAAAAAHs/tDH2WpqILiM/s1600-h/LLBLGenProfiling01.png"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 289px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5388969720482498578" border="0" alt="" src="http://2.bp.blogspot.com/_9F0FMyBvxXA/Ssl3aKayCBI/AAAAAAAAAHs/tDH2WpqILiM/s400/LLBLGenProfiling01.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Add a call to one of the InitializeLogging methods in the DataAccessAdapter's constructor(s). There are a few different overloads of InitializeLogging, depending on what logging features, filters, etc that you want to use.&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_9F0FMyBvxXA/Ssl3avWSA1I/AAAAAAAAAH0/85vFiWXWlRc/s1600-h/LLBLGenProfiling02.png"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 289px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5388969730395734866" border="0" alt="" src="http://4.bp.blogspot.com/_9F0FMyBvxXA/Ssl3avWSA1I/AAAAAAAAAH0/85vFiWXWlRc/s400/LLBLGenProfiling02.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Compile and run the application.&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_9F0FMyBvxXA/Ssl3a33pc2I/AAAAAAAAAH8/M_KSYZXD4Ls/s1600-h/LLBLGenProfiling03.png"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 354px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5388969732683166562" border="0" alt="" src="http://4.bp.blogspot.com/_9F0FMyBvxXA/Ssl3a33pc2I/AAAAAAAAAH8/M_KSYZXD4Ls/s400/LLBLGenProfiling03.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; Start the Huagati Linq-to-SQL Profiler Viewer, open the logging directory used, and have fun with the logs:&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_9F0FMyBvxXA/Ssl3baOruFI/AAAAAAAAAIE/UYli7YJYIdE/s1600-h/LLBLGenProfiling04.png"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 291px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5388969741906589778" border="0" alt="" src="http://4.bp.blogspot.com/_9F0FMyBvxXA/Ssl3baOruFI/AAAAAAAAAIE/UYli7YJYIdE/s400/LLBLGenProfiling04.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Just as when profiling a Linq-to-SQL application, the top part of the window shows log entries and the bottom part shows details such as I/O statistics, timings, call stack etc pertaining to the selected log entry. All blue underlined links are clickable and will bring up additional details; clicking on the execution plan link will open the execution plan diagram in SSMS, clicking on the source code links in the call stack will open up the source file linked to in Visual Studio and so on.&lt;br /&gt;&lt;br /&gt;Database-side I/O statistics and timings are shown in easy-to-spot bars indicating the relative cost. Each one has a tooltip containing more detailed information from the database engine:&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_9F0FMyBvxXA/Ssl3biDe4qI/AAAAAAAAAIM/xRpoAOQUe8U/s1600-h/LLBLGenProfiling05.png"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 191px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5388969744007094946" border="0" alt="" src="http://4.bp.blogspot.com/_9F0FMyBvxXA/Ssl3biDe4qI/AAAAAAAAAIM/xRpoAOQUe8U/s400/LLBLGenProfiling05.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The call stack portion shows the call stack that led to a certain query being executed, with hyperlinks directly to the source code (whenever debug information and source code is available):&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_9F0FMyBvxXA/Ssl3tcG8wiI/AAAAAAAAAIU/Lk4YyZr77JA/s1600-h/LLBLGenProfiling05b.png"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 163px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5388970051648668194" border="0" alt="" src="http://1.bp.blogspot.com/_9F0FMyBvxXA/Ssl3tcG8wiI/AAAAAAAAAIU/Lk4YyZr77JA/s400/LLBLGenProfiling05b.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In short, it is &lt;em&gt;as easy&lt;/em&gt; to get started with profiling LLBLGen based applications as it is to profile Linq-to-SQL based applications.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://www.huagati.com/l2sprofiler/runtimehelp/html/N_Huagati_LinqToSQL_Profiler_Filters.htm"&gt;filters available&lt;/a&gt; in the LLBLGen logging component are the same as the filters available in the Linq-to-SQL logging component. This means that after adding profiling to a LLBLGen app as in the steps above, the examples shown in "&lt;a href="http://huagati.blogspot.com/2009/08/walkthrough-of-newest-filters-and.html"&gt;A walkthrough of the newest filters and visual cues in the Huagati Linq-to-SQL Profiler&lt;/a&gt;", and "&lt;a href="http://huagati.blogspot.com/2009/06/profiling-linq-to-sql-applications.html"&gt;Profiling Linq-to-SQL Applications&lt;/a&gt;" will work with the LLBLGen profiler logging component as well. Custom logging filters can of course also be added the same way; by creating a new class inheriting from the &lt;a href="http://www.huagati.com/l2sprofiler/runtimehelp/html/T_Huagati_LinqToSQL_Profiler_Filters_ProfilerFilter.htm"&gt;ProfilerFilter&lt;/a&gt; base class or from one of the pre-defined filters.&lt;br /&gt;&lt;br /&gt;The profiler logging component for LLBLGen Pro is included in &lt;a href="http://www.huagati.com/L2SProfiler"&gt;Huagati Linq-to-SQL Profiler&lt;/a&gt; version 1.20 (scheduled for release on Oct 12 2009).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-29530441831068541?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/29530441831068541/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2009/10/query-profiling-for-llblgen-pro-based.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/29530441831068541'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/29530441831068541'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2009/10/query-profiling-for-llblgen-pro-based.html' title='Query Profiling for LLBLGen Pro-based applications'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_9F0FMyBvxXA/Ssl3aKayCBI/AAAAAAAAAHs/tDH2WpqILiM/s72-c/LLBLGenProfiling01.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-848768152102581929</id><published>2009-10-04T09:19:00.006+07:00</published><updated>2009-10-04T10:44:25.371+07:00</updated><title type='text'>Code sample: Search and replace in Linq expression trees</title><content type='html'>I recently had the need* to do a 'search and replace' of a parameter in a linq query. It would have been nice to have a set of .Replace methods on the expression object to achieve this, but unfortunately there is no such thing. Instead I had to write a new expression tree visitor to clone the tree, and in the process replace the expression I want replaced with its' replacement.&lt;br /&gt;&lt;br /&gt;I figured it would make sense to post it here in case anyone else need a search-and-replace for expression trees. This sample will replace all occurences of one ParameterExpression with another one but can easily be changed to replace any other type of expression.&lt;br /&gt;&lt;br /&gt;* = And as for the 'why would I ever need to do that' - my specific need was to take a linq query and switch around portions of the projection it was doing without having to define an entirely new projection. I will get to the details of that in a follow up post - to keep this one short and simple... :)&lt;br /&gt;&lt;br /&gt;Enjoy:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ExpressionExtensions&lt;br /&gt;{&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// Replace all occurences of a ParameterExpression within an expression tree with another ParameterExpression, and return a cloned tree&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="expression"&amp;gt;Tree to replace parameters in&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="oldParameter"&amp;gt;Parameter to replace&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="newParameter"&amp;gt;Parameter to use as replacement&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;A cloned expression tree with all occurences of oldParameter replaced with newParameter&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; Expression ReplaceParameter(&lt;span class="kwrd"&gt;this&lt;/span&gt; Expression expression, ParameterExpression oldParameter, ParameterExpression newParameter)&lt;br /&gt;    {&lt;br /&gt;        Expression exp = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;        Type expressionType = expression.GetType();&lt;br /&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (expressionType == &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(ParameterExpression))&lt;br /&gt;        {&lt;br /&gt;            exp = ((ParameterExpression)expression).ReplaceParameter(oldParameter, newParameter);&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (expressionType == &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(MemberExpression))&lt;br /&gt;        {&lt;br /&gt;            exp = ((MemberExpression)expression).ReplaceParameter(oldParameter, newParameter);&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (expressionType == &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(MethodCallExpression))&lt;br /&gt;        {&lt;br /&gt;            exp = ((MethodCallExpression)expression).ReplaceParameter(oldParameter, newParameter);&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (expressionType == &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(NewExpression))&lt;br /&gt;        {&lt;br /&gt;            exp = ((NewExpression)expression).ReplaceParameter(oldParameter, newParameter);&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (expressionType == &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(UnaryExpression))&lt;br /&gt;        {&lt;br /&gt;            exp = ((UnaryExpression)expression).ReplaceParameter(oldParameter, newParameter);&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (expressionType == &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(ConstantExpression))&lt;br /&gt;        {&lt;br /&gt;            exp = ((ConstantExpression)expression).ReplaceParameter(oldParameter, newParameter);&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (expressionType == &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(ConditionalExpression))&lt;br /&gt;        {&lt;br /&gt;            exp = ((ConditionalExpression)expression).ReplaceParameter(oldParameter, newParameter);&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (expressionType == &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(LambdaExpression))&lt;br /&gt;        {&lt;br /&gt;            exp = ((LambdaExpression)expression).ReplaceParameter(oldParameter, newParameter);&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (expressionType == &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(MemberInitExpression))&lt;br /&gt;        {&lt;br /&gt;            exp = ((MemberInitExpression)expression).ReplaceParameter(oldParameter, newParameter);&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (expressionType == &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(BinaryExpression))&lt;br /&gt;        {&lt;br /&gt;            exp = ((BinaryExpression)expression).ReplaceParameter(oldParameter, newParameter);&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="rem"&gt;//did I forget some expression type? probably. this will take care of that... :)&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotImplementedException(&lt;span class="str"&gt;"Expression type "&lt;/span&gt; + expression.GetType().FullName + &lt;span class="str"&gt;" not supported by this expression tree parser."&lt;/span&gt;);&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; exp;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// Replace all occurences of a ParameterExpression within an expression tree with another ParameterExpression, and return a cloned tree&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="expression"&amp;gt;LambdaExpression to replace parameters in&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="oldParameter"&amp;gt;Parameter to replace&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="newParameter"&amp;gt;Parameter to use as replacement&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;A cloned expression tree with all occurences of oldParameter replaced with newParameter&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; LambdaExpression ReplaceParameter(&lt;span class="kwrd"&gt;this&lt;/span&gt; LambdaExpression expression, ParameterExpression oldParameter, ParameterExpression newParameter)&lt;br /&gt;    {&lt;br /&gt;        LambdaExpression lambdaExpression = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;        lambdaExpression = Expression.Lambda(&lt;br /&gt;            expression.Type,&lt;br /&gt;            expression.Body.ReplaceParameter(oldParameter, newParameter),&lt;br /&gt;            (expression.Parameters != &lt;span class="kwrd"&gt;null&lt;/span&gt;) ? expression.Parameters.ReplaceParameter(oldParameter, newParameter) : &lt;span class="kwrd"&gt;null&lt;/span&gt;&lt;br /&gt;            );&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; lambdaExpression;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// Replace all occurences of a ParameterExpression within an expression tree with another ParameterExpression, and return a cloned tree&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="expression"&amp;gt;BinaryExpression to replace parameters in&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="oldParameter"&amp;gt;Parameter to replace&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="newParameter"&amp;gt;Parameter to use as replacement&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;A cloned expression tree with all occurences of oldParameter replaced with newParameter&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; BinaryExpression ReplaceParameter(&lt;span class="kwrd"&gt;this&lt;/span&gt; BinaryExpression expression, ParameterExpression oldParameter, ParameterExpression newParameter)&lt;br /&gt;    {&lt;br /&gt;        BinaryExpression binaryExp = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;        binaryExp = Expression.MakeBinary(&lt;br /&gt;            expression.NodeType,&lt;br /&gt;            (expression.Left != &lt;span class="kwrd"&gt;null&lt;/span&gt;) ? expression.Left.ReplaceParameter(oldParameter, newParameter) : &lt;span class="kwrd"&gt;null&lt;/span&gt;,&lt;br /&gt;            (expression.Right != &lt;span class="kwrd"&gt;null&lt;/span&gt;) ? expression.Right.ReplaceParameter(oldParameter, newParameter) : &lt;span class="kwrd"&gt;null&lt;/span&gt;,&lt;br /&gt;            expression.IsLiftedToNull,&lt;br /&gt;            expression.Method,&lt;br /&gt;            (expression.Conversion != &lt;span class="kwrd"&gt;null&lt;/span&gt;) ? expression.Conversion.ReplaceParameter(oldParameter,newParameter) : &lt;span class="kwrd"&gt;null&lt;/span&gt;&lt;br /&gt;            );&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; binaryExp;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// Replace all occurences of a ParameterExpression within an expression tree with another ParameterExpression, and return a cloned tree&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="expression"&amp;gt;ParameterExpression to replace parameters in&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="oldParameter"&amp;gt;Parameter to replace&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="newParameter"&amp;gt;Parameter to use as replacement&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;A cloned expression tree with all occurences of oldParameter replaced with newParameter&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; ParameterExpression ReplaceParameter(&lt;span class="kwrd"&gt;this&lt;/span&gt; ParameterExpression expression, ParameterExpression oldParameter, ParameterExpression newParameter)&lt;br /&gt;    {&lt;br /&gt;        ParameterExpression paramExpression = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (expression.Equals(oldParameter))&lt;br /&gt;        {&lt;br /&gt;            paramExpression = newParameter;&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;        {&lt;br /&gt;            paramExpression = expression;&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; paramExpression;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// Replace all occurences of a ParameterExpression within an expression tree with another ParameterExpression, and return a cloned tree&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="expression"&amp;gt;MemberExpression to replace parameters in&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="oldParameter"&amp;gt;Parameter to replace&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="newParameter"&amp;gt;Parameter to use as replacement&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;A cloned expression tree with all occurences of oldParameter replaced with newParameter&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; MemberExpression ReplaceParameter(&lt;span class="kwrd"&gt;this&lt;/span&gt; MemberExpression expression, ParameterExpression oldParameter, ParameterExpression newParameter)&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; Expression.MakeMemberAccess(&lt;br /&gt;            (expression.Expression != &lt;span class="kwrd"&gt;null&lt;/span&gt;) ? expression.Expression.ReplaceParameter(oldParameter, newParameter) : &lt;span class="kwrd"&gt;null&lt;/span&gt;,&lt;br /&gt;            expression.Member);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// Replace all occurences of a ParameterExpression within an expression tree with another ParameterExpression, and return a cloned tree&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="expression"&amp;gt;MemberInitExpression to replace parameters in&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="oldParameter"&amp;gt;Parameter to replace&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="newParameter"&amp;gt;Parameter to use as replacement&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;A cloned expression tree with all occurences of oldParameter replaced with newParameter&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; MemberInitExpression ReplaceParameter(&lt;span class="kwrd"&gt;this&lt;/span&gt; MemberInitExpression expression, ParameterExpression oldParameter, ParameterExpression newParameter)&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; Expression.MemberInit(&lt;br /&gt;            (expression.NewExpression != &lt;span class="kwrd"&gt;null&lt;/span&gt;) ? expression.NewExpression.ReplaceParameter(oldParameter, newParameter) : &lt;span class="kwrd"&gt;null&lt;/span&gt;,&lt;br /&gt;            (expression.Bindings != &lt;span class="kwrd"&gt;null&lt;/span&gt;) ? expression.Bindings.ReplaceParameter(oldParameter, newParameter) : &lt;span class="kwrd"&gt;null&lt;/span&gt;&lt;br /&gt;            );&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// Replace all occurences of a ParameterExpression within an expression tree with another ParameterExpression, and return a cloned tree&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="expression"&amp;gt;MethodCallExpression to replace parameters in&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="oldParameter"&amp;gt;Parameter to replace&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="newParameter"&amp;gt;Parameter to use as replacement&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;A cloned expression tree with all occurences of oldParameter replaced with newParameter&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; MethodCallExpression ReplaceParameter(&lt;span class="kwrd"&gt;this&lt;/span&gt; MethodCallExpression expression, ParameterExpression oldParameter, ParameterExpression newParameter)&lt;br /&gt;    {&lt;br /&gt;        MethodCallExpression callExpression = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;        callExpression = Expression.Call(&lt;br /&gt;            (expression.Object != &lt;span class="kwrd"&gt;null&lt;/span&gt;) ? expression.Object.ReplaceParameter(oldParameter, newParameter) : &lt;span class="kwrd"&gt;null&lt;/span&gt;,&lt;br /&gt;            expression.Method,&lt;br /&gt;            (expression.Arguments != &lt;span class="kwrd"&gt;null&lt;/span&gt;) ? expression.Arguments.ReplaceParameter(oldParameter, newParameter) : &lt;span class="kwrd"&gt;null&lt;/span&gt;&lt;br /&gt;            );&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; callExpression;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// Replace all occurences of a ParameterExpression within an expression tree with another ParameterExpression, and return a cloned tree&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="expression"&amp;gt;NewExpression to replace parameters in&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="oldParameter"&amp;gt;Parameter to replace&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="newParameter"&amp;gt;Parameter to use as replacement&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;A cloned expression tree with all occurences of oldParameter replaced with newParameter&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; NewExpression ReplaceParameter(&lt;span class="kwrd"&gt;this&lt;/span&gt; NewExpression expression, ParameterExpression oldParameter, ParameterExpression newParameter)&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; Expression.New(&lt;br /&gt;            expression.Constructor,&lt;br /&gt;            (expression.Arguments != &lt;span class="kwrd"&gt;null&lt;/span&gt;) ? expression.Arguments.ReplaceParameter(oldParameter, newParameter) : &lt;span class="kwrd"&gt;null&lt;/span&gt;,&lt;br /&gt;            expression.Members);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// Replace all occurences of a ParameterExpression within a ReadonlyCollection of ParameterExpressions with another ParameterExpression, and return as an IEnumerable&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="expression"&amp;gt;ReadOnlyCollection&amp;amp;lt;ParameterExpression&amp;amp;gt; to replace parameters in&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="oldParameter"&amp;gt;Parameter to replace&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="newParameter"&amp;gt;Parameter to use as replacement&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;A IEnumerable returning the passed in set of ParameterExpressions, with occurences of oldParameter replaced with newParameter&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; IEnumerable&amp;lt;ParameterExpression&amp;gt; ReplaceParameter(&lt;span class="kwrd"&gt;this&lt;/span&gt; System.Collections.ObjectModel.ReadOnlyCollection&amp;lt;ParameterExpression&amp;gt; expressionArguments, ParameterExpression oldParameter, ParameterExpression newParameter)&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (expressionArguments != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (ParameterExpression argument &lt;span class="kwrd"&gt;in&lt;/span&gt; expressionArguments)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (argument != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;                {&lt;br /&gt;                    &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; argument.ReplaceParameter(oldParameter, newParameter);&lt;br /&gt;                }&lt;br /&gt;                &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;                {&lt;br /&gt;                    &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// Replace all occurences of a ParameterExpression within a ReadonlyCollection of Expressions with another ParameterExpression, and return as an IEnumerable&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="expression"&amp;gt;ReadOnlyCollection&amp;amp;lt;Expression&amp;amp;gt; to replace parameters in&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="oldParameter"&amp;gt;Parameter to replace&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="newParameter"&amp;gt;Parameter to use as replacement&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;A IEnumerable returning the passed in set of Expressions, with occurences of oldParameter replaced with newParameter&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; IEnumerable&amp;lt;Expression&amp;gt; ReplaceParameter(&lt;span class="kwrd"&gt;this&lt;/span&gt; System.Collections.ObjectModel.ReadOnlyCollection&amp;lt;Expression&amp;gt; expressionArguments, ParameterExpression oldParameter, ParameterExpression newParameter)&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (expressionArguments != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Expression argument &lt;span class="kwrd"&gt;in&lt;/span&gt; expressionArguments)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (argument != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;                {&lt;br /&gt;                    &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; argument.ReplaceParameter(oldParameter, newParameter);&lt;br /&gt;                }&lt;br /&gt;                &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;                {&lt;br /&gt;                    &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// Replace all occurences of a ParameterExpression within a ReadonlyCollection of ElementInits with another ParameterExpression, and return as an IEnumerable&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="expression"&amp;gt;ReadOnlyCollection&amp;amp;lt;ElementInit&amp;amp;gt; to replace parameters in&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="oldParameter"&amp;gt;Parameter to replace&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="newParameter"&amp;gt;Parameter to use as replacement&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;A IEnumerable returning the passed in set of ParameterExpressions, with occurences of oldParameter replaced with newParameter&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; IEnumerable&amp;lt;ElementInit&amp;gt; ReplaceParameter(&lt;span class="kwrd"&gt;this&lt;/span&gt; System.Collections.ObjectModel.ReadOnlyCollection&amp;lt;ElementInit&amp;gt; elementInits, ParameterExpression oldParameter, ParameterExpression newParameter)&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (elementInits != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (ElementInit elementInit &lt;span class="kwrd"&gt;in&lt;/span&gt; elementInits)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (elementInit != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;                {&lt;br /&gt;                    &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; Expression.ElementInit(elementInit.AddMethod, elementInit.Arguments.ReplaceParameter(oldParameter, newParameter));&lt;br /&gt;                }&lt;br /&gt;                &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;                {&lt;br /&gt;                    &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// Replace all occurences of a ParameterExpression within a ReadonlyCollection of MemberBindings with another ParameterExpression, and return as an IEnumerable&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="expression"&amp;gt;ReadOnlyCollection&amp;amp;lt;MemberBinding&amp;amp;gt; to replace parameters in&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="oldParameter"&amp;gt;Parameter to replace&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="newParameter"&amp;gt;Parameter to use as replacement&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;A IEnumerable returning the passed in set of ParameterExpressions, with occurences of oldParameter replaced with newParameter&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; IEnumerable&amp;lt;MemberBinding&amp;gt; ReplaceParameter(&lt;span class="kwrd"&gt;this&lt;/span&gt; System.Collections.ObjectModel.ReadOnlyCollection&amp;lt;MemberBinding&amp;gt; memberBindings, ParameterExpression oldParameter, ParameterExpression newParameter)&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (memberBindings != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (MemberBinding binding &lt;span class="kwrd"&gt;in&lt;/span&gt; memberBindings)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (binding != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;                {&lt;br /&gt;                    &lt;span class="kwrd"&gt;switch&lt;/span&gt; (binding.BindingType)&lt;br /&gt;                    {&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; MemberBindingType.Assignment:&lt;br /&gt;                            MemberAssignment memberAssignment = (MemberAssignment)binding;&lt;br /&gt;                            &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; Expression.Bind(binding.Member, memberAssignment.Expression.ReplaceParameter(oldParameter, newParameter));&lt;br /&gt;                            &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; MemberBindingType.ListBinding:&lt;br /&gt;                            MemberListBinding listBinding = (MemberListBinding)binding;&lt;br /&gt;                            &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; Expression.ListBind(binding.Member, listBinding.Initializers.ReplaceParameter(oldParameter, newParameter));&lt;br /&gt;                            &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; MemberBindingType.MemberBinding:&lt;br /&gt;                            MemberMemberBinding memberMemberBinding = (MemberMemberBinding)binding;&lt;br /&gt;                            &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; Expression.MemberBind(binding.Member, memberMemberBinding.Bindings.ReplaceParameter(oldParameter, newParameter));&lt;br /&gt;                            &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;                {&lt;br /&gt;                    &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// Replace all occurences of a ParameterExpression within an expression tree with another ParameterExpression, and return a cloned tree&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="expression"&amp;gt;UnaryExpression to replace parameters in&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="oldParameter"&amp;gt;Parameter to replace&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="newParameter"&amp;gt;Parameter to use as replacement&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;A cloned expression tree with all occurences of oldParameter replaced with newParameter&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; UnaryExpression ReplaceParameter(&lt;span class="kwrd"&gt;this&lt;/span&gt; UnaryExpression expression, ParameterExpression oldParameter, ParameterExpression newParameter)&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; Expression.MakeUnary(&lt;br /&gt;            expression.NodeType,&lt;br /&gt;            (expression.Operand != &lt;span class="kwrd"&gt;null&lt;/span&gt;) ? expression.Operand.ReplaceParameter(oldParameter, newParameter) : &lt;span class="kwrd"&gt;null&lt;/span&gt;,&lt;br /&gt;            expression.Type,&lt;br /&gt;            expression.Method);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// Replace all occurences of a ParameterExpression within an expression tree with another ParameterExpression, and return a cloned tree. Note: this version of ReplaceParameter exists just for conformity - there can't be a parameter expression hiding under a constant expression so this could really be skipped.&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="expression"&amp;gt;ConstantExpression to replace parameters in&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="oldParameter"&amp;gt;Parameter to replace&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="newParameter"&amp;gt;Parameter to use as replacement&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;A cloned expression tree with all occurences of oldParameter replaced with newParameter&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; ConstantExpression ReplaceParameter(&lt;span class="kwrd"&gt;this&lt;/span&gt; ConstantExpression expression, ParameterExpression oldParameter, ParameterExpression newParameter)&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="rem"&gt;//return Expression.Constant(expression.Value, expression.Type);&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; expression;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// Replace all occurences of a ParameterExpression within an expression tree with another ParameterExpression, and return a cloned tree&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="expression"&amp;gt;ConditionalExpression to replace parameters in&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="oldParameter"&amp;gt;Parameter to replace&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="newParameter"&amp;gt;Parameter to use as replacement&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;A cloned expression tree with all occurences of oldParameter replaced with newParameter&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; ConditionalExpression ReplaceParameter(&lt;span class="kwrd"&gt;this&lt;/span&gt; ConditionalExpression expression, ParameterExpression oldParameter, ParameterExpression newParameter)&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; Expression.Condition(&lt;br /&gt;            (expression.Test != &lt;span class="kwrd"&gt;null&lt;/span&gt;) ? expression.Test.ReplaceParameter(oldParameter, newParameter) : &lt;span class="kwrd"&gt;null&lt;/span&gt;,&lt;br /&gt;            (expression.IfTrue != &lt;span class="kwrd"&gt;null&lt;/span&gt;) ? expression.IfTrue.ReplaceParameter(oldParameter, newParameter) : &lt;span class="kwrd"&gt;null&lt;/span&gt;,&lt;br /&gt;            (expression.IfFalse != &lt;span class="kwrd"&gt;null&lt;/span&gt;) ? expression.IfFalse.ReplaceParameter(oldParameter, newParameter) : &lt;span class="kwrd"&gt;null&lt;/span&gt;&lt;br /&gt;            );&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-848768152102581929?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/848768152102581929/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2009/10/code-sample-search-and-replace-in-linq.html#comment-form' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/848768152102581929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/848768152102581929'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2009/10/code-sample-search-and-replace-in-linq.html' title='Code sample: Search and replace in Linq expression trees'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-8660907914213464133</id><published>2009-08-07T13:00:00.007+07:00</published><updated>2009-08-07T14:08:10.737+07:00</updated><title type='text'>A walkthrough of the newest filters and visual cues in the Huagati Linq-to-SQL Profiler</title><content type='html'>Some useful new features were added to the latest two versions of the &lt;a href="http://www.huagati.com/L2SProfiler/"&gt;Huagati Linq-to-SQL Profiler&lt;/a&gt;. First up in version 1.14 was a handful of new &lt;a href="http://www.huagati.com/L2SProfiler/runtimehelp/html/N_Huagati_LinqToSQL_Profiler_Filters.htm"&gt;runtime filters&lt;/a&gt; in the redistributable DLLs that takes care of logging profiler data; among the new filters are the &lt;a href="http://www.huagati.com/L2SProfiler/runtimehelp/html/T_Huagati_LinqToSQL_Profiler_Filters_MissingIndexFilter.htm"&gt;MissingIndexFilter&lt;/a&gt; and the &lt;a href="http://www.huagati.com/L2SProfiler/runtimehelp/html/T_Huagati_LinqToSQL_Profiler_Filters_MissingIndexAndPageReadsFilter.htm"&gt;MissingIndexAndPageReadsFilter&lt;/a&gt; . As the names suggest, these two new filters use the SQL Server optimizer's ability to detect and recommend indexes for queries when it is unable to find a suitable index. The SQL Server optimizer include that information in the generated execution plans as well as store it temporarily in distributed management views from where it can be extracted at runtime.&lt;br /&gt;&lt;br /&gt;The new filters enables profiling of Linq-to-SQL based applications based on this information; with these filters we can tell the Linq-to-SQL Profiler to log only queries where the optimizer detect missing indexes, optionally filtered by a minimum number of page reads to avoid logging queries that have a low I/O cost anyway, and to avoid extracting execution plans for low cost queries.&lt;br /&gt;&lt;br /&gt;The following is a quick walkthrough showing how to use the new filters together with the new visual cues added to the profiler's log viewer in version 1.15 to analyse the logs.&lt;br /&gt;&lt;br /&gt;First of all, I created a test database with a decent amount of records and both indexed and unindexed columns that can be used in joins and where clause criteria. The test database contains three identical tables with a guid primary key and two nvarchar(100)'s - one indexed and one not indexed. To have some data to play with the creation script also adds 999,999 records to all three of the tables:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_9F0FMyBvxXA/SnvFXErWmaI/AAAAAAAAAHc/K_8GJeSceXw/s1600-h/missingIndexTest+-+001+-+testDB.jpg"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 267px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5367100381125319074" border="0" alt="" src="http://4.bp.blogspot.com/_9F0FMyBvxXA/SnvFXErWmaI/AAAAAAAAAHc/K_8GJeSceXw/s400/missingIndexTest+-+001+-+testDB.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;...next, I created a new project in Visual Studio 2008 with a Linq-to-SQL datacontext pointing to the new test database. Of course, I used my other Linq-to-SQL tool, &lt;a href="http://www.huagati.com/dbmltools/"&gt;Huagati DBML/EDMX Tools&lt;/a&gt;, to fix up the class and member names and to add inline xml documentation to the generated classes.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_9F0FMyBvxXA/SnvFXPIndqI/AAAAAAAAAHk/Tqil7fMACaY/s1600-h/missingIndexTest+-+002+-+datacontext.jpg"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 305px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5367100383932413602" border="0" alt="" src="http://1.bp.blogspot.com/_9F0FMyBvxXA/SnvFXPIndqI/AAAAAAAAAHk/Tqil7fMACaY/s400/missingIndexTest+-+002+-+datacontext.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;...after creating the datacontext, I added a new partial class containing a new constructor overload and new dispose method to the datacontext class. The new constructor contains the logic to enable profiling and to instruct the profiler to use the &lt;a href="http://www.huagati.com/L2SProfiler/runtimehelp/html/T_Huagati_LinqToSQL_Profiler_Filters_MissingIndexAndPageReadsFilter.htm"&gt;MissingIndexAndPageReadsFilter&lt;/a&gt; to only log queries that do more than 10k page reads, and where the SQL Server execution plan contain alerts for missing indexes.&lt;br /&gt;&lt;br /&gt;In a test app like this one the runtime filter is not really necessary, but in a real world app containing hundreds of queries using runtime filters is a great way to ensure that only real 'offender' queries are logged.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_9F0FMyBvxXA/SnvFLI6pr4I/AAAAAAAAAHU/EjrGbELOA4M/s1600-h/missingIndexTest+-+002b+-+datacontext+partial.jpg"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 305px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5367100176104796034" border="0" alt="" src="http://3.bp.blogspot.com/_9F0FMyBvxXA/SnvFLI6pr4I/AAAAAAAAAHU/EjrGbELOA4M/s400/missingIndexTest+-+002b+-+datacontext+partial.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;...so with a test database set up, a Linq to SQL datacontext pointing to it, profiler logging enabled, time to write a test query. For this demonstration I do a simple three-table join with the first join done on indexed columns, the second join on columns with no covering indexes, and the where clause criteria using a non indexed column. This should result in two missing index alerts from the optimizer as well as a decent amount of page reads since we will do full table scans on two of the 999,999 record tables.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_9F0FMyBvxXA/SnvFK6T7z-I/AAAAAAAAAHM/AEiPDFuSOHA/s1600-h/missingIndexTest+-+003+-+query.jpg"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 305px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5367100172184309730" border="0" alt="" src="http://4.bp.blogspot.com/_9F0FMyBvxXA/SnvFK6T7z-I/AAAAAAAAAHM/AEiPDFuSOHA/s400/missingIndexTest+-+003+-+query.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;...and just to highlight a feature in &lt;a href="http://www.huagati.com/dbmltools/"&gt;Huagati DBML/EDMX Tools&lt;/a&gt; that could help catching this kind of mistakes already when writing the query in the code editor - the 'update documentation' feature in the add-in added information about what indexes exist (and don't exist) in the XML documentation for the entity classes and their members. Hovering over a member will show what index(es) (if any) exist on the underlying column in the database:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_9F0FMyBvxXA/SnvFK8j31zI/AAAAAAAAAHE/hc9E0_Vrs28/s1600-h/missingIndexTest+-+004+-+index+tooltip.jpg"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 133px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5367100172788029234" border="0" alt="" src="http://4.bp.blogspot.com/_9F0FMyBvxXA/SnvFK8j31zI/AAAAAAAAAHE/hc9E0_Vrs28/s400/missingIndexTest+-+004+-+index+tooltip.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Next, I ran the test app once to generate some log data. After that I opened up the log directory I was interested in (I could go for the root log directory if I want to see everything stored in my logs, or I can - as in the screenshot below - use the directory structure generated by the logging component to filter down by date and time):&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_9F0FMyBvxXA/SnvFKshOAGI/AAAAAAAAAG8/2RtlBGNf808/s1600-h/missingIndexTest+-+005+-+open+log.jpg"&gt;&lt;img style="WIDTH: 309px; HEIGHT: 400px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5367100168481931362" border="0" alt="" src="http://2.bp.blogspot.com/_9F0FMyBvxXA/SnvFKshOAGI/AAAAAAAAAG8/2RtlBGNf808/s400/missingIndexTest+-+005+-+open+log.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Since I ran the test app only once, there is only one entry in the log folder I opened. Now, look in the lower left corner of this screenshot of the log viewer:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_9F0FMyBvxXA/SnvFKVDftzI/AAAAAAAAAG0/F9nWavf0f-U/s1600-h/missingIndexTest+-+006+-+logwindow.jpg"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 291px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5367100162183247666" border="0" alt="" src="http://2.bp.blogspot.com/_9F0FMyBvxXA/SnvFKVDftzI/AAAAAAAAAG0/F9nWavf0f-U/s400/missingIndexTest+-+006+-+logwindow.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The new part is the two little alerts in the lower left corner. One of them says that this log entry contain missing index alerts, and the other one says that there was a table scan on more than 10k rows. Had the scan been on between 1k and 10k rows that alert would have been yellow rather than red. Hovering over the table scan alert shows which table(s) was scanned, as well as estimated and actual number of rows that were scanned:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_9F0FMyBvxXA/SnvDg5eFNfI/AAAAAAAAAGM/Z_oQZzt8egA/s1600-h/missingIndexTest+-+006b+-+logwindow+tablescan+alert.jpg"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 304px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5367098350892299762" border="0" alt="" src="http://2.bp.blogspot.com/_9F0FMyBvxXA/SnvDg5eFNfI/AAAAAAAAAGM/Z_oQZzt8egA/s400/missingIndexTest+-+006b+-+logwindow+tablescan+alert.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;...and hovering over the Missing Index(es) alert brings up a floating window showing the indexes that the SQL Server optimizer would like to see in the database to execute this query in the most efficient way.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_9F0FMyBvxXA/SnvDhOl_2cI/AAAAAAAAAGU/4bUvhsBMXuk/s1600-h/missingIndexTest+-+006c+-+logwindow+missingindex+alert.jpg"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 161px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5367098356562647490" border="0" alt="" src="http://1.bp.blogspot.com/_9F0FMyBvxXA/SnvDhOl_2cI/AAAAAAAAAGU/4bUvhsBMXuk/s400/missingIndexTest+-+006c+-+logwindow+missingindex+alert.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now, it is worth mentioning that these are recommendations (or rather a wish list) generated by the SQL Server optimizer. That doesn't mean that it is always a good idea to generate the indexes it would need. In real life there is of course a balance; over indexing can be as bad as not having enough indexes since it increases I/O when writing as well as (if there are too many indexes covering the same column(s)) increasing the number of possibilities that the SQL Server optimizer must consider when compiling an execution plan. In other words, review the index recommendations carefully, edit as necessary, and create indexes thereafter. Blindly creating everything the optimizer asks for is a sure way to get into trouble. &lt;span style="font-size:85%;"&gt;&lt;em&gt;(Did I mention the database I recently reviewed for a customer where they had a large table with 70+ columns and 56 indexes? Don't do that....)&lt;/em&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Despite my caution above, I will go ahead and just follow the optimizer generated recommendations blindly, just for the purpose of demonstration. So I clicked the "copy" link next to the "Missing index(es)" alert in the profiler log viewer to get the new indexes onto the clipboard, jumped right over to SSMS and created the indexes as they were:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_9F0FMyBvxXA/SnvDhGSTrrI/AAAAAAAAAGc/_iBMMMg2tgc/s1600-h/missingIndexTest+-+007+-+create+missing+indexes.jpg"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 267px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5367098354332577458" border="0" alt="" src="http://1.bp.blogspot.com/_9F0FMyBvxXA/SnvDhGSTrrI/AAAAAAAAAGc/_iBMMMg2tgc/s400/missingIndexTest+-+007+-+create+missing+indexes.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Next, suspecting that the new indexes will result in the profiler not logging anything with the previous runtime filter, I removed the MissingIndexAndPageReadsFilter filter from the test app and replaced it with a null. This means 'no filtering at all, please' and will ensure that the profiler logging component writes all queries to the log:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_9F0FMyBvxXA/SnvDhRA1gII/AAAAAAAAAGk/aCaLa6XzOv8/s1600-h/missingIndexTest+-+008+-+datacontext+no+filter.jpg"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 305px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5367098357212086402" border="0" alt="" src="http://4.bp.blogspot.com/_9F0FMyBvxXA/SnvDhRA1gII/AAAAAAAAAGk/aCaLa6XzOv8/s400/missingIndexTest+-+008+-+datacontext+no+filter.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;...and after re-running the test app, I refreshed the profiler's log viewer window to see the new entry. The new entry shows significantly less reads &lt;span style="font-size:85%;"&gt;(although there's still room to optimize this query additionally, but that's another story for another day)&lt;/span&gt;, and both the table scan and missing index alerts are gone from the log entry details at the bottom of the screen:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_9F0FMyBvxXA/SnvDhlYXPyI/AAAAAAAAAGs/F9uPxKHh7kk/s1600-h/missingIndexTest+-+009+-+logwindow+after+indexes.jpg"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 291px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5367098362679476002" border="0" alt="" src="http://3.bp.blogspot.com/_9F0FMyBvxXA/SnvDhlYXPyI/AAAAAAAAAGs/F9uPxKHh7kk/s400/missingIndexTest+-+009+-+logwindow+after+indexes.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So, that was a quick walkthrough of what the new runtime filters can do. Of course, there are plenty of other &lt;a href="http://www.huagati.com/L2SProfiler/runtimehelp/html/N_Huagati_LinqToSQL_Profiler_Filters.htm"&gt;runtime filters&lt;/a&gt; and other goodies in the profiler - some covered in a previous blog entry ( &lt;a href="http://huagati.blogspot.com/2009/06/profiling-linq-to-sql-applications.html"&gt;Profiling Linq-to-SQL applications&lt;/a&gt; ). Also not mentioned above is the &lt;a href="http://www.huagati.com/L2SProfiler/runtimehelp/html/T_Huagati_LinqToSQL_Profiler_Filters_PrePlanPostPlanFilter.htm"&gt;PrePlanPostPlanFilter&lt;/a&gt; that allows two filters to be combined together; one not relying on execution plans and one relying on execution plans. This is useful from a profiling performance perspective; the profiler will not extract the execution plans for a query unless it passes the first (non-execution-plan-dependant) filter and will then apply the execution plan dependant filter as the last step to determine what queries should be logged or not logged.&lt;br /&gt;&lt;br /&gt;If you want to try out any of the above, or test the profiler with your own Linq-to-SQL based apps, go ahead and download it and get a trial license (free for 45 days) over at &lt;a href="http://www.huagati.com/L2SProfiler/"&gt;http://www.huagati.com/L2SProfiler/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-8660907914213464133?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/8660907914213464133/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2009/08/walkthrough-of-newest-filters-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/8660907914213464133'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/8660907914213464133'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2009/08/walkthrough-of-newest-filters-and.html' title='A walkthrough of the newest filters and visual cues in the Huagati Linq-to-SQL Profiler'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_9F0FMyBvxXA/SnvFXErWmaI/AAAAAAAAAHc/K_8GJeSceXw/s72-c/missingIndexTest+-+001+-+testDB.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-2157233178328294311</id><published>2009-07-30T13:33:00.005+07:00</published><updated>2009-07-30T14:02:29.507+07:00</updated><title type='text'>Model first in Entity Framework v1.0</title><content type='html'>Every now and then people ask in forums etc how to do model first with Entity Framework version 1 &lt;span style="font-size:85%;"&gt;(.net 3.5 SP1 / Visual Studio 2008 SP1)&lt;/span&gt;. In other words, how to create a model using the Entity Framework designer in Visual Studio and then generate a database from that model. The simple answer is that it is not supported out of the box. However, since one of my tools has supported that for quite some time I figured it was about time to repost a tutorial on how to do model first with EFv1 &lt;span style="font-size:85%;"&gt;(for those who don't want to wait until Visual Studio 2010 where it will be supported out-of-the-box).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So... here are the steps. Requires &lt;a href="http://www.microsoft.com/visualstudio/en-us/default.mspx"&gt;Visual Studio 2008&lt;/a&gt; &lt;span style="font-size:85%;"&gt;(not express edition, but any higher SKU will work)&lt;/span&gt;, and &lt;a href="http://www.huagati.com/dbmltools/"&gt;Huagati DBML/EDMX Tools&lt;/a&gt; to be installed. &lt;span style="font-size:85%;"&gt;(Huagati DBML/EDMX Tools is free to use for the first 45 days, if you want to continue using it after that please buy a license to support continued development).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Step 1: &lt;/strong&gt;Create a new EDMX file (Entity Framework model file).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_9F0FMyBvxXA/SnFAaE2eBuI/AAAAAAAAAFE/QhcSl4bfFd8/s1600-h/modelFirstSampleEF001.png"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 305px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5364139447897949922" border="0" alt="" src="http://2.bp.blogspot.com/_9F0FMyBvxXA/SnFAaE2eBuI/AAAAAAAAAFE/QhcSl4bfFd8/s400/modelFirstSampleEF001.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Choose "empty model" if you start from scratch, or "generate from database" if you have an existing database that you want to use as a base.&lt;/p&gt;&lt;p&gt;&lt;a href="http://4.bp.blogspot.com/_9F0FMyBvxXA/SnFAaRTLcxI/AAAAAAAAAFM/89O40sWvvfI/s1600-h/modelFirstSampleEF002.png"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 356px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5364139451239592722" border="0" alt="" src="http://4.bp.blogspot.com/_9F0FMyBvxXA/SnFAaRTLcxI/AAAAAAAAAFM/89O40sWvvfI/s400/modelFirstSampleEF002.png" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Add entities, entity members, associations etc. In other words, create a model. &lt;/p&gt;&lt;p&gt;&lt;a href="http://1.bp.blogspot.com/_9F0FMyBvxXA/SnFAapyjf_I/AAAAAAAAAFU/vQBBw2avG7Y/s1600-h/modelFirstSampleEF003.png"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 305px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5364139457813643250" border="0" alt="" src="http://1.bp.blogspot.com/_9F0FMyBvxXA/SnFAapyjf_I/AAAAAAAAAFU/vQBBw2avG7Y/s400/modelFirstSampleEF003.png" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; Review the model...&lt;/p&gt;&lt;a href="http://4.bp.blogspot.com/_9F0FMyBvxXA/SnFAa161ZgI/AAAAAAAAAFc/UNHGjzDmCBY/s1600-h/modelFirstSampleEF004.png"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 305px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5364139461069596162" border="0" alt="" src="http://4.bp.blogspot.com/_9F0FMyBvxXA/SnFAa161ZgI/AAAAAAAAAFc/UNHGjzDmCBY/s400/modelFirstSampleEF004.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Step 5:&lt;/strong&gt; Generate SSDL (Entity Framework's storage layer description) from the CSDL generated by the designer:&lt;/p&gt;&lt;a href="http://4.bp.blogspot.com/_9F0FMyBvxXA/SnFAbHY8NsI/AAAAAAAAAFk/sf8cwZOFkjA/s1600-h/modelFirstSampleEF005.png"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 305px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5364139465759274690" border="0" alt="" src="http://4.bp.blogspot.com/_9F0FMyBvxXA/SnFAbHY8NsI/AAAAAAAAAFk/sf8cwZOFkjA/s400/modelFirstSampleEF005.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_9F0FMyBvxXA/SnFCFqJzZPI/AAAAAAAAAFs/-8KqSnCXUIw/s1600-h/modelFirstSampleEF006.png"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 300px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5364141296157156594" border="0" alt="" src="http://1.bp.blogspot.com/_9F0FMyBvxXA/SnFCFqJzZPI/AAAAAAAAAFs/-8KqSnCXUIw/s400/modelFirstSampleEF006.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Step 6:&lt;/strong&gt; After generating SSDL, the VS2008 output window shows a summary of the SSDL generation process (what was generated etc). Just as a FYI thing...&lt;/p&gt;&lt;a href="http://2.bp.blogspot.com/_9F0FMyBvxXA/SnFCFwUX2AI/AAAAAAAAAF0/82S44Wo8G_8/s1600-h/modelFirstSampleEF007.png"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 305px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5364141297812101122" border="0" alt="" src="http://2.bp.blogspot.com/_9F0FMyBvxXA/SnFCFwUX2AI/AAAAAAAAAF0/82S44Wo8G_8/s400/modelFirstSampleEF007.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Step 7:&lt;/strong&gt; Generate SQL-DDL for the database.&lt;/p&gt;&lt;a href="http://2.bp.blogspot.com/_9F0FMyBvxXA/SnFCGOn2W2I/AAAAAAAAAF8/iwTOD5KJQCY/s1600-h/modelFirstSampleEF008.png"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 305px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5364141305946856290" border="0" alt="" src="http://2.bp.blogspot.com/_9F0FMyBvxXA/SnFCGOn2W2I/AAAAAAAAAF8/iwTOD5KJQCY/s400/modelFirstSampleEF008.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;strong&gt;Step 8:&lt;/strong&gt; Review the SQL-DDL that was generated, change data types as necessary, add precision/length where needed etc.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_9F0FMyBvxXA/SnFCGWVr1XI/AAAAAAAAAGE/L-1zfb_xkBI/s1600-h/modelFirstSampleEF009.png"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 305px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5364141308018152818" border="0" alt="" src="http://4.bp.blogspot.com/_9F0FMyBvxXA/SnFCGWVr1XI/AAAAAAAAAGE/L-1zfb_xkBI/s400/modelFirstSampleEF009.png" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-2157233178328294311?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/2157233178328294311/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2009/07/model-first-in-entity-framework-v10.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/2157233178328294311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/2157233178328294311'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2009/07/model-first-in-entity-framework-v10.html' title='Model first in Entity Framework v1.0'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_9F0FMyBvxXA/SnFAaE2eBuI/AAAAAAAAAFE/QhcSl4bfFd8/s72-c/modelFirstSampleEF001.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-6238161438627984233</id><published>2009-06-24T17:50:00.002+07:00</published><updated>2009-06-24T18:18:58.732+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='Linq to SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='Linq-to-SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><category scheme='http://www.blogger.com/atom/ns#' term='profiling'/><title type='text'>Profiling Linq-to-SQL applications</title><content type='html'>&lt;h4&gt;Profiling - why? &lt;/h4&gt;&lt;p&gt;When developing database driven applications - especially apps with many users and different usage patterns - database performance is key to application performance and the database is often the 'resource bottleneck' when it comes to scaling applications to cope with a larger number of users.&lt;/p&gt;&lt;p&gt;If a certain operation spends a bit more time, CPU, and other resources &lt;em&gt;client side&lt;/em&gt; it is often not as big of a matter scalability-wise as if it spends time or resources &lt;em&gt;database-side/server-side&lt;/em&gt;. As the number of users in a large system grow, the impact of query costs - and savings of reducing it - is often the single most important factor to look at to improve performance and scalability, and the cheapest way to improve scalability.&lt;/p&gt;&lt;p&gt;Additionally, a production environment will often differ from test/development in ways that can affect how queries behave:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Applications are often used different in a production environment than what developers and designers envisioned; users may refresh 'screen x' twice as often as was envisioned during design and development, or use search filters in search screen differently than anyone thought. &lt;/li&gt;&lt;li&gt;SQL Server will often execute queries differently on different systems; depending on data volumes, available resources, system load, system and db configuration, and many other factors. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Because of this, runtime profiling live production systems can sometimes reveal bottlenecks and/or room for improvements/optimization that would not show up during development/test/QA, or on dev/test systems. &lt;/p&gt;&lt;p&gt;&lt;strong&gt;Profiling tools &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;There are many great tools available for investigating database performance at runtime / in production environments. The Microsoft tool stack offer some nice stuff for Linq-to-SQL and SQL Server based apps: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;SQL Server Profiler&lt;/em&gt; is a really great tool that comes with the management tools for SQL Server (Standard edition and up, unfortunately it not available in Express edition). &lt;/li&gt;&lt;li&gt;&lt;em&gt;Linq-to-SQL&lt;/em&gt; has a built in logging feature that allows executed queries to be written to log files by simply attaching a textwriter to the datacontext object. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;To take this a step further, I have decided to throw a new tool onto the stack for L2S developers: a brand new profiler specifically targeting Linq-to-SQL applications. &lt;/p&gt;&lt;p&gt;But before we take a look at the L2S Profiler, a brief look at what comes out-of-the-box with SQL Server and Linq-to-SQL, and then what the L2S Profiler brings to the table compared to the existing tool stack. &lt;/p&gt;&lt;p&gt;&lt;strong&gt;SQL Server Profiler &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Although SQL Server Profiler goes a long way when it comes to pinpointing what queries are causing the most stress db-side, it provides information from the SQL Server side of things only. It is built as a generic tool for all kinds of SQL Server profiling - not only queries but targeting other kinds of database activity as well. But a missing part is the application side of it: &lt;em&gt;where&lt;/em&gt; did that query come from, &lt;em&gt;what&lt;/em&gt; [user actions/calls] led to it being executed etc. In a large application with many developers involved this can make it time consuming to determine another important aspect &lt;em&gt;who's&lt;/em&gt; code is responsible for hitting the database too frequently, or with too heavy queries, etc. &lt;/p&gt;&lt;p&gt;Add to that that SQL Server Profiler is made for DBAs, sys-admins, developers, and must be manually set up in a production environment. It can't be controlled from within applications, and it requires the person using it to know what they're looking for. It requires access to and privileges on the database server which is not always available in hosted environments, or in locked-down customer environments. It won't record execution plans so if you're reviewing a profiler log from a customer's system on your own system there is no way of determining what execution plan SQL Server used when it was executed.&lt;/p&gt;&lt;p&gt;Don't get me wrong: SQL Server profiler is an invaluable tool that I use on almost a daily basis, but there are some things it won't do that I would want it to.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Linq-to-SQL's DataContext.Log &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;So what about the built-in logging in Linq-to-SQL? It is a great feature as it stands, with a few lines of code you can get all SQL statements and queries generated by Linq-to-SQL written to a log file. Unfortunately you will then need to sort through them and manually determine which ones are a cause for concern and which ones are not. Time consuming to say the least as soon as query volumes creep up, and finding what queries can/need to be optimized quickly becomes a forest vs trees situation. Great for debugging locally, but beyond that at least I need more data and more filtering options.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Getting more into details &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;What if we are just interested in the where/what/who aspects of say... &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Queries that hit a specific table? &lt;/li&gt;&lt;li&gt;Queries that do more than &lt;strong&gt;n&lt;/strong&gt; I/O operations / page reads? &lt;/li&gt;&lt;li&gt;Queries that take longer than &lt;strong&gt;n&lt;/strong&gt; milliseconds to execute? &lt;/li&gt;&lt;li&gt;Queries that generate specific SQL Server warning messages? &lt;/li&gt;&lt;li&gt;Queries that result in scans? &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Finding those queries by hand in a large text file isn't going to be easy. Spotting them in SQL Server Profiler is easier provided that all the requirements for using it in the first place are satisfied. On the other hand, SQL Server Profiler won't give us the where/what/who; &lt;em&gt;where&lt;/em&gt; in the application it came from, &lt;em&gt;what&lt;/em&gt; caused it to run, or &lt;em&gt;who&lt;/em&gt;'se code generated it. &lt;/p&gt;&lt;p&gt;Add to that that we may want to control the profiling/logging from &lt;em&gt;within&lt;/em&gt; the application by for example app settings. If we want to profile just a specific part of an application in a runtime environment, and filter out only queries that are costly then the combination of SQL Server Profiler, SQL Server Management Studio and the out-of-the-box logging capabilities of Linq-to-SQL can add quite a bit of manual work to map the logs together. &lt;/p&gt;&lt;p&gt;&lt;strong&gt;Introducting the Huagati Linq-to-SQL Profiler &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;So, to bring the .net application side together with the database performance side of things, I put together the Linq-to-SQL Profiler. It consists of two main components: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;A runtime component that is referenced from within an application and that can be distributed with your applications. It hooks into a combination of the Linq-to-SQL built in logging, the underlying database connections, and SQL Server's own features for retrieving I/O information, timings, execution plans etc, and combines that information into log files. It also has some advanced (and customizable) filtering options so you can instruct it to log only queries that fulfill certain criteria. &lt;/li&gt;&lt;li&gt;A log viewer that read the log files generated by the runtime component, provides additional filtering, sorting (which is not available in SQL Server Profiler), and shows not only what query was executed by also the managed call stack that caused to to run, SQL Server I/O and timings etc. If execution plan logging was enabled in the runtime component it also provides quick links to bring up the execution plan as it stood on the machine where the query was executed, from when it was executed. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;The runtime component &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;The runtime component is a small DLL that you add as a reference in your Linq-to-SQL application. It won't do anything just by being referenced, but it adds some new capabilities to the Linq-to-SQL DataContext. It can be distributed freely together with your app, provided that you have a license for the profiler. &lt;/p&gt;&lt;p&gt;Using it is very simple; it has two methods (with a couple of overloads) that can be used to instruct it to start profiler logging (&lt;a href="http://www.huagati.com/L2SProfiler/runtimehelp/html/Overload_Huagati_LinqToSQL_Profiler_ProfilingExtensions_BeginProfiling.htm" target="_blank"&gt;datacontext.BeginProfiling&lt;/a&gt;), and to end profiler logging (&lt;a href="http://www.huagati.com/L2SProfiler/runtimehelp/html/Overload_Huagati_LinqToSQL_Profiler_ProfilingExtensions_EndProfiling.htm" target="_blank"&gt;datacontext.EndProfiling&lt;/a&gt;). Depending on your usage scenario you can either call those methods inline from your app code or you can extend the partial DataContext class generated by the Linq-to-SQL designer to call the profiler logging methods whenever a datacontext is created/used. &lt;/p&gt;&lt;p&gt;The following code samples shows a couple of usage scenarios which can be used to use for example app settings to determine if logging should be enabled or not, and what logging options to use. &lt;/p&gt;&lt;p&gt; &lt;a href="http://lh4.ggpht.com/_9F0FMyBvxXA/SkIEgUZ8PDI/AAAAAAAAACw/uEGTG4Z6loM/s1600-h/dcProfilingSampleCS%5B6%5D.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="Example 1: a profiler enabled datacontext (C#)" border="0" alt="Example 1: a profiler enabled datacontext (C#)" src="http://lh3.ggpht.com/_9F0FMyBvxXA/SkIEhn6KnuI/AAAAAAAAAC4/hW1ALpJdMXU/dcProfilingSampleCS_thumb%5B4%5D.png?imgmax=800" width="734" height="549" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;Example 1: A profiler enabled datacontext partial class in C#&lt;/span&gt;&lt;/p&gt;&lt;p&gt; &lt;a href="http://lh3.ggpht.com/_9F0FMyBvxXA/SkIEiheicmI/AAAAAAAAAC8/CGWTpoxz8Z4/s1600-h/inlineProfilingSampleCS%5B4%5D.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="inlineProfilingSampleCS" border="0" alt="inlineProfilingSampleCS" src="http://lh3.ggpht.com/_9F0FMyBvxXA/SkIEjgx-hjI/AAAAAAAAADA/7hQtayvZsuk/inlineProfilingSampleCS_thumb%5B2%5D.png?imgmax=800" width="569" height="276" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;Example 2: Inline profiling with C# as an alternative to profiling-enabled DCs&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:78%;"&gt;&lt;/span&gt; &lt;/p&gt;&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_9F0FMyBvxXA/SkIElJc16nI/AAAAAAAAADM/Z6j_yhWgeIg/s1600-h/dcProfilingSampleVB%5B3%5D.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="dcProfilingSampleVB" border="0" alt="dcProfilingSampleVB" src="http://lh5.ggpht.com/_9F0FMyBvxXA/SkIEme6lWHI/AAAAAAAAADY/byHxHr9P3ZY/dcProfilingSampleVB_thumb%5B1%5D.png?imgmax=800" width="627" height="529" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;Example 3: A profiling enabled datacontext in VB.NET&lt;/span&gt;&lt;/p&gt;&lt;p&gt; &lt;a href="http://lh6.ggpht.com/_9F0FMyBvxXA/SkIEniHB5-I/AAAAAAAAADc/7P5F6vArUEE/s1600-h/inlineProfilingSampleVB%5B3%5D.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="inlineProfilingSampleVB" border="0" alt="inlineProfilingSampleVB" src="http://lh4.ggpht.com/_9F0FMyBvxXA/SkIEowFKBRI/AAAAAAAAADg/VvjzET6us88/inlineProfilingSampleVB_thumb%5B1%5D.png?imgmax=800" width="564" height="597" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;Example 4: Inline profiling in VB.NET as an alternative to profiling-enabled DataContexts &lt;/span&gt;&lt;/p&gt;&lt;p&gt;If you want to read more about the profiler runtime component API, check out the online help over at &lt;a href="http://www.huagati.com/L2SProfiler/runtimehelp"&gt;http://www.huagati.com/L2SProfiler/runtimehelp&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;The profiler viewer &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;The profiler viewer is a windows application that read the log files generated by the Linq-to-SQL Profiler runtime component. It has filter options and sorting to make it easier to find the 'worst offenders' or log entries that match more specific criteria than was used during the runtime logging. &lt;/p&gt;&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_9F0FMyBvxXA/SkIErM2hTWI/AAAAAAAAADk/riQSj3HGUX4/s1600-h/ProfilerViewer%5B5%5D.png" target="_blank"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="ProfilerViewer" border="0" alt="ProfilerViewer" src="http://lh6.ggpht.com/_9F0FMyBvxXA/SkIEuS1ihrI/AAAAAAAAADo/I-jQ5cuFyFA/ProfilerViewer_thumb%5B3%5D.png?imgmax=800" width="644" height="396" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;The profiler's screen is divided into two parts; the upper part shows all queries from the log (minus those filtered out by any filters set in the viewer) and the lower part shows the details; the query itself, the managed call stack, I/O and timings etc. The I/O and timing data is accompanied by visual indicators showing the relative impact of a query. The thresholds used by the visual indicators can be configured in the application settings. &lt;/p&gt;&lt;p&gt; &lt;a href="http://lh4.ggpht.com/_9F0FMyBvxXA/SkIEvvfjCzI/AAAAAAAAADs/5a8Y1M3de70/s1600-h/ProfilerViewer_indicators%5B3%5D.jpg"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="ProfilerViewer_indicators" border="0" alt="ProfilerViewer_indicators" src="http://lh6.ggpht.com/_9F0FMyBvxXA/SkIEwvWR0hI/AAAAAAAAADw/SUQVL8fxOzw/ProfilerViewer_indicators_thumb%5B1%5D.jpg?imgmax=800" width="255" height="274" /&gt;&lt;/a&gt; &lt;a href="http://lh3.ggpht.com/_9F0FMyBvxXA/SkIEx_H13UI/AAAAAAAAAD0/o9RO4CQA84I/s1600-h/ProfilerViewer_stackTrace%5B4%5D.jpg"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="ProfilerViewer_stackTrace" border="0" alt="ProfilerViewer_stackTrace" src="http://lh6.ggpht.com/_9F0FMyBvxXA/SkIEzNhTX0I/AAAAAAAAAEA/efxxoue18Ec/ProfilerViewer_stackTrace_thumb%5B2%5D.jpg?imgmax=800" width="554" height="145" /&gt;&lt;/a&gt;&lt;a href="http://lh6.ggpht.com/_9F0FMyBvxXA/SkIE0TrCqGI/AAAAAAAAAEE/yUJPMEhr5m4/s1600-h/ProfilerViewer_query%5B3%5D.jpg"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="ProfilerViewer_query" border="0" alt="ProfilerViewer_query" src="http://lh4.ggpht.com/_9F0FMyBvxXA/SkIE1q-fK8I/AAAAAAAAAEI/khi2EuFQhYE/ProfilerViewer_query_thumb%5B1%5D.jpg?imgmax=800" width="554" height="203" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;The lower part of the screen can also be customized; the log files contain a lot more information than what is shown in the default view and the rendering of the lower part is done using XSLT style sheets that can be switched in the application settings dialog. This allows developers to create their own detail views focusing on the specific information they're interested in. &lt;/p&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_9F0FMyBvxXA/SkIE2vyV_zI/AAAAAAAAAEU/hfMEfsqJx-M/s1600-h/profilerSettingsDialog%5B4%5D.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="profilerSettingsDialog" border="0" alt="profilerSettingsDialog" src="http://lh6.ggpht.com/_9F0FMyBvxXA/SkIE4R02ulI/AAAAAAAAAEY/8mEC_j--dwQ/profilerSettingsDialog_thumb%5B2%5D.png?imgmax=800" width="644" height="327" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;The profiler settings dialog &lt;/span&gt;&lt;/p&gt;&lt;p&gt;Additional details such as the execution plan diagram, the source code involved, parameterized and 'sp_execute'-wrapped versions of the queries etc are available as hyperlinks in the detail view, but the same information can of course be visualized directly in a customized detail view template. &lt;/p&gt;&lt;p&gt;&lt;strong&gt;Taking it for a test spin &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;If you would like to take the profiler for a test spin, head over to the product page over at &lt;a href="http://www.huagati.com/L2SProfiler/"&gt;http://www.huagati.com/L2SProfiler/&lt;/a&gt; , where you can download it and get a free 45-day trial license. After the trial expires I hope you're happy with it and want to continue using it. If so, please support continued development by purchasing a license (or a pile of licenses for your team :) ). &lt;/p&gt;&lt;p&gt;If you have any questions or concerns about the profiler, feel free to send an email to support@huagati.com, ask a question in the support forum (&lt;a href="http://forum.huagati.com/forum4-huagati-linqtosql-profiler-support.aspx"&gt;http://forum.huagati.com/forum4-huagati-linqtosql-profiler-support.aspx&lt;/a&gt; ), or drop a comment here on my blog. &lt;/p&gt;&lt;p&gt;&lt;strong&gt;Future features &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;There are of course new features are planned for the profiler, these will be made available as they're completed: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;A centralized logging server that you can run to write logs to a database. It will have a web-based frontend very similar to the windows version of the profiler logger but is better suited for team environments where many people may want to access and work with the same logs. &lt;/li&gt;&lt;li&gt;More templates for the detail view in the profiler viewer &lt;/li&gt;&lt;li&gt;Additional filters; both runtime- and design time filters to help keep the log files focused on the interesting bits only. &lt;/li&gt;&lt;li&gt;Additional logging providers; if there is enough interest I may extend the runtime logging component to also support Entity Framework, plain ADO.NET, or other data access technologies such as 3rd party OR/Ms. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Fin. &lt;/strong&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-6238161438627984233?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/6238161438627984233/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2009/06/profiling-linq-to-sql-applications.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/6238161438627984233'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/6238161438627984233'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2009/06/profiling-linq-to-sql-applications.html' title='Profiling Linq-to-SQL applications'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_9F0FMyBvxXA/SkIEhn6KnuI/AAAAAAAAAC4/hW1ALpJdMXU/s72-c/dcProfilingSampleCS_thumb%5B4%5D.png?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4155628149386914837.post-7463566993033608204</id><published>2009-04-30T10:42:00.001+07:00</published><updated>2009-04-30T10:48:39.216+07:00</updated><title type='text'>New blog</title><content type='html'>Welcome to my new blog.&lt;br /&gt;&lt;br /&gt;I recently took my old blog offline, for a number of reasons:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It was becoming unstructured; lots of content that didn't fit the title of the blog etc.&lt;/li&gt;&lt;li&gt;It was a huge spam magnet (comment spam)&lt;/li&gt;&lt;li&gt;I didn't feel comfortable having the whole wordpress/php/mysql thing running on my server.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Some of the old content will probably be reposted here but I'll focus more on new content. Let me know if you miss something from the old blog and I'll look into migrating it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4155628149386914837-7463566993033608204?l=huagati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://huagati.blogspot.com/feeds/7463566993033608204/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://huagati.blogspot.com/2009/04/new-blog.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/7463566993033608204'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4155628149386914837/posts/default/7463566993033608204'/><link rel='alternate' type='text/html' href='http://huagati.blogspot.com/2009/04/new-blog.html' title='New blog'/><author><name>KristoferA</name><uri>http://www.blogger.com/profile/01779909152712388764</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_9F0FMyBvxXA/TPdX0lYL6vI/AAAAAAAAAWI/IqkhXBp3QVA/S220/huagati256x256.png'/></author><thr:total>5</thr:total></entry></feed>
