<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Frans Bouma's blog</title><link>http://weblogs.asp.net/fbouma/default.aspx</link><description>Generator.CreateCoolTool();</description><dc:language>en</dc:language><generator>CommunityServer 2007 SP1 (Build: 20510.895)</generator><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/FransBouma" /><feedburner:info uri="fransbouma" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><creativeCommons:license>http://creativecommons.org/licenses/by-sa/3.0/</creativeCommons:license><image><link>http://creativecommons.org/licenses/by-sa/3.0/</link><url>http://creativecommons.org/images/public/somerights20.gif</url><title>Some Rights Reserved</title></image><item><title>WCF Data Services and the IExpandProvider</title><link>http://feedproxy.google.com/~r/FransBouma/~3/mGkTz2Znaxo/wcf-data-services-and-the-iexpandprovider.aspx</link><pubDate>Sun, 02 Jun 2013 10:22:58 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:10371764</guid><dc:creator>FransBouma</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=10371764</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2013/06/02/wcf-data-services-and-the-iexpandprovider.aspx#comments</comments><description>&lt;p&gt;Yesterday, a &lt;a href="http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=21958" target="_blank"&gt;customer ran into a weird issue&lt;/a&gt; with our OData/WCF Data Services support in &lt;a href="http://www.llblgen.com/" target="_blank"&gt;LLBLGen Pro&lt;/a&gt;: when an $expand directive was given which was more than one level deep, the service would only return the first level. $expand is OData's directive to &lt;em&gt;eager load &lt;/em&gt;additional data into the data requested. So if I for example want to read the data of customer 'ALFKI' from the Northwind database and also that customer's orders, I'd issue this OData query:&lt;/p&gt;  &lt;p&gt;&lt;code&gt;http://localhost:3931/NorthwindService.svc/Customer('ALFKI')?$expand=Orders&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;This will return the data of ALFKI and the data of all Orders of that customer. This all worked fine. However, when I also would specify to load all OrderDetail entities for each order (so i.o.w.: a second level expand), it would not return these OrderDetail rows, but simply return the same data as the query above:&lt;/p&gt;  &lt;p&gt;&lt;code&gt;http://localhost:3931/NorthwindService.svc/Customer('ALFKI')?$expand=Orders/OrderDetails&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;This could be caused by a lot of things of course, but as it has worked in the past and it didn't work today, what did change? First I verified with &lt;a href="http://www.ormprofiler.com" target="_blank"&gt;ORM Profiler&lt;/a&gt; that the engine indeed executed three queries: one for Customer with a filter on CustomerID, one on Orders with the same predicate and one on OrderDetails with a filter on all OrderIds returned by the Orders query, a typical three node &lt;a href="http://www.llblgen.com/documentation/4.0/LLBLGen%20Pro%20RTF/hh_goto.htm#Using%20the%20generated%20code/Adapter/gencode_prefetchpaths_adapter.htm#preface" target="_blank"&gt;prefetch path&lt;/a&gt; query. Debugging the engine revealed that the expand directives were properly converted to a prefetch path, and the data was properly merged into a single graph of Customer – Orders – OrderDetails. &lt;/p&gt;  &lt;p&gt;This frustrated me to no end, because my code did what it was told to do, it handed over the proper entity instance graph to the calling service code and apparently something went wrong there, but what and why was a mystery. Not only that, but who to ask what's wrong and if something was wrong on Microsoft's end, would they ever fix it? Writing the WCF Data Services support code for our O/R mapper framework was a frustrating experience as there's little documentation available how to add WCF Data Services support for your ORM/Data access technology (as everything about WCF Data Services is tightly designed around Entity Framework) so you have to piece together what you have to do from blog-posts, simple examples and decompiling (sorry) the Entity Framework WCF Data Services provider. &lt;/p&gt;  &lt;p&gt;First rule of fixing issues when writing code to support a Microsoft framework is to look whether you're the only one having this problem. I was. Well, I did find &lt;a href="http://stackoverflow.com/questions/14183134/replacement-for-iexpandprovider" target="_blank"&gt;a question on stackoverflow&lt;/a&gt; which asked what to do about the fact that IExpandProvider interface was deprecated. This refreshed my memory on it a bit. IExpandProvider is the interface which is to be implemented by the class which &lt;em&gt;handles&lt;/em&gt; $expand fragments. That is, it &lt;em&gt;was&lt;/em&gt;. Microsoft deprecated this interface some time ago but if your WCF Data Services service implemented the interface, it would still work as if nothing happened. For LLBLGen Pro v4 we moved our WCF Data Services code to the nuget version of the WCF Data Services code instead of the one shipped with .NET 4/4.5. Everything worked properly, so we signed it off. But we didn't have a test with two-level expands, so we missed an important aspect: it apparently seems the case the v5.x version of WCF Data Services doesn't return multiple levels of data fetched with $expand, &lt;em&gt;if&lt;/em&gt; the service provides an IExpandProvider implementing object. &lt;/p&gt;  &lt;p&gt;Reading the reply on the stackoverflow question by Vitek Karas, one of the WCF Data Services team members, I ended up on a blogpost which went on and on about expand wrappers, projection wrappers and what not, as an alternative to IExpandProvider implementing classes. It was unclear to me if I had to do that all myself or not: this is typical for what I had to wade through when writing the original WCF Data Services support code: there's no real documentation for this. As it looked rather daunting, and I have the feeling the guy who posted the question on stackoverflow thought the same, I had enough: I just want to provide top-quality code to my customers, but this endless stream of frustration made it impossible for me to do so. &lt;/p&gt;  &lt;p&gt;I can understand why Microsoft has less eye for us, 3rd party ORM developers: we're a small group, we compete with their ORM framework which is there to keep people on .NET/MS platforms, Microsoft is still a product-oriented company and so other things might have higher priority. That doesn't make it less frustrating though. &lt;/p&gt;  &lt;p&gt;After a good night sleep I woke up this morning with a daft thought in my mind: what if I simply told the service there was no IExpandProvider implemented? What would the service do? So I changed my WCF Data Services support code to simply return null if it was asked to return an IExpandProvider implementation and re-ran the tests. They worked! All levels of data were returned, and the queries were still efficiently done. But how? After all, there was no prefetch path handler code active anymore, and the prefetch path API is not the same as Entity Framework's (ours can do filters on included data, sort, exclude fields etc.).&lt;/p&gt;  &lt;p&gt;If there's no IExpandProvider, the WCF Data Services creates a custom projection with the expand fragments as nested queries. I &lt;a href="http://weblogs.asp.net/fbouma/archive/2008/03/07/developing-linq-to-llblgen-pro-part-14.aspx" target="_blank"&gt;described them here more in detail&lt;/a&gt;. Our Linq provider recognizes these nested queries and performs a similar procedure as if it would do with prefetch paths: each nested query is executed as a separate query and the results are merged using hash maps in-memory with parent nodes and nested queries are filtered based on the data fetched in parent nodes. This means the engine will still run three queries on the Customer – Orders – OrderDetails expand path, though it will use the nested query pipeline in the linq provider (which can deal with nested custom projections as well as nested entity sets). &lt;/p&gt;  &lt;p&gt;The fix was simple for my code: comment out some lines and everything was fine. But as I commented on Vitek's stackoverflow reply: what if the ORM has a proper eager-loading pipeline? It now has to rely on nested queries, something which isn't done properly in e.g. Linq to Sql (they're loaded in a SELECT N+1 fashion), unless a lot of work is done to make this load properly. You can't simply mark a working system 'obsolete', and expect frameworks supporting your service to say 'ok, no problem, we'll invest again some time and write some more code'. &lt;/p&gt;  &lt;p&gt;There are two scenario's for fetching additional data: fetch additional &lt;em&gt;entities&lt;/em&gt; with the entity loaded, or fetch a &lt;em&gt;custom projection&lt;/em&gt; of a set of nested sets, because if you fetch an entity E, where in E do you store the custom projection of some related data? Why not keep IExpandProvider around for the scenario where you fetch entities and related entities, the normal &lt;em&gt;eager load&lt;/em&gt; scenario? If one needs $expand to fetch a custom projection with nested sets, why not use the mechanism that's available now to replace IExpandProvider's logic? Just to support custom selects on entities to exclude fields for Entity Framework? Isn't it then better to implement an exclude/include facility in EF for that? &lt;/p&gt;  &lt;p&gt;Anyway, it's solved now and I'm glad this scenario has a happy end as I didn't expect it would. I hope it helps some poor souls out there who are faced with the same problem and I also hope some people within Microsoft do realize that if you make it difficult for 3rd party frameworks to support your frameworks, they might stop doing so. &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=10371764" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=mGkTz2Znaxo:1o9TbjmAje8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=mGkTz2Znaxo:1o9TbjmAje8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=mGkTz2Znaxo:1o9TbjmAje8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=mGkTz2Znaxo:1o9TbjmAje8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=mGkTz2Znaxo:1o9TbjmAje8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/mGkTz2Znaxo" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/LLBLGen+Pro/default.aspx">LLBLGen Pro</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/O_2F00_R+Mapping/default.aspx">O/R Mapping</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Advanced+.NET/default.aspx">Advanced .NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Linq/default.aspx">Linq</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Linq+to+LLBLGen+Pro/default.aspx">Linq to LLBLGen Pro</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/entity+framework/default.aspx">entity framework</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2013/06/02/wcf-data-services-and-the-iexpandprovider.aspx</feedburner:origLink></item><item><title>LLBLGen Pro v4.0 feature highlights: Resultset Caching</title><link>http://feedproxy.google.com/~r/FransBouma/~3/VhPi1-iJ21M/llblgen-pro-v4-0-feature-highlights-resultset-caching.aspx</link><pubDate>Wed, 29 May 2013 10:08:59 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:10364306</guid><dc:creator>FransBouma</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=10364306</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2013/05/29/llblgen-pro-v4-0-feature-highlights-resultset-caching.aspx#comments</comments><description>&lt;p&gt;This is the second post of a series about the new features in &lt;a href="http://www.llblgen.com/"&gt;LLBLGen Pro&lt;/a&gt; v4.0, which was released on April 6th, 2013. Today I'd like to highlight a new major feature of the LLBLGen Pro Runtime Framework, our own ORM framework shipped with LLBLGen Pro, namely Resultset Caching. &lt;/p&gt;  &lt;p&gt;I have &lt;a href="http://weblogs.asp.net/fbouma/archive/2006/08/31/Why-a-cache-in-an-O_2F00_R-mapper-doesn_2700_t-make-it-fetch-data-faster_2E00_.aspx" target="_blank"&gt;written about caching in ORMs before&lt;/a&gt;, though that particular way of caching was about materialized objects, which is something else than Resultset Caching. Resultset Caching is a mechanism which caches the actual resultset used during the execution of a select query for a given duration. This means that if a given Linq / QuerySpec query is specified to have its resultset cached for e.g. 10 seconds, every execution of the exact same query with the same parameters will pull the results from the cache for the 10 seconds after the query was first executed on the database. &lt;/p&gt;  &lt;p&gt;Caching can lead to better performance in situations where a query is taking a relatively long time in the database and/or is executed a lot of times: by automatically re-using already read rows from the cache instead of from the database, a round trip + query execution is omitted. This is completely transparent and automatic: the only thing the developer has to do is to specify with a query whether it should cache its resultset and for how long. &lt;/p&gt;  &lt;p&gt;The caching system is opt-in per query, so by default, all queries are executed on the database, every time, and no caching takes place. This is ideal because caching resultsets means that the resultset of a query which is defined to cache its results might pull its resultset from the cache instead of the database and therefore it might be the data is out-of-date with the data in the database: the cache data is 'stale' data, but for many situations this is ok, at least for a short period of time. &lt;/p&gt;  &lt;p&gt;Resultset caching is done through &lt;em&gt;cache objects&lt;/em&gt; which implement the caching of resultsets, either by delegating it to 3rd party servers like the .NET system cache or e.g. Memcached, or by doing the caching themselves like the built-in &lt;strong&gt;ResultsetCache&lt;/strong&gt; class. Cache objects implement a common interface, IResultsetCache , and it's easy to implement a cache object class yourself. With the LLBLGen Pro Runtime Framework we ship the built-in ResultsetCache class and in the recently started &lt;a href="https://github.com/SolutionsDesign/LLBLGenProContrib" target="_blank"&gt;LLBLGen Pro contrib library&lt;/a&gt; (github) we ship an implementation of the IResultsetCache interface for caching data in the .NET 4+ cache &lt;a href="https://github.com/SolutionsDesign/LLBLGenProContrib/blob/master/SD.LLBLGen.Pro.ORMSupportClasses.Contrib/Caching/MemoryCachedResultsetCache.cs" target="_blank"&gt;MemoryCache&lt;/a&gt;. As you can see with the MemoryCache supporting implementation, it's very easy to add a class which caches the data in your cache system of choice, e.g. Redis. &lt;/p&gt;  &lt;h4&gt;Registering a cache&lt;/h4&gt;  &lt;p&gt;Before caching can take place, at least one cache has to be registered with the &lt;strong&gt;CacheController&lt;/strong&gt;. The &lt;strong&gt;CacheController&lt;/strong&gt; is a static class which keeps track of the registered &lt;em&gt;caches&lt;/em&gt; and is consulted by the query object whether a cached set of rows is available for that query. &lt;/p&gt;  &lt;p&gt;Example of registering an instance of the ResultsetCache: &lt;/p&gt; &lt;code class="csharpcode"&gt;CacheController.RegisterCache(connectionString, &lt;span class="kwrd"&gt;new&lt;/span&gt; ResultsetCache()); &lt;/code&gt;&lt;style type="text/css"&gt;





.csharpcode, .csharpcode code
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	overflow: auto;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;  &lt;p&gt;After this line, all queries executed over a connection with the same connection string and which are specified to have their resultsets cached, are cached in the ResultsetCache instance registered. This means you can have multiple caches if you have multiple databases in use at the same time. You can also use one cache for all databases in use, by specifying an empty string as the connection string. &lt;/p&gt;  &lt;h4&gt;What makes a query unique? The Cache Key&lt;/h4&gt;  &lt;p&gt;Resultsets are cached in a cache under a key, a &lt;strong&gt;CacheKey&lt;/strong&gt; instance. A &lt;strong&gt;CacheKey&lt;/strong&gt; is created from a query object which provides the values for the key. &lt;/p&gt;  &lt;p&gt;A &lt;strong&gt;CacheKey&lt;/strong&gt; uses: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The SQL statement &lt;/li&gt;    &lt;li&gt;All parameter values before execution &lt;/li&gt;    &lt;li&gt;Flags for in-memory distinct/limiting/paging &lt;/li&gt;    &lt;li&gt;Values for rows to skip/take in in-memory paging scenarios &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;A hashcode is calculated from these values and an &lt;em&gt;Equals&lt;/em&gt; implementation makes sure two &lt;strong&gt;CacheKey&lt;/strong&gt; instances are only considered equal if all of these values are indeed equal. This makes sure that two queries which differ only in e.g. parameter values will not return each other's resultsets from the cache. Two pieces of code which are fetching data differently (e.g. a normal entity collection fetch and a projection using all entity fields onto a custom class) but result in the same SQL query and parameters will re-use the same set from the cache, if both queries are defined to be cacheable.&lt;/p&gt;  &lt;h4&gt;Specifying a query to have its resultset cached&lt;/h4&gt;  &lt;p&gt;LLBLGen Pro has three ways to specify a query: Linq, QuerySpec and the Low-level API. We primarily added caching specification code to Linq and QuerySpec, as those two query APIs are the recommended way to formulate queries. I'll show how to specify caching directives in Linq and QuerySpec below. &lt;/p&gt;  &lt;h5&gt;QuerySpec&lt;/h5&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;// typed list fetch &lt;/span&gt;
var tl = &lt;span class="kwrd"&gt;new&lt;/span&gt; OrderCustomerTypedList();
var q = tl.GetQuerySpecQuery(&lt;span class="kwrd"&gt;new&lt;/span&gt; QueryFactory())
                 .CacheResultset(10);  &lt;span class="rem"&gt;// cache for 10 seconds&lt;/span&gt;
&lt;span class="kwrd"&gt;new&lt;/span&gt; DataAccessAdapter().FetchAsDataTable(q, tl);

&lt;span class="rem"&gt;// typed view fetch&lt;/span&gt;
var qf = &lt;span class="kwrd"&gt;new&lt;/span&gt; QueryFactory();
var q = qf.Create()
            .Select(InvoicesFields.CustomerId, InvoicesFields.CustomerName, InvoicesFields.OrderId)
            .Where(InvoicesFields.Country.StartsWith(&lt;span class="str"&gt;&amp;quot;U&amp;quot;&lt;/span&gt;))
            .CacheResultset(10);        &lt;span class="rem"&gt;// cache for 10 seconds&lt;/span&gt;
var tv = &lt;span class="kwrd"&gt;new&lt;/span&gt; InvoicesTypedView();
&lt;span class="kwrd"&gt;new&lt;/span&gt; DataAccessAdapter().FetchAsDataTable(q, tv);

&lt;span class="rem"&gt;// dynamic list / custom projection&lt;/span&gt;
var qf = &lt;span class="kwrd"&gt;new&lt;/span&gt; QueryFactory();
var q = qf.Employee
        .From(QueryTarget.InnerJoin(qf.Order)
                   .On(EmployeeFields.EmployeeId == OrderFields.EmployeeId))
        .OrderBy(EmployeeFields.EmployeeId.Ascending()).Offset(1).Distinct()
        .Select(() =&amp;gt; &lt;span class="kwrd"&gt;new&lt;/span&gt;
            {
                EmployeeId = EmployeeFields.EmployeeId.ToValue&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt;(),
                Notes = EmployeeFields.Notes.ToValue&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;()
            })
        .CacheResultset(5);    &lt;span class="rem"&gt;// cache for 5 seconds&lt;/span&gt;
var results = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataAccessAdapter().FetchQuery(q);

&lt;span class="rem"&gt;// custom projection with nested set&lt;/span&gt;
var qf = &lt;span class="kwrd"&gt;new&lt;/span&gt; QueryFactory();
var q = qf.Create()
        .Select(() =&amp;gt; &lt;span class="kwrd"&gt;new&lt;/span&gt;
          {
                Key = CustomerFields.Country.ToValue&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(),
                CustomersInCountry = qf.Customer.TargetAs(&lt;span class="str"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;)
                                         .CorrelatedOver(CustomerFields.Country.Source(&lt;span class="str"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;) ==
                                                         CustomerFields.Country)
                                         .ToResultset()
          })
        .GroupBy(CustomerFields.Country)
        .CacheResultset(10);     &lt;span class="rem"&gt;// cache all for 10 seconds&lt;/span&gt;
var results = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataAccessAdapter().FetchQuery(q);

&lt;span class="rem"&gt;// entity fetch&lt;/span&gt;
var qf = &lt;span class="kwrd"&gt;new&lt;/span&gt; QueryFactory();
var q = qf.Customer
            .Where(CustomerFields.Country == &lt;span class="str"&gt;&amp;quot;Germany&amp;quot;&lt;/span&gt;)
                 .WithPath(CustomerEntity.PrefetchPathOrders
                               .WithSubPath(OrderEntity.PrefetchPathEmployee),
                                      CustomerEntity.PrefetchPathEmployeeCollectionViaOrder)
            .CacheResultset(10);    &lt;span class="rem"&gt;// cache all for 10 seconds&lt;/span&gt;
var customers = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataAccessAdapter().FetchQuery(q);&lt;/pre&gt;

&lt;h5&gt;Linq&lt;/h5&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;// custom projection, with nested set&lt;/span&gt;
var metaData = &lt;span class="kwrd"&gt;new&lt;/span&gt; LinqMetaData(&lt;span class="kwrd"&gt;new&lt;/span&gt; DataAccessAdapter());
var q = (from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer
          group c by c.Country into g
          select &lt;span class="kwrd"&gt;new&lt;/span&gt;
          {
             g.Key,
             CustomersInCountry = (
                  from c2 &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer
                  &lt;span class="kwrd"&gt;where&lt;/span&gt; g.Key == c2.Country
                  select c2)
          })
         .CacheResultset(10);    &lt;span class="rem"&gt;// cache all for 10 seconds&lt;/span&gt;

&lt;span class="rem"&gt;// entity fetch with prefetch path&lt;/span&gt;
LinqMetaData metaData = &lt;span class="kwrd"&gt;new&lt;/span&gt; LinqMetaData(adapter);
var q = (from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer
          &lt;span class="kwrd"&gt;where&lt;/span&gt; c.Country == &lt;span class="str"&gt;&amp;quot;Germany&amp;quot;&lt;/span&gt;
          select c).WithPath&amp;lt;CustomerEntity&amp;gt;(cpath =&amp;gt; cpath
                 .Prefetch&amp;lt;OrderEntity&amp;gt;(c =&amp;gt; c.Orders)
                     .SubPath(opath =&amp;gt; opath
                         .Prefetch(o =&amp;gt; o.OrderDetails)
                         .Prefetch&amp;lt;EmployeeEntity&amp;gt;(o =&amp;gt; o.Employee).Exclude(e =&amp;gt; e.Photo, e =&amp;gt; e.Notes)))
          .CacheResultset(10);    // cache all &lt;span class="kwrd"&gt;for&lt;/span&gt; 10 seconds&lt;/pre&gt;

&lt;p&gt;As you can see, it's just an operator to the query, and from then on its resultset is cached in the cache object registered for the connection string used at runtime. If there's already a resultset, that one is used; if there's no cached resultset found, the one read from the database is cached for the specified amount of time so the next execution of the same query will re-use that resultset. &lt;/p&gt;

&lt;p&gt;an easy way to tweak your data-access code on a per-query basis. &lt;/p&gt;

&lt;p&gt;&lt;img class="wlEmoticon wlEmoticon-smile" style="border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none" alt="Smile" src="http://weblogs.asp.net/blogs/fbouma/wlEmoticon-smile_2096E658.png" /&gt;&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=10364306" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=VhPi1-iJ21M:9hIz-mrjI2g:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=VhPi1-iJ21M:9hIz-mrjI2g:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=VhPi1-iJ21M:9hIz-mrjI2g:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=VhPi1-iJ21M:9hIz-mrjI2g:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=VhPi1-iJ21M:9hIz-mrjI2g:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/VhPi1-iJ21M" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET+General/default.aspx">.NET General</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Database+_2F00_+SQL+Server/default.aspx">Database / SQL Server</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/LLBLGen+Pro/default.aspx">LLBLGen Pro</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/O_2F00_R+Mapping/default.aspx">O/R Mapping</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Advanced+.NET/default.aspx">Advanced .NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Linq/default.aspx">Linq</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Linq+to+LLBLGen+Pro/default.aspx">Linq to LLBLGen Pro</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2013/05/29/llblgen-pro-v4-0-feature-highlights-resultset-caching.aspx</feedburner:origLink></item><item><title>ORM Profiler now .NET 4.5 / Async aware</title><link>http://feedproxy.google.com/~r/FransBouma/~3/M2bpxQlaFB0/orm-profiler-now-net-4-5-async-aware.aspx</link><pubDate>Fri, 24 May 2013 11:29:28 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:10338037</guid><dc:creator>FransBouma</dc:creator><slash:comments>2</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=10338037</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2013/05/24/orm-profiler-now-net-4-5-async-aware.aspx#comments</comments><description>&lt;p&gt;We updated our data-access profiler &lt;a href="http://www.ormprofiler.com" target="_blank"&gt;ORM Profiler&lt;/a&gt; with a new .NET 4.5 specific interceptor dll. This interceptor, which is called &lt;strong&gt;SD.Tools.OrmProfiler.Interceptor.NET45.dll&lt;/strong&gt;, can be found in the main installation folder of the ORM Profiler build we uploaded this week. If you're an ORM Profiler customer, please download the latest build from the customer area. &lt;/p&gt;  &lt;p&gt;The .NET 4.5 interceptor intercepts calls to Async specific ADO.NET methods, and also contains all Entity Framework required classes, so there's no need for the EF4 specific interceptor if you're using .NET 4.5 and Entity Framework 5. Using this interceptor, any call to a *Async method will not fall back to the synchronous calls of System.Data.Common classes as the previous builds did, but will call into the Async methods of the used ADO.NET provider. &lt;/p&gt;  &lt;p&gt;There's more async news coming soon, namely for &lt;a href="http://www.llblgen.com/" target="_blank"&gt;LLBLGen Pro v4&lt;/a&gt;, stay tuned &lt;img class="wlEmoticon wlEmoticon-smile" style="border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none" alt="Smile" src="http://weblogs.asp.net/blogs/fbouma/wlEmoticon-smile_15F3B73A.png" /&gt;&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=10338037" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=M2bpxQlaFB0:i0fZWDwDCU0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=M2bpxQlaFB0:i0fZWDwDCU0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=M2bpxQlaFB0:i0fZWDwDCU0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=M2bpxQlaFB0:i0fZWDwDCU0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=M2bpxQlaFB0:i0fZWDwDCU0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/M2bpxQlaFB0" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET+General/default.aspx">.NET General</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/LLBLGen+Pro/default.aspx">LLBLGen Pro</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/O_2F00_R+Mapping/default.aspx">O/R Mapping</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/ORM+Profiler/default.aspx">ORM Profiler</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/entity+framework/default.aspx">entity framework</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2013/05/24/orm-profiler-now-net-4-5-async-aware.aspx</feedburner:origLink></item><item><title>LLBLGen Pro v4.0 feature highlights: Visual Studio integration</title><link>http://feedproxy.google.com/~r/FransBouma/~3/mSZ9SwTwLQQ/llblgen-pro-v4-0-feature-highlights-visual-studio-integration.aspx</link><pubDate>Mon, 13 May 2013 10:32:29 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:10281338</guid><dc:creator>FransBouma</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=10281338</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2013/05/13/llblgen-pro-v4-0-feature-highlights-visual-studio-integration.aspx#comments</comments><description>&lt;p&gt;This is the first post of a series about the new features in &lt;a href="http://www.llblgen.com/" target="_blank"&gt;LLBLGen Pro&lt;/a&gt; v4.0, which was released on April 6th, 2013. Starting with v4.0, the LLBLGen Pro designer is usable both as standalone (as it was before) and as an integrated designer in Visual Studio. I'll explain in this article what this integration is all about and what we had to do to make it work. If you want to know more about how to use this feature, &lt;a href="http://www.llblgen.com/documentation/4.0/Designer/hh_goto.htm#How%20To/VSNetIntegration.htm" target="_blank"&gt;please check out the manual page on this feature&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;So how does this integration look like? Below is a screenshot from the manual:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.llblgen.com/documentation/4.0/Designer/Images/gui_overview_vsnet.png" /&gt;&lt;/p&gt;  &lt;p&gt;It almost looks like the stand-alone designer, eh? &lt;img class="wlEmoticon wlEmoticon-winkingsmile" style="border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none" alt="Winking smile" src="http://weblogs.asp.net/blogs/fbouma/wlEmoticon-winkingsmile_2B6E0BD5.png" /&gt;Integrating in Visual Studio can be done in several ways: through e.g. a plug-in/add-in, an extension to the editor or a Visual Studio extension. Our integration is done through a Visual Studio extension (VSIX). &lt;/p&gt;  &lt;h2&gt;How the integration works, user perspective&lt;/h2&gt;  &lt;p&gt;When you start Visual Studio, the extension isn't visible: no menus, no tool windows, no tool bars. When you load an LLBLGen Pro project (a file with the extension '.llblgenproj') into Visual Studio, or create a new one inside Visual Studio using the normal item creation system, the designer is loaded inside Visual Studio: all panes are opened as tool windows and the project file itself is opened as a &lt;em&gt;document editor&lt;/em&gt; inside the document well (central tab area) of Visual Studio. When this document editor, which is a single tab inside the document well, has the focus, the toolbar and menu are visible, and the project's contents is visible in the various tool windows (see screen shot above). &lt;/p&gt;  &lt;p&gt;Opening another LLBLGen Pro project inside Visual Studio opens another document editor, but no extra tool windows. Instead, the contents of the tool windows is switched when you switch between document editors so they always show the project contents of the document editor which has focus. For a background on this, please see the section below called 'How we wrote the VSIX'. &lt;/p&gt;  &lt;p&gt;Generating code will add the generated VS.NET projects to the loaded solution, if they're not already present there. This way of working as the advantage that you don't have to leave VS.NET to work with the designer, you can add the LLBLGen Pro project to your solution as a bonus don't have to manually add the generated code to your solution. &lt;/p&gt;  &lt;p&gt;All functionality, except imports (see below) is the same as with the stand-alone designer, as the stand-alone designer is actually loaded inside Visual Studio and its parts are displayed within the IDE. &lt;/p&gt;  &lt;h2&gt;How we wrote the VSIX (or: how to lose your hair in 2 months)&lt;/h2&gt;  &lt;p&gt;Visual Studio is mainly an IDE around editing files: a file is opened with the associated editor of the file's extension in the document well and the editor associated with the file's extension can open 0 or more tool windows and do other things. You can of course open tool windows inside the document well which edit 'objects' and not 'files', however this isn't as simple as it sounds. And precisely that was a problem we had to solve: our designer is also an IDE with a central tab area but instead of opening files in that tab area, we open editors of objects. &lt;/p&gt;  &lt;p&gt;To make Visual Studio work like our designer, we were forced to go what I'd call, 'the All-In' route: create custom project types for Visual Studio, rewrite our project explorer to build objects in the Solution Explorer in Visual Studio, open custom tool windows inside the document well of Visual Studio for each object edited. We quickly learned that creating an extension to Visual Studio is not a walk in the park: the code isn't that complex, it's the lack of serious documentation, examples and above all, the quirks of the IDE which made it a big a project to complete. Looking at the work for the All-in variant, we decided to go for the alternative: create a file-extension bound editor. Looking back this was a wise decision, as this extension too took us a long time to create, almost two months.&amp;#160; &lt;/p&gt;  &lt;p&gt;With v3.0, released in early 2010, we designed the designer to be modular so it wouldn't be to much work to make it usable from within another application, e.g. Visual Studio. The UI is broken up in several parts and all designer logic is structured in an event-oriented system with several controllers on top. The advantage of this is that whenever something happens inside the UI, one or more events are raised and observers to these events (or the events as result of these events) are picking them up and act accordingly. These observers are all located outside the UI. The main advantage of this is that even though the designer in stand-alone form looks like an MDI window with tool windows docked inside it, the control of these docked windows and what happens inside them is not within the MDI window. &lt;/p&gt;  &lt;p&gt;The v4.0 designer is a successor of v3's so with the modular design at hand we decided to create a Visual Studio extension tied to the LLBLGen Pro project file file-extension '.llblgenproj'. In Visual Studio terms: a custom document editor. A Visual Studio extension is actually a Visual Studio &lt;em&gt;package&lt;/em&gt;, packed in the form of an 'extension'. The extension contains of the following parts: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Each docked 'pane' in the designer is opened as a Visual Studio Tool window and docked inside the IDE &lt;/li&gt;    &lt;li&gt;The document well of the designer is opened as a Visual Studio Document Editor in the document well. &lt;/li&gt;    &lt;li&gt;The toolbar is created as a button bar inside Visual Studio &lt;/li&gt;    &lt;li&gt;The menus are pivoted into a single menu in the main menu of Visual Studio &lt;/li&gt;    &lt;li&gt;A factory which produces new document editors &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;To achieve this, we wrote an extension which loads the standalone designer into Visual Studio, and instead of telling it to open an MDI window and dock some panes into it, it simply tells the loaded designer to hand the pane windows and its own window to the extension object. The extension object then opens the Visual Studio tool windows and its main editor and there you are: integrated inside Visual Studio. &lt;/p&gt;  &lt;p&gt;Simple? Well… not quite. &lt;/p&gt;  &lt;p&gt;The fun starts with where Visual Studio extensions are located. There are two locations: inside the user's My Documents folder and inside the Visual Studio installation folder. Both locations are not ideal if you want your code to also be usable as stand-alone. The trick was to create a registry key at installation which is read by the Visual Studio extension which points to the folder where LLBLGen Pro was installed. I tried numerous things, including junctions but these all failed. The registry key is easy enough though. &lt;/p&gt;  &lt;p&gt;The next problem was something we never had to run into before: what if multiple LLBLGen Pro projects are opened inside Visual Studio? Although opening multiple LLBLGen Pro projects will open multiple instances of the designer, without separating the AppDomains, we'd run into problems where statics were suddenly shared among instances. However, creating a new AppDomain per instance wouldn't work as that would require the editor panes we would like to show inside the designer to serializable, which isn't possible. Luckily we had grouped all statics inside objects which lived in a few singletons which act as Services inside our designer. &lt;/p&gt;  &lt;p&gt;Whenever a designer instance was loaded into the extension, we assigned to it an ID and we'd request an object we dubbed &lt;em&gt;integration controller&lt;/em&gt; from the designer, which would act like the controller of the designer and data exchange. Through this controller we also could tell the designer instance which document editor instance was active. The services/singletons then switched their state to the instance ID passed to the integration controller and all code of the designer and its sub-systems would think they were running inside the stand-alone version. &lt;/p&gt;  &lt;p&gt;This state-switching also helped with the tool windows of Visual Studio: by default each Visual Studio tool window is created just once. You can create multiple instances if you must, but you'll soon learn that multiple instances of a tool window makes things less usable. So each time a document editor became &lt;em&gt;active&lt;/em&gt; inside the IDE, the document editor would get called by the IDE and we simply made the extension to update the associated designer's state to the one associated with the document editor's ID and as well update the tool windows to the ones of the designer instance associated with the ID. &lt;/p&gt;  &lt;p&gt;On to undo-redo. Our own designer has a full undo-redo system, based on &lt;a href="https://github.com/SolutionsDesign/Algorithmia" target="_blank"&gt;our OSS library Algorithmia&lt;/a&gt; (available on github), and so does VS.NET. Of course these aren't compatible with each other however the designer's undo-redo should work in sync with the VS.NET undo-redo system. After looking into making things compatible for a few days, it occurred to me it doesn't matter: whenever a user does something &lt;em&gt;through&lt;/em&gt; the document editor, the IDE will query your editor if the undo/redo state of the buttons should change. Our designer already kept track of that, so simply returning this state was enough. Whenever the user pressed the undo/redo buttons (or the keystrokes) inside the IDE, the document editor with focus got a call which was passed through to the integration controller to do the actual undo/redo on the model, similar to if the user would undo/redo in the stand-alone designer. &lt;/p&gt;  &lt;p&gt;Undo-redo is a global system, however with multiple instances, there are multiple undo/redo stacks active at once, one per instance. Algorithmia's undo/redo system is able to work with that: it works with 'scopes'. This means you can have local undo/redo separated from the global undo/redo. We utilize this in the integration so each designer instance is a separate scope inside the undo/redo system, so undo/redo information isn't shared. &lt;/p&gt;  &lt;p&gt;The last problem I'd like to address is installation. Visual Studio extensions, VSIXs, can be installed in two ways: you either dump all files in a folder in one of the two extension locations and let VS.NET know some extension installation took place or you wrap your code inside a .vsix file. The latter has as advantage that registration of your extension is done for you without a slow re-scan of the complete extension folders. It also takes care of locating the extensions folders. I first looked at the former alternative, as we use our own installer but the logic to locate the folders and install everything in both 2010 and 2012 was a pain, and everything was taken care of with a .vsix file: we simply run it silently during installation and it installs the extension in both 2010 and 2012 if present, in the right folder and registers the extension as well. &lt;/p&gt;  &lt;h2&gt;Was it all worth it?&lt;/h2&gt;  &lt;p&gt;Yes. Developing this extension was a true pain, I'd be lying if I called it something else, but as a tool / framework developer it's part of our job to write the painful code so our customers don't have to; that's why they pay for a license. In the end, I can only say I'm very pleased with the result and have heard only positive feedback from users, so in short: yes it was worth it. &lt;/p&gt;  &lt;p&gt;As I said above, creating a Visual Studio extension isn't a walk in the park: using .NET for an extension is possible, the SDK looks OK, the starter project gives you a lot of code to start with, but after a short while you'll learn that below this thin layer of chrome, the actual metal is pretty rusty and shows its true age. The technical debt of the C/C++/COM based system is so big, I doubt it will ever get better, especially as there's little incentive to do so: the biggest 'customer' of VS.NET's integration system is Microsoft itself, and as we all know internal code is more rough, less documented than software that's delivered to customers outside the company.&lt;/p&gt;  &lt;p&gt;If you're planning to develop your own Visual Studio extension, be aware of the fact you'll spend a lot of time cursing the IDE, it's long list of quirks and inconsistencies, missing docs and serious lack of examples how to do things: you'll run into many posts with similar questions as yours but with no or unusable answers. You're entitled to throw your hands into the air and scream the filthiest curse words in the direction of Redmond, but that won't get you near your goal. As an engineer, you have to think and act like one: write some prototype code and attach a debugger in another VS.NET instance to your test VS.NET instance to see what's happening, what's called when you do X. &lt;/p&gt;  &lt;p&gt;It will be a struggle at first, but you'll get there: and you'll have to do it yourself, there's no-one out there to help you. But hey, that's the life of an engineer.&lt;/p&gt;  &lt;p&gt;&lt;img class="wlEmoticon wlEmoticon-winkingsmile" style="border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none" alt="Winking smile" src="http://weblogs.asp.net/blogs/fbouma/wlEmoticon-winkingsmile_2B6E0BD5.png" /&gt;&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=10281338" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=mSZ9SwTwLQQ:TGwuDqqfCCM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=mSZ9SwTwLQQ:TGwuDqqfCCM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=mSZ9SwTwLQQ:TGwuDqqfCCM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=mSZ9SwTwLQQ:TGwuDqqfCCM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=mSZ9SwTwLQQ:TGwuDqqfCCM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/mSZ9SwTwLQQ" height="1" width="1"/&gt;</description><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2013/05/13/llblgen-pro-v4-0-feature-highlights-visual-studio-integration.aspx</feedburner:origLink></item><item><title>LLBLGen Pro v4.0 released!</title><link>http://feedproxy.google.com/~r/FransBouma/~3/15WxGkT98kU/llblgen-pro-v4-0-released.aspx</link><pubDate>Mon, 08 Apr 2013 09:48:08 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:10115038</guid><dc:creator>FransBouma</dc:creator><slash:comments>1</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=10115038</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2013/04/08/llblgen-pro-v4-0-released.aspx#comments</comments><description>&lt;p&gt;I'm proud to announce we've released v4.0 of &lt;a href="http://www.llblgen.com/" target="_blank"&gt;LLBLGen Pro&lt;/a&gt;! This release is the 13th full release we've done and it arrives in the year LLBLGen Pro turns 10. As always we've packed the new release with great new features and I hope we've added what you wanted us to add. You can find what's new here: &lt;a href="http://www.llblgen.com/pages/whatsnew.aspx"&gt;http://www.llblgen.com/pages/whatsnew.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Not only did we add new features, we also introduced something else: &lt;em&gt;Lite.&lt;/em&gt;&lt;/p&gt;  &lt;h4&gt;Lite&lt;/h4&gt;  &lt;p&gt;LLBLGen Pro &lt;em&gt;Lite &lt;/em&gt;is a &lt;strong&gt;free&lt;/strong&gt; version of LLBLGen Pro. It packs all the features of the full version, however it comes with a limitation: an entity model is limited to 8 entities per model and it also come with no support. It's free as in beer and you can use the generated code in production.&lt;/p&gt;  &lt;h4&gt;Upgrades&lt;/h4&gt;  &lt;p&gt;V3.x users can upgrade with a 30% discount, by logging into the customer area. &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=10115038" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=15WxGkT98kU:7CSRJvD6vQQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=15WxGkT98kU:7CSRJvD6vQQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=15WxGkT98kU:7CSRJvD6vQQ:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=15WxGkT98kU:7CSRJvD6vQQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=15WxGkT98kU:7CSRJvD6vQQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/15WxGkT98kU" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET+General/default.aspx">.NET General</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/LLBLGen+Pro/default.aspx">LLBLGen Pro</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/O_2F00_R+Mapping/default.aspx">O/R Mapping</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Advanced+.NET/default.aspx">Advanced .NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/General+Software+Development/default.aspx">General Software Development</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Code+generation/default.aspx">Code generation</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/entity+framework/default.aspx">entity framework</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2013/04/08/llblgen-pro-v4-0-released.aspx</feedburner:origLink></item><item><title>LLBLGen Pro v4.0 BETA released!</title><link>http://feedproxy.google.com/~r/FransBouma/~3/jX2NbVWX2dw/llblgen-pro-v4-0-beta-released.aspx</link><pubDate>Thu, 07 Mar 2013 16:35:59 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:9955952</guid><dc:creator>FransBouma</dc:creator><slash:comments>6</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=9955952</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2013/03/07/llblgen-pro-v4-0-beta-released.aspx#comments</comments><description>&lt;p&gt;   &lt;br /&gt;We've released the first beta of LLBLGen Pro v4.0! We hope you all like the new features and additions we packed into this new release! To make sure stuff is truly tested in a lot of scenario's, the beta is available to all v3.x licensees.     &lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;How to get the beta&lt;/b&gt;    &lt;br /&gt;Log into the customer area, then select 'v3.5' from the Downloads menu and navigate on the downloads page to 'Betas'. No license is required, the beta license is included in the installer.     &lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Installation&lt;/b&gt;    &lt;br /&gt;Run the installer as administrator. It will automatically install the VS.NET extension to use the designer inside VS.NET in VS.NET 2010 and VS.NET 2012 (pro and up), if available. Of course the designer is also usable as stand-alone, outside VS.NET.     &lt;br /&gt;The installer will start the VSIX (visual studio extension) installer at the end of the normal install. It might be the VSIX installer is still running when the normal installer ends. If you have VS.NET open when you install the beta, you'll have to close VS.NET and restart VS.NET to see the add-in.    &lt;br /&gt;You can install the beta side-by-side with older versions of LLBLGen Pro. V4's file format is compatible with v3, however a v4 file which is loaded into v3 and saved in v3 will lose v4 specific data.     &lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Documentation&lt;/b&gt;    &lt;br /&gt;We included a word document with the details about this beta, which features are included and how to use them. This document, called LLBLGen Pro v4.0 beta readme.docx, is installed in the LLBLGen Pro v4 beta installation.    &lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;How to provide feedback&lt;/b&gt;    &lt;br /&gt;Please provide all feedback in the beta forum: &lt;a href="http://www.llblgen.com/tinyforum/Threads.aspx?ForumID=52"&gt;http://www.llblgen.com/tinyforum/Threads.aspx?ForumID=52&lt;/a&gt;    &lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;What's new in V4.0&lt;/b&gt;    &lt;br /&gt;The list below is the global list of what's new in V4. The enclosed word document has the fine details of these new features and changes and also details of minor changes and new features not listed below.     &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;Designer&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Full Visual Studio integration (VS.NET 2010 / 2012)&lt;/li&gt;    &lt;li&gt;Table Valued Functions support (EF/Linq to Sql/LLBLGen Pro RTF)&lt;/li&gt;    &lt;li&gt;Additional interfaces/namespaces now use the rule system&lt;/li&gt;    &lt;li&gt;Update / Delete rules for FK constraints (Cascade delete/update)&lt;/li&gt;    &lt;li&gt;SQL Server 2012 sequence support (LLBLGen Pro RTF/NHibernate)&lt;/li&gt;    &lt;li&gt;Action suggestions window&lt;/li&gt;    &lt;li&gt;Custom type shortcuts can now have default length/precision&lt;/li&gt;    &lt;li&gt;The designer is now a .NET 4.0 application, no more .net 4 runners.&lt;/li&gt;    &lt;li&gt;Char &amp;lt;-&amp;gt; String system type converter&lt;/li&gt;    &lt;li&gt;Re-scan of enum typeimport files without closing designer&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Runtime Framework&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Table Valued Functions support&lt;/li&gt;    &lt;li&gt;Query result cache&lt;/li&gt;    &lt;li&gt;Much faster entity fetches&lt;/li&gt;    &lt;li&gt;Inlining DDD value types&lt;/li&gt;    &lt;li&gt;SQL Server 2012 sequence support&lt;/li&gt;    &lt;li&gt;Data Scopes (see &lt;a href="https://github.com/SolutionsDesign/LLBLGenProExamples_4.0"&gt;https://github.com/SolutionsDesign/LLBLGenProExamples_4.0&lt;/a&gt;)&lt;/li&gt;    &lt;li&gt;Xml Serializability of entire query API&lt;/li&gt;    &lt;li&gt;True skip / offset&lt;/li&gt;    &lt;li&gt;Fetch typed lists with QuerySpec&lt;/li&gt;    &lt;li&gt;Runtime libraries are now built against .NET 3.5 &lt;/li&gt;    &lt;li&gt;QuerySpec and Linq assemblies are merged into ORMSupport Classes&lt;/li&gt;    &lt;li&gt;OData support classes are now built against WCF Data Services 5.3 and support OData v3&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I'm especially pleased with the VS.NET integration which turned out to be very nice, the TVF support, the much faster query fetches, the query result cache and the DataScopes. Please check out the example available at github (like above) how little code it takes to make a typical LoB application with the new DataScopes. &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=9955952" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=jX2NbVWX2dw:nfvdwb0EcTI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=jX2NbVWX2dw:nfvdwb0EcTI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=jX2NbVWX2dw:nfvdwb0EcTI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=jX2NbVWX2dw:nfvdwb0EcTI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=jX2NbVWX2dw:nfvdwb0EcTI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/jX2NbVWX2dw" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET+General/default.aspx">.NET General</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Software+Engineering/default.aspx">Software Engineering</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/LLBLGen+Pro/default.aspx">LLBLGen Pro</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/O_2F00_R+Mapping/default.aspx">O/R Mapping</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Advanced+.NET/default.aspx">Advanced .NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Windows+Forms/default.aspx">Windows Forms</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Linq+to+LLBLGen+Pro/default.aspx">Linq to LLBLGen Pro</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Code+generation/default.aspx">Code generation</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/entity+framework/default.aspx">entity framework</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2013/03/07/llblgen-pro-v4-0-beta-released.aspx</feedburner:origLink></item><item><title>Re: You’re not your code</title><link>http://feedproxy.google.com/~r/FransBouma/~3/UnVwPVbFXn0/re-you-re-not-your-code.aspx</link><pubDate>Fri, 25 Jan 2013 10:26:32 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:9797977</guid><dc:creator>FransBouma</dc:creator><slash:comments>1</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=9797977</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2013/01/25/re-you-re-not-your-code.aspx#comments</comments><description>&lt;p&gt;This post is a reply to &lt;a href="http://hanselman.com" target="_blank"&gt;Scott Hanselman&lt;/a&gt;’s post: &amp;quot;&lt;a href="http://www.hanselman.com/blog/YouAreNotYourCode.aspx" target="_blank"&gt;You’re not your code&lt;/a&gt;&amp;quot;&lt;/p&gt;  &lt;p&gt;There are no two programmers in the world who like each others code, there's always criticism: &amp;quot;I would have done this differently&amp;quot; or worse &amp;quot;Whoa, dude, never heard of SOLID? Where are the tests for this?&amp;quot;. IMHO, criticism is OK, as long as it's based on well founded arguments and they make the original programmer of the criticized code learn new things. I don't think Scott's post is about that. &lt;/p&gt;  &lt;p&gt;I think Scott refers to this: simply bitching about someone else's code because you'd have implemented the same program much better&lt;em&gt;,&lt;/em&gt; as you see yourself as a great developer is stupid. &lt;/p&gt;  &lt;p&gt;I'd like to make an addition to that: if you think you're a great developer and express yourself in that fashion, and your &lt;em&gt;professional&lt;/em&gt; code is not code one can expect from a professional (i.e. code which is maintainable, without (most of the) bugs, it's well documented etc.), you're a fraud and it's a little bit different: you tried to sell the idea that your hack, your hobby code is professional code.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;em&gt;However&lt;/em&gt;, not all code is professional code. Sometimes we simply hack something together to make something happen 1 time, or only for a single user (ourselves). For example internally here I use a change log system in where I log changes made to the various parts of the tools we produce. This is a very rudimentary piece of software, with a tremendously ugly UI, buggy event handlers and the databinding sometimes gets confused. This is because I wrote it in one afternoon, no tests, no design thoughts, just started hammering in code and when it compiled without errors I said &amp;quot;Done!&amp;quot;. &lt;/p&gt;  &lt;p&gt;But it works, it gets the job done of what I want to do: log the change made into a database so I can sync it with the online change log on our website so users can browse the change log online. Every time I run into a bug (which isn't often, as I know what to click and do) in this marvelous piece of code (ahum) I say to myself &amp;quot;it might be better if I fix this some day&amp;quot;, but as the only time I use this software is when I have to do a push of a new build, this 'some day' is not today. &lt;/p&gt;  &lt;p&gt;If this software would ever be released somewhere in source-code form, it will likely be bashed to pieces. If I would release it as source-code with the remark 'great system to log your changes and sync with online database', the bashing would IMHO be justified. But as it's a tool which is only for myself, and if I would release it as 'Dunno if this helps anyone, it works for me, have fun' and a bigwig would bash it to pieces because he's holier than me, that bashing IMHO wouldn't be justified: it's a hack, not professional software. &lt;/p&gt;  &lt;p&gt;Bashing a hack released as a hack is stupid. Bashing a hack released as professional code isn't, as it exposes the hack as what it truly is: a hack. &lt;/p&gt;  &lt;p&gt;Question of course is: when is a piece of code a hack / hobby code and when does it become professional code? IMHO the variety of answers to that question will tell you why the bashing of other people's code will continue no matter what and why there will never be two programmers in the world who like each others code without criticism. &lt;/p&gt;  &lt;p&gt;Though we can do something. As it's difficult to determine when a piece of software is a hack if it's not described as such (not by one person but as a general qualification: if piece of software A is declared a hack, &lt;em&gt;everyone&lt;/em&gt; will agree it is in fact crap), we as developers could keep that in mind when we use our bash-hammer on some piece of code we found online somewhere: what is truly gained from our criticism? Will the world be a better place? Will the software magically become better? Or is it just about our own ego that by declaring piece of software A a true example of crapcode, our own code must be much better?&lt;/p&gt;  &lt;p&gt;The main reason we have to take that in mind is because we &lt;em&gt;are&lt;/em&gt; our code. Well, not entirely, but we &lt;em&gt;did&lt;/em&gt; write it. An outsider won't know whether we poured our soul into it and that we invested precious time in it. Bashing it to pieces because the fruits of our hard work is seen as a hack while it's not &lt;em&gt;is&lt;/em&gt; going to hurt. If it doesn't hurt, you're not caring enough about the quality of your work, or they might have been right: your work was a hack after all, it didn't exceed the hobby code bar. &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=9797977" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=UnVwPVbFXn0:u086w93Cv1I:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=UnVwPVbFXn0:u086w93Cv1I:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=UnVwPVbFXn0:u086w93Cv1I:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=UnVwPVbFXn0:u086w93Cv1I:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=UnVwPVbFXn0:u086w93Cv1I:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/UnVwPVbFXn0" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/Software+Engineering/default.aspx">Software Engineering</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/General+Software+Development/default.aspx">General Software Development</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Code+generation/default.aspx">Code generation</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2013/01/25/re-you-re-not-your-code.aspx</feedburner:origLink></item><item><title>LLBLGen Pro and JSON serialization</title><link>http://feedproxy.google.com/~r/FransBouma/~3/piMjPrVNMqc/llblgen-pro-and-json-serialization.aspx</link><pubDate>Sun, 04 Nov 2012 15:29:01 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:9298911</guid><dc:creator>FransBouma</dc:creator><slash:comments>2</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=9298911</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2012/11/04/llblgen-pro-and-json-serialization.aspx#comments</comments><description>&lt;p&gt;I accidentally removed a reply from &lt;a href="http://weblogs.asp.net/fbouma/archive/2012/10/05/how-to-make-asp-net-webapi-serialize-your-llblgen-pro-entities-to-json.aspx" target="_blank"&gt;my previous blogpost&lt;/a&gt;, and as this blog-engine here at weblogs.asp.net is apparently falling apart, I can't re-add it as it thought it would be wise to disable comment controls on all posts, except new ones. So I'll post the reply here as a quote and reply on it. &lt;/p&gt;  &lt;p&gt;'Steven' asks:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;What would the future be for LLBLGen Pro to support JSON for serialization? Would it be worth the effort for a LLBLGenPro user to bother creating some code templates to produce additional JSON serializable classes?&lt;/p&gt;    &lt;p&gt;Or just create some basic POCO classes which could be used for exchange of client/server data and use DTO to map these back to LLBGenPro ones? If I understand the work around, it is at the expense of losing xml serialization.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Well, as described in &lt;a href="http://weblogs.asp.net/fbouma/archive/2012/10/05/how-to-make-asp-net-webapi-serialize-your-llblgen-pro-entities-to-json.aspx" target="_blank"&gt;the previous post&lt;/a&gt;, to enable JSON serialization, you can do that with a couple of lines and some attribute assignments. However, indeed, the attributes might make the XML serialization not working, as described in the previous blogpost. This is the case if the service you're using serializes objects using the DataContract serializer: this serializer will give up to serialize the entity objects to XML as the entity objects implement IXmlSerializable and this is a no-go area for the DataContract serializer. &lt;/p&gt;  &lt;p&gt;However, if your service doesn't use a DataContract serializer, or you serialize the objects manually to Xml using an xml serializer, you're fine. &lt;/p&gt;  &lt;p&gt;When you want to switch to Xml serializing again, instead of JSON in WebApi, and you have decorated the entity classes with the data-contract attributes, you can switch off the DataContract serializer, by setting a &lt;a href="http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization" target="_blank"&gt;global configuration setting&lt;/a&gt;: &lt;/p&gt;  &lt;pre&gt;var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
xml.UseXmlSerializer = true;&lt;/pre&gt;

&lt;p&gt;This will make the WebApi use the XmlSerializer, and run the normal IXmlSerializable interface implementation. &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=9298911" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=piMjPrVNMqc:nB7Nlw1gG1g:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=piMjPrVNMqc:nB7Nlw1gG1g:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=piMjPrVNMqc:nB7Nlw1gG1g:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=piMjPrVNMqc:nB7Nlw1gG1g:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=piMjPrVNMqc:nB7Nlw1gG1g:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/piMjPrVNMqc" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET+General/default.aspx">.NET General</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/LLBLGen+Pro/default.aspx">LLBLGen Pro</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Advanced+.NET/default.aspx">Advanced .NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Code+generation/default.aspx">Code generation</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2012/11/04/llblgen-pro-and-json-serialization.aspx</feedburner:origLink></item><item><title>How to make ASP.NET WebApi serialize your LLBLGen Pro entities to JSON</title><link>http://feedproxy.google.com/~r/FransBouma/~3/lk4yPQZo64c/how-to-make-asp-net-webapi-serialize-your-llblgen-pro-entities-to-json.aspx</link><pubDate>Fri, 05 Oct 2012 13:01:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:9049371</guid><dc:creator>FransBouma</dc:creator><slash:comments>4</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=9049371</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2012/10/05/how-to-make-asp-net-webapi-serialize-your-llblgen-pro-entities-to-json.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://www.llblgen.com" mce_href="http://www.llblgen.com" target="_blank"&gt;LLBLGen Pro&lt;/a&gt; has several ways to serialize / deserialize your entity data in an LLBLGen Pro Entity object:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;font color="#000000"&gt;Binary, using superfast custom binary formatters, triggered by ISerializable methods.&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;&lt;font color="#000000"&gt;XML, using XmlDocuments&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;&lt;font color="#000000"&gt;XML, using XmlWriters, triggered by IXmlSerializable methods. Xml is configurable to various formats, from verbose (to rebuild the objects using the embedded type info) to compact ("Just the data, ma'am")&lt;/font&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Once upon a time, all these fancy methods were the latest and greatest. Today however, they're not modern anymore, as a new format is taken over: JSON. JSON as the advantage that you can easily consume it in javascript on the client, no custom XML parser needed. &lt;/p&gt;  &lt;p&gt;Microsoft recently released ASP.NET 4.0 MVC with a fancy new service system: &lt;a href="http://www.asp.net/web-api" mce_href="http://www.asp.net/web-api" target="_blank"&gt;WebAPI&lt;/a&gt;. WebAPI let's you create a service without the hassle that's required with a WCF service running inside IIS. Not only makes WebAPI it easy to write a service for your data needs on a client, it also makes it easy to serialize/deserialize this data as JSON. &lt;/p&gt;  &lt;p&gt;This post is about how to make WebAPI work with LLBLGen Pro and serialize the data to JSON without the internals bleeding into the JSON data. &lt;/p&gt;  &lt;p&gt;&lt;b&gt;Note&lt;/b&gt;: by following these steps, the data is serialized as JSON only, the XML serializer won't work anymore (see below). By default, WebAPI serializes to XML, so you need these steps only if you want to serialize to JSON. &lt;/p&gt;  &lt;h4&gt;Step 1: decorate your entities, fields and navigators&lt;/h4&gt;  &lt;p&gt;LLBLGen Pro's designer has the ability to decorate generated classes and members of the generated classes with attributes, even based on rules you set. See a &lt;a href="http://weblogs.asp.net/fbouma/archive/2012/05/21/llblgen-pro-feature-highlights-assigning-attributes-based-on-rules-to-properties-in-generated-code.aspx" mce_href="http://weblogs.asp.net/fbouma/archive/2012/05/21/llblgen-pro-feature-highlights-assigning-attributes-based-on-rules-to-properties-in-generated-code.aspx" target="_blank"&gt;previous blogpost about this feature&lt;/a&gt; or &lt;a href="http://www.llblgen.com/documentation/3.5/Designer/hh_goto.htm#How%20To/AssignAttributesToElements.htm" mce_href="http://www.llblgen.com/documentation/3.5/Designer/hh_goto.htm#How%20To/AssignAttributesToElements.htm" target="_blank"&gt;the documentation for details&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;Load your LLBLGen Pro project into the designer and select from the main menu &lt;b&gt;Project -&amp;gt; Settings&lt;/b&gt;. A dialog opens. Navigate to General -&amp;gt; Conventions -&amp;gt; Code Generation -&amp;gt; Attributes. &lt;/p&gt;  &lt;p&gt;At the top, 'Entity' is selected. Add below &lt;i&gt;Attribute definition&lt;/i&gt;: DataContract&lt;/p&gt;  &lt;p&gt;Press enter. &lt;/p&gt;  &lt;p&gt;Select at the top 'NormalField'. Add below &lt;i&gt;Attribute definition: &lt;/i&gt;DataMember&lt;/p&gt;  &lt;p&gt;Press enter.&lt;/p&gt;  &lt;p&gt;Repeat the action you did with NormalField also for NavigatorSingleValue and NavigatorCollection.&lt;/p&gt;  &lt;p&gt;Click OK to close the settings dialog. You have now decorated all entities, the fields of the entities and the navigator properties with the required attributes. &lt;/p&gt;  &lt;p&gt;Regenerate your code. &lt;/p&gt;  &lt;h4&gt;Step 2: Make WebAPI's JSON serialize do the right thing&lt;/h4&gt;  &lt;p&gt;Now, you might think that with the DataContract/DataMember attributes, we're going to use the DataContractJsonSerializer, but that's not the case. Not only is that serializer not recommended by many, including &lt;a href="http://www.west-wind.com/weblog/posts/2012/Mar/09/Using-an-alternate-JSON-Serializer-in-ASPNET-Web-API" mce_href="http://www.west-wind.com/weblog/posts/2012/Mar/09/Using-an-alternate-JSON-Serializer-in-ASPNET-Web-API" target="_blank"&gt;Rick Strahl&lt;/a&gt;, it also fails to do anything as it complains that the entity objects implement IXmlSerializable and it can't work with objects which implement IXmlSerializable and have DataContract attributes. These kind of errors show how dumb the serialization strategies (or lack thereof, if they had implement a proper strategy pattern for this it would all be OK) of Microsoft have been during the years: I &lt;i&gt;have to&lt;/i&gt; have IXmlSerializable implemented on the classes for Xml serialization over normal WCF services to make sure &lt;i&gt;change tracking &lt;/i&gt;data is preserved and also object graph references are left in-tact. The same error is given when we try to serialize the data to XML instead of JSON. &lt;/p&gt;  &lt;p&gt;We're going to use the default JSON serializer of WebAPI, which is the Newtonsoft JSON.NET serializer. By default it doesn't do what we want, so we have to configure it. It's simple:&lt;/p&gt;  &lt;p&gt;Open WebApiConfig.cs which is located in the App_Start folder. Now add the following lines to the &lt;b&gt;Register&lt;/b&gt; method:&lt;/p&gt;  &lt;pre class="c#" name="code"&gt;var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
json.SerializerSettings.ContractResolver = new DefaultContractResolver() 
    { 
        IgnoreSerializableInterface = true, 
        IgnoreSerializableAttribute = true 
    };&lt;/pre&gt;

&lt;h4&gt;Step 3: There's no step 3&lt;/h4&gt;

&lt;p&gt;You're all setup now. A method like:&lt;/p&gt;

&lt;pre class="c#" name="code"&gt;public IEnumerable&amp;lt;ProductEntity&amp;gt; GetAllProducts()
{
    using(var adapter = new DataAccessAdapter())
    {
        var metaData = new LinqMetaData(adapter);
        return metaData.Product.WithPath(p=&amp;gt;p.Prefetch(x=&amp;gt;x.Category)).ToList();     
    }
}&lt;/pre&gt;

&lt;p&gt;&lt;font color="#000000" size="2"&gt;will now properly serialize the data (All product entities and their related category entities) to JSON, including reference tracking. Again, pulling the data as XML by specifying application/xml in the Accept header element of the request will make things fail as WebAPI chooses a DataContract serializer by default if it sees a [DataContract] attribute on the objects to serialize. It might be configurable to have it choose to use the normal XmlSerializer instead, but I'm no WebAPI expert so I can't give you a heads-up on that. If you know whether this is possible, please leave a comment below :&lt;font size="2"&gt;)&lt;/font&gt; &lt;/font&gt;&lt;/p&gt;

&lt;p&gt;Hope this helps!&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=9049371" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=lk4yPQZo64c:38ZWn4zJ1AE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=lk4yPQZo64c:38ZWn4zJ1AE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=lk4yPQZo64c:38ZWn4zJ1AE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=lk4yPQZo64c:38ZWn4zJ1AE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=lk4yPQZo64c:38ZWn4zJ1AE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/lk4yPQZo64c" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/LLBLGen+Pro/default.aspx">LLBLGen Pro</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Advanced+.NET/default.aspx">Advanced .NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Code+generation/default.aspx">Code generation</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2012/10/05/how-to-make-asp-net-webapi-serialize-your-llblgen-pro-entities-to-json.aspx</feedburner:origLink></item><item><title>Re: Everything's broken and nobody's upset</title><link>http://feedproxy.google.com/~r/FransBouma/~3/mZW3vu78ZTk/re-everything-s-broken-and-nobody-s-upset.aspx</link><pubDate>Tue, 18 Sep 2012 08:19:55 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8938232</guid><dc:creator>FransBouma</dc:creator><slash:comments>8</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=8938232</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2012/09/18/re-everything-s-broken-and-nobody-s-upset.aspx#comments</comments><description>&lt;p&gt;This is a re-worked answer to &lt;a href="http://www.hanselman.com" target="_blank"&gt;Scott Hanselman&lt;/a&gt;'s great post '&lt;a href="http://www.hanselman.com/blog/EverythingsBrokenAndNobodysUpset.aspx" target="_blank"&gt;Everything's broken and nobody's upset&lt;/a&gt;'. I replied it below the post, but I think it deserves a post here. Scott's post is about how we seemingly accept a long list of annoyances and issues with the software we use and how we apparently ignore the fact just &lt;em&gt;how broken&lt;/em&gt; today's software seems to be. In my answer I tried to give an answer to why that is. This answer is below. &lt;/p&gt;  &lt;p&gt;I think a lot of the problems with today's software are simply allowed to show up in public because the dev teams of these software products aren't given the time to fix them: Time to Market is critical, marketing already reserved a given launch date for the product, things are already in motion and only the bugs in the category 'it kills kittens and old ladies' are fixed at that point, the rest is 'moved to a later date'. But that later date never comes, because after the product is done, the team moves on to the newer version with new stuff, and fixing bugs is dreadful work, new stuff is exciting. &lt;/p&gt;  &lt;p&gt;There's another thing about bugs which is also key in this issue: fixing them won't sell more licenses of vNext: people won't run to the store, yelling &amp;quot;OMG! They fixed bug 33422!!!1 I can't believe it!&amp;quot;. They'll run to the store because new, shiny things have been added, like a completely new UI with ergonomic characteristics of which no-one really knows whether it's actually a step forward. &lt;/p&gt;  &lt;p&gt;We, as software developers, all know software contains bugs, even though we did our best to fix them before RTM. But in the end, we have to admit that that label, 'RTM', is really just an arbitrary calendar event, not a landmark which says &amp;quot;0 bugs, It's ready!&amp;quot;. This means that even though something went RTM, it doesn't mean it's bug free, it simply means: &amp;quot;It's good enough that it won't kill kittens nor old ladies&amp;quot;. &lt;/p&gt;  &lt;p&gt;A wise man, who unfortunately passed away way too soon, once said to me: &amp;quot;Your motivation and ability to fix issues and bugs is part of the quality you want to provide&amp;quot;, which means: even though at first glance your software might look stunning out of the box, if that essential part of the quality of the software is missing, i.e. when a bug pops up it gets fixed, pronto, your software isn't of the quality you think it is. The insight given by this wise man opened my eyes all those years ago and I to this day still try to live up to it: stand for the quality you want to provide by giving customers the best support and software they could get. &lt;/p&gt;  &lt;p&gt;If I look at today's software development landscape, I see a tremendous amount of people trying to write applications without the necessary skills and knowledge, in languages and platforms which have had a bad track-record for years, yet no-one seems to care, or at least too little. Last year I was in an open spaces session and some guy explained that they would place people who just started programming as 'trainee' at customers for 'free' and after a few months these trainees became 'junior' programmers and the client had to pay a fee per hour. I asked him what he thought of the term 'fraud', and he didn't understand what I meant. I tried to explain to him that if you think a person who has no training at all and you let him 'learn on the job' for a few months, is suddenly able to write any form of software, you're delusional. He didn't get what I wanted to say, and how it was a bad thing that someone with no skills was placed at a client as if the person knew what he was doing. Shockingly, some others in the room agreed with him. &lt;/p&gt;  &lt;p&gt;But with the lack of highly trained professional developers growing and growing each day, more and more people who can tell the difference between a keyboard and a mouse are hired to do 'dev work', as the client doesn't know better and is already happy at least &lt;em&gt;someone&lt;/em&gt; is there to do the work. I fear it only gets worse in the coming years. Frankly, I'm starting to get fed up with the bullshit pseudo-devs who seem to pop up more and more every day, who cry 'I'm just learning, don't be so rude!' when you tell them their work pretty much doesn't cut it, while at the same time they try to keep up the charade that they're highly skilled and experienced. You're either a trainee and therefore your work can lack in areas, or you're a professional and you have to take responsibility for the quality you say you'll provide. &lt;/p&gt;  &lt;p&gt;Sadly this process of pseudo-devs which are seen as the true 'specialists', is in progress for some time now and will continue in the next decade I think. Let's hope they'll learn something about what 'quality' means with respect to software, that 'quality' is more than just the bits making up the software. But I'm not optimistic.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8938232" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=mZW3vu78ZTk:TvAokjuK5vk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=mZW3vu78ZTk:TvAokjuK5vk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=mZW3vu78ZTk:TvAokjuK5vk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=mZW3vu78ZTk:TvAokjuK5vk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=mZW3vu78ZTk:TvAokjuK5vk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/mZW3vu78ZTk" height="1" width="1"/&gt;</description><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2012/09/18/re-everything-s-broken-and-nobody-s-upset.aspx</feedburner:origLink></item><item><title>The Windows Store... why did I sign up with this mess again?</title><link>http://feedproxy.google.com/~r/FransBouma/~3/4PXT_izCg2k/the-windows-store-why-did-i-sign-up-with-this-mess-again.aspx</link><pubDate>Wed, 12 Sep 2012 14:36:27 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8913670</guid><dc:creator>FransBouma</dc:creator><slash:comments>16</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=8913670</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2012/09/12/the-windows-store-why-did-i-sign-up-with-this-mess-again.aspx#comments</comments><description>&lt;p&gt;Yesterday, &lt;a href="http://blogs.msdn.com/b/windowsstore/archive/2012/09/11/windows-store-now-open-to-all-developers.aspx" target="_blank"&gt;Microsoft revealed that the Windows Store&lt;/a&gt; is now open to all developers in a wide range of countries and locations. For the people who think &amp;quot;wtf is the 'Windows Store'?&amp;quot;, it's the central place where Windows 8 users will be able to find, download and purchase applications (or as we now have to say to not look like a computer illiterate: &amp;lt;accent style=&amp;quot;Kentucky&amp;quot;&amp;gt;aaaaappss&amp;lt;/accent&amp;gt;) for Windows 8. &lt;/p&gt;  &lt;p&gt;As this is the store which is integrated into Windows 8, it's an interesting place for ISVs, as potential customers might very well look there first. This of course isn't true for all kinds of software, and developer tools in general aren't the kind of applications most users will download from the Windows store, but a presence there can't hurt. &lt;/p&gt;  &lt;p&gt;Now, this Windows Store hosts two kinds of applications: 'Metro-style' applications and 'Desktop' applications. The 'Metro-style' applications are applications created for the new 'Metro' UI which is present on Windows 8 desktop and Windows RT (the single color/big font fingerpaint-oriented UI). 'Desktop' applications are the applications we all run and use on Windows today. Our software are desktop applications. The Windows Store hosts all Metro-style applications locally in the store and handles the payment for these applications. This means you upload your application (sorry, 'app') to the store, jump through a lot of hoops, Microsoft verifies that your application is not violating a tremendous long list of rules and after everything is OK, it's published and hopefully you get customers and thus earn money. Money which Microsoft will pay you on a regular basis after customers buy your application. &lt;/p&gt;  &lt;p&gt;Desktop applications are not following this path however. Desktop applications aren't hosted by the Windows Store. Instead, the Windows Store more or less hosts a page with the application's information and where to get the goods. I.o.w.: it's nothing more than a product's &lt;a href="https://www.facebook.com/LLBLGenPro" target="_blank"&gt;Facebook page&lt;/a&gt;. Microsoft will simply redirect a visitor of the Windows Store to your website and the visitor will then use your site's system to purchase and download the application. This last bit of information is very important. &lt;/p&gt;  &lt;p&gt;So, this morning I started with fresh energy to register our company 'Solutions Design bv' at the Windows Store and our two applications, &lt;a href="http://www.llblgen.com" target="_blank"&gt;LLBLGen Pro&lt;/a&gt; and &lt;a href="http://www.ormprofiler.com" target="_blank"&gt;ORM Profiler&lt;/a&gt;. First I went to the &lt;a href="https://appdev.microsoft.com/StorePortals/" target="_blank"&gt;Windows Store dashboard page&lt;/a&gt;. If you don't have an account, you have to log in or sign up if you don't have a live account. I signed in with my live account. After that, it greeted me with a page where I had to fill in a code which was mailed to me. My local mail server polls every several minutes for email so I had to kick it to get it immediately. &lt;/p&gt;  &lt;p&gt;I grabbed the code from the email and I was presented with a multi-step process to register myself as a company or as an individual. In red I was warned that this choice was permanent and not changeable. I chuckled: Microsoft apparently stores its data on paper, not in digital form. I chose 'company' and was presented with a lengthy form to fill out. On the form there were two strange remarks:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;font color="#000000"&gt;Per company there can just be 1 (one, uno, not zero, not two or more) registered developer, and only that developer is able to upload stuff to the store. I have no idea how this works with large companies, oh the overhead nightmares... &amp;quot;Sorry, but John, our registered developer with the Windows Store is on holiday for 3 months, backpacking through Australia, no, he's not reachable at this point. M'yeah, sorry bud. Hey, did you fill in those TPS reports yesterday?&amp;quot;&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;&lt;font color="#000000"&gt;A separate &lt;em&gt;Approver&lt;/em&gt; has to be specified, which has to be a different person than the registered developer. Apparently to Microsoft a company with just 1 person is not a company. Luckily we're with two people! *pfew*, dodged that one, otherwise I would be stuck forever: the choice I already made was not reversible!&lt;/font&gt;&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;After I had filled out the form and it was all well and good and accepted by the Microsoft lackey who had to write it all down in some paper notebook (&amp;quot;Hey, be warned! It's a permanent choice! Written down in ink, can't be changed!&amp;quot;), I was presented with the question how I wanted to pay for all this. &amp;quot;Pay for what?&amp;quot; I wondered. Must be the paper they were scribbling the information on, I concluded. After all, there's a financial crisis going on! How could I forget! Silly me.&lt;/p&gt;  &lt;p&gt;&amp;quot;Ok fair enough&amp;quot;. &lt;/p&gt;  &lt;p&gt;The price was 75 Euros, not the end of the world. I could only pay by credit card, so it was accepted quickly. Or so I thought. You see, Microsoft has a different idea about CC payments. In the normal world, you type in your CC number, some date, a name and a security code and that's it. But Microsoft wants to verify this even more. They want to make a verification purchase of a very small amount and are doing that with a special code in the description. You then have to type in that code in a special form in the Windows Store dashboard and after that you're verified. Of course they'll refund the small amount they pull from your card. &lt;/p&gt;  &lt;p&gt;Sounds simple, right? Well... no. The problem starts with the fact that I can't see the CC activity on some website: I have a bank issued CC card. I get the CC activity once a month on a piece of paper sent to me. The bank's online website doesn't show them. So it's possible I have to wait for this code till October 12th. One &lt;strong&gt;month&lt;/strong&gt;. &lt;/p&gt;  &lt;p&gt;&amp;quot;So what, I'm not going to use it anyway, Desktop applications don't use the payment system&amp;quot;, I thought. &amp;quot;Haha, you're so naive, dear developer!&amp;quot; Microsoft won't allow you to publish any applications till this verification is done. So no application publishing for a month. Wouldn't it be nice if things were, you know, digital, so things got done instantly? But of course, that lackey who scribbled everything in the Big Windows Store Registration Book isn't that quick. Can't blame him though. He's just doing his job. &lt;/p&gt;  &lt;p&gt;Now, after the payment was done, I was presented with a page which tells me Microsoft is going to use a third party company called 'Symantec', which will verify my identity again. The page explains to me that this could be done through email or phone and that they'll contact the Approver to verify my identity. &amp;quot;Phone?&amp;quot;, I thought... that's a little drastic for a developer account to publish a single page of information about an external hosted software product, isn't it? On Facebook I just added a page, done. And paying you, Microsoft, took &lt;em&gt;less &lt;/em&gt;information: you were happy to take my money &lt;em&gt;before&lt;/em&gt; my identity was even 'verified' by this 3rd party's minions! &amp;quot;Double standards!&amp;quot;, I roared. No-one cared. But it's the thought of getting it off your chest, you know. &lt;/p&gt;  &lt;p&gt;Luckily for me, everyone at Symantec was asleep when I was registering so they went for the fallback option in case phone calls were not possible: my Approver received an email. Imagine you have to explain the idiot web of security theater I was caught in to someone else who then has to reply a random person over the internet that I indeed was who I said I was. As she's a true sweetheart, she gave me the benefit of the doubt and assured that for now, I was who I said I was. &lt;/p&gt;  &lt;p&gt;Remember, this is for a desktop application, which is only a &lt;em&gt;link&lt;/em&gt; to a website, some pictures and a piece of text. No file hosting, no payment processing, nothing, just a single page. Yeah, I also thought I was crazy. But we're not at the end of this quest yet. &lt;/p&gt;  &lt;p&gt;I clicked around in the confusing menus of the Windows Store dashboard and found the 'Desktop' section. I get a helpful screen with a warning in red that it can't find any certified 'apps'. True, I'm just getting started, buddy. I see a link: &amp;quot;Check the Windows apps you submitted for certification&amp;quot;. Well, I haven't submitted anything, but let's see where it brings me. Oh the thrill of adventure!&lt;/p&gt;  &lt;p&gt;I click the link and I end up on this site: &lt;a href="https://sysdev.microsoft.com/en-US/desktop/signup/" target="_blank"&gt;the hardware/desktop dashboard account registration&lt;/a&gt;. &amp;quot;Erm... but I just registered...&amp;quot;, I mumbled to no-one in particular. Apparently for desktop registration / verification I have to register again, it tells me. But not only that, the desktop application has to be signed with a certificate. And not just some random el-cheapo certificate you can get at any mall's discount store. No, this certificate is special. It's precious. This certificate, the 'Microsoft Authenticode' Digital Certificate, is the only certificate that's acceptable, and jolly, it can be purchased from VeriSign for the price of only ... $99.-, but be quick, because this is a limited time offer! After that it's, I kid you not, $499.-. 500 dollars for a certificate to sign an executable. But, I do feel special, I got a special price. Only for me! I'm glowing. Not for long though. &lt;/p&gt;  &lt;p&gt;Here I started to wonder, what the benefit of it all was. I now again had to pay money for a shiny certificate which will add 'Solutions Design bv' to our installer as the publisher instead of 'unknown', while our customers download the file from our website. Not only that, but this was all about a &lt;strong&gt;Desktop&lt;/strong&gt; application, which wasn't hosted by Microsoft. They only link to it. And make no mistake. These prices aren't single payments. Every year these have to be renewed. Like a membership of an exclusive club: you're special and privileged, but only if you cough up the dough. &lt;/p&gt;  &lt;p&gt;To give you an example how silly this all is: I added LLBLGen Pro and ORM Profiler to the Visual Studio Gallery some time ago. It's the same thing: it's a central place where one can find software which adds to / extends / works with Visual Studio. I could simply create the pages, add the information and they show up inside Visual Studio. No files are hosted at Microsoft, they're downloaded from our website. Exactly the same system. &lt;/p&gt;  &lt;p&gt;As I have to wait for the CC transcripts to arrive anyway, I can't proceed with publishing in this new shiny store. After the verification is complete I have to wait for verification of my software by Microsoft. Even Desktop applications need to be verified using a long list of rules which are mainly focused on Metro-style applications. Even while they're not hosted by Microsoft. I wonder what they'll find. &amp;quot;Your application wasn't approved. It violates rule 14 X sub D: it provides more value than our own competing framework&amp;quot;.&lt;/p&gt;  &lt;p&gt;While I was writing this post, I tried to check something in the Windows Store Dashboard, to see whether I remembered it correctly. I was presented again with the question, after logging in with my live account, to enter the code that was just mailed to me. Not the previous code, a brand new one. Again I had to kick my mail server to pull the email to proceed. This was it. This 'experience' is so beyond miserable, I'm afraid I have to say goodbye for now to the 'Windows Store'. It's simply not worth my time. &lt;/p&gt;  &lt;p&gt;Now, about live accounts. You might know this: live accounts are tied to everything you do with Microsoft. So if you have an MSDN subscription, e.g. the one which costs over $5000.-, it's tied to this same live account. But the fun thing is, you can login with your live account to the MSDN subscriptions with just the account id and password. No additional code is mailed to you. While it gives you access to all Microsoft software available, including your licenses. &lt;/p&gt;  &lt;p&gt;Why the draconian security theater with this Windows Store, while all I want is to publish some &lt;em&gt;desktop &lt;/em&gt;applications while on other Microsoft sites it's OK to simply sign in with your live account: no codes needed, no verification and no certificates? Microsoft, one thing you need with this store and that's: apps. Apps, apps, apps, apps, aaaaaaaaapps. Sorry, my bad, got carried away. I just can't stand the word 'app'. This store's shelves have to be filled to the brim with goods. But instead of being welcomed into the store with open arms, I have to fight an uphill battle with an endless list of rules and bullshit to earn the privilege to publish in this shiny store. As if I have to be thrilled to be one of the exclusive club called 'Windows Store Publishers'. As if Microsoft doesn't want it to succeed. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.teamb.com/craigstuntz" target="_blank"&gt;Craig Stuntz&lt;/a&gt; sent me a link to an old blog post of his regarding code signing and uploading to Microsoft's old mobile store from back in the WinMo5 days: &lt;a title="http://blogs.teamb.com/craigstuntz/2006/10/11/28357/" href="http://blogs.teamb.com/craigstuntz/2006/10/11/28357/"&gt;http://blogs.teamb.com/craigstuntz/2006/10/11/28357/&lt;/a&gt;. Good read and good background info about how little things changed over the years. &lt;/p&gt;  &lt;p&gt;I hope this helps Microsoft make things more clearer and smoother and also helps ISVs with their decision whether to go with the Windows Store scheme or ignore it. For now, I don't see the advantage of publishing there, especially not with the nonsense rules Microsoft cooked up. Perhaps it changes in the future, who knows. &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8913670" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=4PXT_izCg2k:6jOXIiXBv28:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=4PXT_izCg2k:6jOXIiXBv28:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=4PXT_izCg2k:6jOXIiXBv28:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=4PXT_izCg2k:6jOXIiXBv28:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=4PXT_izCg2k:6jOXIiXBv28:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/4PXT_izCg2k" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET+General/default.aspx">.NET General</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Software+Engineering/default.aspx">Software Engineering</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/LLBLGen+Pro/default.aspx">LLBLGen Pro</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/General+Software+Development/default.aspx">General Software Development</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Community+News/default.aspx">Community News</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/ORM+Profiler/default.aspx">ORM Profiler</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2012/09/12/the-windows-store-why-did-i-sign-up-with-this-mess-again.aspx</feedburner:origLink></item><item><title>LLBLGen Pro feature highlights: model views</title><link>http://feedproxy.google.com/~r/FransBouma/~3/4bI34cWqoyY/llblgen-pro-feature-highlights-model-views.aspx</link><pubDate>Fri, 31 Aug 2012 10:38:11 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8881362</guid><dc:creator>FransBouma</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=8881362</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2012/08/31/llblgen-pro-feature-highlights-model-views.aspx#comments</comments><description>&lt;p&gt;(This post is part of a series of posts about features of the &lt;a href="http://www.llblgen.com"&gt;LLBLGen Pro&lt;/a&gt; system)&lt;/p&gt;  &lt;p&gt;To be able to work with large(r) models, it's key you can view subsets of these models so you can have a better, more focused look at them. For example because you want to display how a subset of entities relate to one another in a different way than the list of entities. LLBLGen Pro offers this in the form of &lt;em&gt;&lt;a href="http://www.llblgen.com/documentation/3.5/Designer/hh_goto.htm#Functionality%20Reference/ModelViewEditor.htm" target="_blank"&gt;Model Views&lt;/a&gt;&lt;/em&gt;. Model Views are views on parts of the entity model of a project, and the subsets are displayed in a graphical way. &lt;/p&gt;  &lt;p&gt;Additionally, one can add documentation to a Model View. As Model Views are displaying parts of the model in a graphical way, they're easier to explain to people who aren't familiar with entity models, e.g. the stakeholders you're interviewing for your project. The documentation can then be used to communicate specifics of the elements on the model view to the developers who have to write the actual code. &lt;/p&gt;  &lt;p&gt;Below I've included an example. It's a model view on a subset of the entities of AdventureWorks. It displays several entities, their relationships (both relational and inheritance relationships) and also some specifics gathered from the interview with the stakeholder. As the information is &lt;em&gt;inside&lt;/em&gt; the actual project the developer will work with, the information doesn't have to be converted back/from e.g .word documents or other intermediate formats, it's the &lt;em&gt;same&lt;/em&gt; project. This makes sure there are less errors / misunderstandings. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.xs4all.nl/~perseus/sshots/llblgenpro_modelview.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" border="0" alt="llblgenpro_modelview" src="http://weblogs.asp.net/blogs/fbouma/WindowsLiveWriter/LLBLGenProfeaturehighlightsmodelviews_B1A8/llblgenpro_modelview_thumb.png" width="640" height="456" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;(of course you can hide the docked documentation pane or dock it to another corner). &lt;/p&gt;  &lt;p&gt;The Model View can contain entities which are placed in &lt;a href="http://weblogs.asp.net/fbouma/archive/2012/06/20/llblgen-pro-feature-highlights-grouping-model-elements.aspx" target="_blank"&gt;different groups&lt;/a&gt;. This makes it ideal to group entities together for close examination even though they're stored in different groups. &lt;/p&gt;  &lt;p&gt;The Model View is a first-class citizen of the code-generator. This means you can write templates which consume Model Views and generate code accordingly. E.g. you can write a template which generates a service per Model View and exposes the entities in the Model View as a single entity graph, fetched through a method. (This template isn't included in the LLBLGen Pro package, but it's easy to write it up yourself with the built-in template editor). &lt;/p&gt;  &lt;p&gt;Viewing an entity model in different ways is key to fully understand the entity model and Model Views help with that. &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8881362" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=4bI34cWqoyY:karEPs9zRaU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=4bI34cWqoyY:karEPs9zRaU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=4bI34cWqoyY:karEPs9zRaU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=4bI34cWqoyY:karEPs9zRaU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=4bI34cWqoyY:karEPs9zRaU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/4bI34cWqoyY" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/Database+_2F00_+SQL+Server/default.aspx">Database / SQL Server</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Software+Engineering/default.aspx">Software Engineering</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/LLBLGen+Pro/default.aspx">LLBLGen Pro</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/O_2F00_R+Mapping/default.aspx">O/R Mapping</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/General+Software+Development/default.aspx">General Software Development</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Code+generation/default.aspx">Code generation</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2012/08/31/llblgen-pro-feature-highlights-model-views.aspx</feedburner:origLink></item><item><title>Beware when using .NET's named pipes in a windows forms application</title><link>http://feedproxy.google.com/~r/FransBouma/~3/mTqbpiERRhY/beware-when-using-net-s-named-pipes-in-a-windows-forms-application.aspx</link><pubDate>Tue, 28 Aug 2012 17:08:47 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8874768</guid><dc:creator>FransBouma</dc:creator><slash:comments>3</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=8874768</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2012/08/28/beware-when-using-net-s-named-pipes-in-a-windows-forms-application.aspx#comments</comments><description>&lt;p&gt;Yesterday a user of our .net &lt;a href="http://www.ormprofiler.com" target="_blank"&gt;ORM Profiler&lt;/a&gt; tool reported that he couldn't get the snapshot recording from code feature working in a windows forms application. Snapshot recording in code means you start recording profile data from within the profiled application, and after you're done you save the snapshot as a file which you can open in the profiler UI. When using a console application it worked, but when a windows forms application was used, the snapshot was always empty: nothing was recorded. &lt;/p&gt;  &lt;p&gt;Obviously, I wondered why that was, and debugged a little. Here's an example piece of code to record the snapshot. This piece of code works OK in a console application, but results in an empty snapshot in a windows forms application:&lt;/p&gt;  &lt;pre class="c#" name="code"&gt;var snapshot = new Snapshot();
snapshot.Record();
using(var ctx = new ORMProfilerTestDataContext())
{
	var customers = ctx.Customers.Where(c =&amp;gt; c.Country == &amp;quot;USA&amp;quot;).ToList();
}
InterceptorCore.Flush();
snapshot.Stop();
string error=string.Empty;
if(!snapshot.IsEmpty)
{
	snapshot.SaveToFile(@&amp;quot;c:\temp\generatortest\test2\blaat.opsnapshot&amp;quot;, out error);
}
if(!string.IsNullOrEmpty(error))
{
	Console.WriteLine(&amp;quot;Save error: {0}&amp;quot;, error);
}&lt;/pre&gt;

&lt;p&gt;&lt;font color="#000000" size="2"&gt;(the Console.WriteLine doesn't do anything in a windows forms application, but you get the idea).&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;ORM Profiler uses named pipes: the interceptor (referenced and initialized in your application, the application to profile) sends data over the named pipe to a listener, which when receiving a piece of data begins reading it, asynchronically, and when properly read, it will signal observers that new data has arrived so they can store it in a repository. In this case, the snapshot will be the observer and will store the data in its own repository. &lt;/p&gt;

&lt;p&gt;The reason the above code doesn't work in windows forms is because windows forms is a wrapper around Win32 and its WM_* message based system. Named pipes in .NET are wrappers around Windows named pipes which also work with WM_* messages. Even though we use BeginRead() on the named pipe (which spawns a thread to read the data from the named pipe), nothing is received by the named pipe in the windows forms application, because it doesn't handle the WM_* messages in its message queue till after the method is over, as the message pump of a windows forms application is handled by the only thread of the windows forms application, so it will handle WM_* messages when the application idles. &lt;/p&gt;

&lt;p&gt;The fix is easy though: add Application.DoEvents(); right before snapshot.Stop(). Application.DoEvents() forces the windows forms application to process all WM_* messages in its message queue at that moment: all messages for the named pipe are then handled, the .NET code of the named pipe wrapper will react on that and the whole process will complete as if nothing happened. &lt;/p&gt;

&lt;p&gt;It's not that simple to just say 'why didn't you use a worker thread to create the snapshot here?', because a thread doesn't get its own message pump: the messages would still be posted to the window's message pump. A hidden form would create its own message pump, so the additional thread should also create a window to get the WM_* messages of the named pipe posted to a different message pump than the one of the main window. &lt;/p&gt;

&lt;p&gt;This WM_* messages pain is not something you want to be confronted with when using .NET and its libraries. Unfortunately, the way they're implemented, a lot of APIs are leaky abstractions, they bleed the characteristics of the OS objects they hide away through to the .NET code. Be aware of that fact when using them :)&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8874768" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=mTqbpiERRhY:-dtGt6By4WE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=mTqbpiERRhY:-dtGt6By4WE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=mTqbpiERRhY:-dtGt6By4WE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=mTqbpiERRhY:-dtGt6By4WE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=mTqbpiERRhY:-dtGt6By4WE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/mTqbpiERRhY" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/WinForms/default.aspx">WinForms</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Advanced+.NET/default.aspx">Advanced .NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Windows+Forms/default.aspx">Windows Forms</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/General+Software+Development/default.aspx">General Software Development</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2012/08/28/beware-when-using-net-s-named-pipes-in-a-windows-forms-application.aspx</feedburner:origLink></item><item><title>LLBLGen Pro feature highlights: grouping model elements</title><link>http://feedproxy.google.com/~r/FransBouma/~3/1FxTa3IeiT8/llblgen-pro-feature-highlights-grouping-model-elements.aspx</link><pubDate>Wed, 20 Jun 2012 10:59:02 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8624997</guid><dc:creator>FransBouma</dc:creator><slash:comments>4</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=8624997</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2012/06/20/llblgen-pro-feature-highlights-grouping-model-elements.aspx#comments</comments><description>&lt;p&gt;(This post is part of a series of posts about features of the &lt;a href="http://www.llblgen.com"&gt;LLBLGen Pro&lt;/a&gt; system)&lt;/p&gt;  &lt;p&gt;When working with an entity model which has more than a few entities, it's often convenient to be able to &lt;em&gt;group&lt;/em&gt; entities together if they belong to a semantic sub-model. For example, if your entity model has several entities which are about 'security', it would be practical to group them together under the 'security' moniker. This way, you could easily find them back, yet they can be left inside the complete entity model altogether so their relationships with entities outside the &lt;em&gt;group&lt;/em&gt; are kept.&lt;/p&gt;  &lt;p&gt;In other situations your domain consists of semi-separate entity models which all target tables/views which are located in the same database. It then might be convenient to have a single project to manage the complete target database, yet have the entity models separate of each other and have them result in separate code bases. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.llblgen.com" target="_blank"&gt;LLBLGen Pro&lt;/a&gt; can do both for you. This blog post will illustrate both situations. The feature is called &lt;em&gt;group usage&lt;/em&gt; and is controllable through the project settings. This setting is supported on all supported O/R mapper frameworks.&lt;/p&gt;  &lt;h4&gt;Situation one: grouping entities in a single model.&lt;/h4&gt;  &lt;p&gt;This situation is common for entity models which are &lt;em&gt;dense&lt;/em&gt;, so many relationships exist between all sub-models: you can't split them up easily into separate models (nor do you likely want to), however it's convenient to have them &lt;em&gt;grouped&lt;/em&gt; together into groups inside the entity model at the project level. A typical example for this is the AdventureWorks example database for SQL Server. This database, which is a single catalog, has for each sub-group a schema, however most of these schemas are tightly connected with each other: adding all schemas together will give a model with entities which indirectly are related to all other entities. LLBLGen Pro's default setting for &lt;em&gt;group usage &lt;/em&gt;is &lt;em&gt;AsVisualGroupingMechanism&lt;/em&gt; which is what this situation is all about: we group the elements for visual purposes, it has no real meaning for the model nor the code generated.&lt;/p&gt;  &lt;p&gt;Let's reverse engineer AdventureWorks to an entity model. By default, &lt;a href="http://www.llblgen.com" target="_blank"&gt;LLBLGen Pro&lt;/a&gt; uses the target schema an element is in which is being reverse engineered, as the group it will be in. This is convenient if you already have categorized tables/views in schemas, like which is the case in AdventureWorks. Of course this can be switched off, or corrected on the fly. &lt;/p&gt;  &lt;p&gt;When reverse engineering, we'll walk through a wizard which will guide us with the selection of the elements which relational model data should be retrieved, which we can later on use to reverse engineer to an entity model. The first step after specifying which database server connect to is to select these elements. below we can see the AdventureWorks catalog as well as the different schemas it contains. We'll include all of them. &lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="Relational model data retrieval wizard." src="http://weblogs.asp.net/blogs/fbouma/WindowsLiveWriter/LLBLGenProfeaturehighlightsgroupingmodel_ABCC/sshot_%5B2%5D_3.png" width="615" height="527" /&gt; &lt;/p&gt;  &lt;p&gt;After the wizard completes, we have all relational model data nicely in our catalog data, with schemas. So let's reverse engineer entities from the tables in these schemas. We select in the &lt;em&gt;catalog explorer&lt;/em&gt; the schemas 'HumanResources', 'Person', 'Production', 'Purchasing' and 'Sales', then right-click one of them and from the context menu, we select &lt;em&gt;Reverse engineer Tables to Entity Definitions...&lt;/em&gt;. This will bring up the dialog below. We check all checkboxes in one go by checking the checkbox at the top to mark them all to be added to the project. &lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="sshot_[3]" src="http://weblogs.asp.net/blogs/fbouma/WindowsLiveWriter/LLBLGenProfeaturehighlightsgroupingmodel_ABCC/sshot_%5B3%5D_3.png" width="711" height="588" /&gt; &lt;/p&gt;  &lt;p&gt;As you can see &lt;a href="http://www.llblgen.com" target="_blank"&gt;LLBLGen Pro&lt;/a&gt; has already filled in the group name based on the schema name, as this is the default and we didn't change the setting. If you want, you can select multiple rows at once and set the group name to something else using the controls on the dialog. We're fine with the group names chosen so we'll simply click &lt;em&gt;Add to Project&lt;/em&gt;. This gives the following result:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="sshot_[6]" src="http://weblogs.asp.net/blogs/fbouma/WindowsLiveWriter/LLBLGenProfeaturehighlightsgroupingmodel_ABCC/sshot_%5B6%5D_3.png" width="351" height="360" /&gt; &lt;/p&gt;  &lt;p&gt;(I collapsed the other groups to keep the picture small ;)). As you can see, the entities are now grouped. Just to see how dense this model is, I've expanded the relationships of Employee: &lt;/p&gt;  &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/fbouma/WindowsLiveWriter/LLBLGenProfeaturehighlightsgroupingmodel_ABCC/sshot_%5B7%5D_2.png"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="sshot_[7]" src="http://weblogs.asp.net/blogs/fbouma/WindowsLiveWriter/LLBLGenProfeaturehighlightsgroupingmodel_ABCC/sshot_%5B7%5D_thumb.png" width="720" height="275" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;As you can see, it has relationships with entities from three other groups than &lt;em&gt;HumanResources&lt;/em&gt;. It's not doable to cut up this project into sub-models without duplicating the &lt;em&gt;Employee&lt;/em&gt; entity in all those groups, so this model is better suited to be used as a single model resulting in a single code base, however it benefits greatly from having its entities grouped into separate groups at the project level, to make work done on the model easier. &lt;/p&gt;  &lt;p&gt;Now let's look at another situation, namely where we work with a single database while we want to have multiple models and for each model a separate code base. &lt;/p&gt;  &lt;h4&gt;Situation two: grouping entities in separate models within the same project.&lt;/h4&gt;  &lt;p&gt;To get rid of the entities to see the second situation in action, simply undo the reverse engineering action in the project. We still have the AdventureWorks relational model data in the catalog. To switch LLBLGen Pro to see each group in the project as a separate project, open the Project Settings, navigate to &lt;em&gt;General&lt;/em&gt; and set &lt;em&gt;Group usage&lt;/em&gt; to &lt;em&gt;AsSeparateProjects&lt;/em&gt;. &lt;/p&gt;  &lt;p&gt;In the catalog explorer, select &lt;em&gt;Person &lt;/em&gt;and &lt;em&gt;Production, &lt;/em&gt;right-click them and select again &lt;em&gt;Reverse engineer Tables to Entities&lt;/em&gt;.... Again check the checkbox at the top to mark all entities to be added and click &lt;em&gt;Add to Project&lt;/em&gt;. We get two groups, as expected, however this time the groups are seen as separate projects. This means that the validation logic inside LLBLGen Pro will see it as an error if there's e.g. a relationship or an inheritance edge linking two groups together, as that would lead to a cyclic reference in the code bases. &lt;/p&gt;  &lt;p&gt;To see this variant of the grouping feature, seeing the groups as separate projects, in action, we'll generate code from the project with the two groups we just created: select from the main menu: &lt;em&gt;Project -&amp;gt; Generate Source-code...&lt;/em&gt; (or press F7 ;)). In the dialog popping up, select the target .NET framework you want to use, the template preset, fill in a destination folder and click &lt;em&gt;Start Generator (normal)&lt;/em&gt;. This will start the code generator process. &lt;/p&gt;  &lt;p&gt;As expected the code generator has simply generated two code bases, one for &lt;em&gt;Person&lt;/em&gt; and one for &lt;em&gt;Production&lt;/em&gt;:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="sshot_[8]" src="http://weblogs.asp.net/blogs/fbouma/WindowsLiveWriter/LLBLGenProfeaturehighlightsgroupingmodel_ABCC/sshot_%5B8%5D_3.png" width="462" height="188" /&gt; &lt;/p&gt;  &lt;p&gt;The &lt;em&gt;group name&lt;/em&gt; is used inside the namespace for the different elements. This allows you to add both code bases to a single solution and use them together in a different project without problems. Below is a snippet from the code file of a generated entity class. &lt;/p&gt;  &lt;pre class="c#" name="code"&gt;//...
using System.Xml.Serialization;
using AdventureWorks.Person;
using AdventureWorks.Person.HelperClasses;
using AdventureWorks.Person.FactoryClasses;
using AdventureWorks.Person.RelationClasses;
using SD.LLBLGen.Pro.ORMSupportClasses;

namespace AdventureWorks.Person.EntityClasses
{    
//...
	/// &amp;lt;summary&amp;gt;Entity class which represents the entity 'Address'.&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;/summary&amp;gt;
	[Serializable]    
	public partial class AddressEntity : CommonEntityBase
//...&lt;/pre&gt;

&lt;p&gt;The advantage of this is that you can have two code bases and work with them separately, yet have a single target database and maintain everything in a single location. If you decide to move to a single code base, you can do so with a change of one setting. It's also useful if you want to keep the groups as separate models (and code bases) yet want to add relationships to elements from another group using a copy of the entity: you can simply reverse engineer the target table to a new entity into a different group, effectively making a copy of the entity. As there's a single target database, changes made to that database are reflected in both models which makes maintenance easier than when you'd have a separate project for each group, with its own relational model data. &lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://www.llblgen.com" target="_blank"&gt;LLBLGen Pro&lt;/a&gt; offers a flexible way to work with entities in sub-models and control how the sub-models end up in the generated code. &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8624997" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=1FxTa3IeiT8:hC3rzNfMBZw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=1FxTa3IeiT8:hC3rzNfMBZw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=1FxTa3IeiT8:hC3rzNfMBZw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=1FxTa3IeiT8:hC3rzNfMBZw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=1FxTa3IeiT8:hC3rzNfMBZw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/1FxTa3IeiT8" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET+General/default.aspx">.NET General</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Database+_2F00_+SQL+Server/default.aspx">Database / SQL Server</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Software+Engineering/default.aspx">Software Engineering</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/LLBLGen+Pro/default.aspx">LLBLGen Pro</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/O_2F00_R+Mapping/default.aspx">O/R Mapping</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Advanced+.NET/default.aspx">Advanced .NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Code+generation/default.aspx">Code generation</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/entity+framework/default.aspx">entity framework</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2012/06/20/llblgen-pro-feature-highlights-grouping-model-elements.aspx</feedburner:origLink></item><item><title>Azure, don't give me multiple VMs, give me one elastic VM</title><link>http://feedproxy.google.com/~r/FransBouma/~3/IXvQr-5tkAA/azure-don-t-give-me-multiple-vms-give-me-one-elastic-vm.aspx</link><pubDate>Fri, 08 Jun 2012 09:51:54 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8584085</guid><dc:creator>FransBouma</dc:creator><slash:comments>8</slash:comments><wfw:commentRss>http://weblogs.asp.net/fbouma/rsscomments.aspx?PostID=8584085</wfw:commentRss><comments>http://weblogs.asp.net/fbouma/archive/2012/06/08/azure-don-t-give-me-multiple-vms-give-me-one-elastic-vm.aspx#comments</comments><description>&lt;p&gt;Yesterday, Microsoft revealed new major features for Windows Azure (see &lt;a href="http://weblogs.asp.net/scottgu/archive/2012/06/07/meet-the-new-windows-azure.aspx" target="_blank"&gt;ScottGu's post&lt;/a&gt;). It all looks shiny and great, but after reading most of the material describing the new features, I still find the overall idea behind all of it flawed: why should I care on how much VMs my web app runs? Isn't that a problem to solve for the Windows Azure engineers / software? And what if I need the file system, why can't I simply get a virtual filesystem ? &lt;/p&gt;  &lt;p&gt;To illustrate my point, let's use a real example: a product website with a customer system/database and next to it a support site with accompanying database. Both are written in .NET, using ASP.NET and use a SQL Server database each. The product website offers files to download by customers, very simple. &lt;/p&gt;  &lt;p&gt;You have a couple of options to host these websites:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;font color="#000000"&gt;Buy a server, place it in a rack at an ISP and run the sites on that server&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;&lt;font color="#000000"&gt;Use 'shared hosting' with an ISP, which means your sites' appdomains are running on the same machine, as well as the files stored, and the databases are hosted in the same server as the other shared databases. &lt;/font&gt;&lt;/li&gt;    &lt;li&gt;&lt;font color="#000000"&gt;Hire a VM, install your OS of choice at an ISP, and host the sites on that VM, basically the same as the first option, except you don't have a physical server&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;&lt;font color="#000000"&gt;At some cloud-vendor, either host the sites 'shared' or in a VM. See above.&lt;/font&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;With all of those options, scalability is a problem, even the cloud-based ones, though not due to the same reasons:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;font color="#000000"&gt;The physical server solution has the obvious problem that if you need more power, you need to buy a bigger server or more servers which requires you to add replication and other overhead&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;&lt;font color="#000000"&gt;Shared hosting solutions are almost always capped on memory usage / traffic and database size: if your sites get too big, you have to move out of the shared hosting environment and start over with one of the other solutions&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;&lt;font color="#000000"&gt;The VM solution, be it a VM at an ISP or 'in the cloud' at e.g. Windows Azure or Amazon, in theory allows scaling out by simply instantiating more VMs, however that too introduces the same overhead problems as with the physical servers: suddenly more than 1 instance runs your sites. &lt;/font&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;If a cloud vendor offers its services in the form of VMs, you won't gain much over having a VM at some ISP: the main problems you have to work around are still there: when you spin up more than one VM, your application must be completely stateless at any moment, including the DB sub system, because what's in memory in instance 1 might not be in memory in instance 2. &lt;/p&gt;  &lt;p&gt;This might sounds trivial but it's not. A lot of the websites out there started rather small: they were perfectly runnable on a single machine with normal memory and CPU power. After all, you don't need a big machine to run a website with even thousands of users a day. Moving these sites to a multi-VM environment will cause a problem: all the in-memory state they use, all the multi-page transitions they use while keeping state across the transition, they can't do that anymore like they did that on a single machine: state is something of the past, you have to store every byte of state in either a DB or in a viewstate or in a cookie somewhere so with the next request, all state information is available through the request, as nothing is kept in-memory.&lt;/p&gt;  &lt;p&gt;Our example uses a bunch of files in a file system. Using multiple VMs will require that these files move to a cloud storage system which is mounted in each VM so we don't have to store the files on each VM. This might require different file paths, but this change should be minor. What's perhaps less minor is the maintenance procedure in place on the new type of cloud storage used: instead of ftp-ing into a VM, you might have to update the files using different ways / tools. &lt;/p&gt;  &lt;p&gt;All in all this makes moving an existing website which was written for an environment that's based around a VM (namely .NET with its CLR) overly cumbersome and problematic: it forces you to refactor your website system to be able to be used 'in the cloud', which is caused by the limited way how e.g. Windows Azure offers its cloud services: in blocks of VMs. &lt;/p&gt;  &lt;h4&gt;Offer a scalable, flexible VM which extends with my needs&lt;/h4&gt;  &lt;p&gt;Instead, cloud vendors should offer simply &lt;em&gt;one&lt;/em&gt; VM to me. On that VM I run the websites, store my DB and my files. As it's a &lt;em&gt;virtual&lt;/em&gt; machine, how this machine is actually ran on physical hardware (e.g. partitioned), I don't care, as that's the problem for the cloud vendor to solve. If I need more resources, e.g. I have more traffic to my server, way more visitors per day, the VM stretches, like I bought a bigger box. This frees me from the problem which comes with multiple VMs: I don't have any refactoring to do at all: I can simply build my website as if it runs on my local hardware server, upload it to the VM offered by the cloud vendor, install it on the VM and I'm done. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;quot;But that might require changes to windows!&amp;quot;&lt;/strong&gt;    &lt;br /&gt;Yes, but Microsoft &lt;em&gt;is &lt;/em&gt;Windows. Windows Azure is their service, they can make whatever change to what they offer to make it look like it's windows. Yet, they're stuck, like Amazon, in thinking in VMs, which forces developers to 'think ahead' and gamble whether they would need to migrate to a cloud with multiple VMs in the future or not. Which comes down to: gamble whether they should invest time in code / architecture which they might never need. (YAGNI anyone?)&lt;/p&gt;  &lt;p&gt;So the VM we're talking about, is that a low-level VM which runs a guest OS, or is that VM a different kind of VM? &lt;/p&gt;  &lt;h4&gt;The flexible VM: .NET's CLR ?&lt;/h4&gt;  &lt;p&gt;My example websites are ASP.NET based, which means they run inside a .NET appdomain, on the .NET CLR, which is a VM. The only physical OS resource the sites need is the file system, however this too is accessed through .NET. In short: all the websites see is what .NET allows the websites to see, the world as the websites know it is what .NET shows them and lets them access. How the .NET appdomain is run physically, that's the concern of .NET, not mine. This begs the question why Windows Azure doesn't offer virtual appdomains? Or better: .NET environments which look like one machine but could be physically multiple machines. &lt;/p&gt;  &lt;p&gt;In such an environment, no change has to be made to the websites to migrate them from a local machine or own server to the cloud to get proper scaling: the .NET VM will simply scale with the need: more memory needed, more CPU power needed, it stretches. What it offers to the application running inside the appdomain is simply increasing, but not fragmented: all resources are available to the application: this means that the problem of &lt;em&gt;how to scale&lt;/em&gt; is back to where it should be: with the cloud vendor. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;quot;Yeah, great, but what about the databases?&amp;quot;&lt;/strong&gt;    &lt;br /&gt;The .NET application communicates with the database server through a .NET ADO.NET provider. Where the database is located is not a problem of the appdomain: the ADO.NET provider has to solve that. I.o.w.: we can host the databases in an environment which offers itself as a single resource and is accessible through one connection string without replication overhead on the &lt;em&gt;outside&lt;/em&gt;, and use that environment inside the .NET VM as if it was a single DB. &lt;/p&gt;  &lt;h4&gt;But what about memory replication and other problems?&lt;/h4&gt;  &lt;p&gt;This environment isn't simple, at least not for the cloud vendor. But it &lt;em&gt;is&lt;/em&gt; simple for the customer who wants to run his sites in that cloud: no work needed. No refactoring needed of existing code. Upload it, run it. &lt;/p&gt;  &lt;p&gt;Perhaps I'm dreaming and what I described above isn't possible. Yet, I think if cloud vendors don't move into that direction, what they're offering isn't interesting: it doesn't solve a problem at all, it simply offers a way to instantiate more VMs with the guest OS of choice at the cost of me needing to refactor my website code so it can run in the straight jacket form factor dictated by the cloud vendor. &lt;/p&gt;  &lt;p&gt;Let's not kid ourselves here: most of us developers will never build a website which needs a truck load of VMs to run it: almost all websites created by developers can run on just a few VMs at most. Yet, the most expensive change is right at the start: moving from one to two VMs. As soon as you have refactored your website code to run across multiple VMs, adding another one is just as easy as clicking a mouse button. But that first step, that's the problem here and as it's right there at the beginning of scaling the website, it's particularly strange that cloud vendors refuse to solve that problem and leave it to the developers to solve that. &lt;/p&gt;  &lt;p&gt;Which makes migrating 'to the cloud' particularly expensive. &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8584085" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=IXvQr-5tkAA:ev5SOFz01tc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=IXvQr-5tkAA:ev5SOFz01tc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=IXvQr-5tkAA:ev5SOFz01tc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/FransBouma?a=IXvQr-5tkAA:ev5SOFz01tc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/FransBouma?i=IXvQr-5tkAA:ev5SOFz01tc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FransBouma/~4/IXvQr-5tkAA" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET+General/default.aspx">.NET General</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Database+_2F00_+SQL+Server/default.aspx">Database / SQL Server</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Software+Engineering/default.aspx">Software Engineering</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Advanced+.NET/default.aspx">Advanced .NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/fbouma/archive/tags/Azure/default.aspx">Azure</category><feedburner:origLink>http://weblogs.asp.net/fbouma/archive/2012/06/08/azure-don-t-give-me-multiple-vms-give-me-one-elastic-vm.aspx</feedburner:origLink></item></channel></rss>
