<?xml version="1.0" encoding="utf-8"?>
<feed xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom">
  <title>Static Void</title>
  <link rel="alternate" type="text/html" href="http://martinwilley.com/blog/" />
  <link rel="self" href="http://martinwilley.com/blog/SyndicationService.asmx/GetAtom" />
  <icon>favicon.ico</icon>
  <updated>2012-01-05T01:51:53.0417525-07:00</updated>
  <author>
    <name>Martin Willey</name>
  </author>
  <subtitle>What next?</subtitle>
  <id>http://martinwilley.com/blog/</id>
  <generator uri="http://dasblog.info/" version="2.3.9074.18820">DasBlog</generator>
  <entry>
    <title>Visual Studio 2010 - find TFS working directory</title>
    <link rel="alternate" type="text/html" href="http://martinwilley.com/blog/2012/01/05/VisualStudio2010FindTFSWorkingDirectory.aspx" />
    <id>http://martinwilley.com/blog/PermaLink,guid,70a11d6b-a7dd-47dd-803d-9c545b2adfeb.aspx</id>
    <published>2012-01-05T01:51:17.114-07:00</published>
    <updated>2012-01-05T01:51:53.0417525-07:00</updated>
    <category term="TFS" label="TFS" scheme="http://martinwilley.com/blog/CategoryView,category,TFS.aspx" />
    <category term="VS2010" label="VS2010" scheme="http://martinwilley.com/blog/CategoryView,category,VS2010.aspx" />
    <author>
      <name>Martin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <pre style="font-family:Consolas;color:black;background:white;">
          <span style="color:green;">
          </span>
          <span style="color:green;">//find the working folder for each TFS</span>
          <span style="color:blue;">var</span> projectCollections = <span style="color:#2b91af;">RegisteredTfsConnections</span>.GetProjectCollections(); <span style="color:blue;">foreach</span> (<span style="color:blue;">var</span> registeredProjectCollection <span style="color:blue;">in</span> projectCollections)
{     <span style="color:#2b91af;">Console</span>.WriteLine(<span style="color:#a31515;">"Project collection: </span><span style="color:mediumseagreen;">{0}</span><span style="color:#a31515;"> </span><span style="color:mediumseagreen;">{1}</span><span style="color:#a31515;">"</span>, 
<br />
registeredProjectCollection.Name, 
<br />
registeredProjectCollection.Uri.AbsoluteUri);     <span style="color:blue;">var</span> projectCollection =
        <span style="color:#2b91af;">TfsTeamProjectCollectionFactory</span>.GetTeamProjectCollection(registeredProjectCollection);
    <span style="color:blue;">var</span> versionControl = projectCollection.GetService&lt;<span style="color:#2b91af;">VersionControlServer</span>&gt;();
    <span style="color:green;">// get workspace</span>     <span style="color:blue;">var</span> workspace =
        versionControl.QueryWorkspaces(<span style="color:blue;">null</span>,
                System.Threading.<span style="color:#2b91af;">Thread</span>.CurrentPrincipal.Identity.Name,
                <span style="color:#2b91af;">Environment</span>.MachineName)
                .FirstOrDefault(x =&gt; 
                    x.Folders.Length &gt; 0 &amp;&amp;
                    <span style="color:green;">//if there is a Work Item Manager, we don't care</span>                     x.Name != <span style="color:#a31515;">"WIM ("</span> + <span style="color:#2b91af;">Environment</span>.MachineName + <span style="color:#a31515;">")"</span>);
    <span style="color:blue;">if</span>(workspace == <span style="color:blue;">null</span>) <span style="color:blue;">continue</span>; <span style="color:green;">//no workspace for this server</span>     <span style="color:green;">//there's normally only one</span>     <span style="color:#2b91af;">WorkingFolder</span> folder = workspace.Folders.First();
    <span style="color:#2b91af;">Console</span>.WriteLine(<span style="color:#a31515;">"Working folder </span><span style="color:mediumseagreen;">{0}</span><span style="color:#a31515;">"</span>, folder.LocalItem);
}<br /><br /><span style="color:green;">//old VS 2008 way</span><span style="color:green;">//using (TeamFoundationServer tfsServer = new TeamFoundationServer(tfsServerName))</span><span style="color:green;">//{</span><span style="color:green;">//    // Get a reference to version control</span><span style="color:green;">//    VersionControlServer versionControl =</span><span style="color:green;">//        (VersionControlServer) tfsServer.GetService(typeof (VersionControlServer));</span><span style="color:green;">//    //....</span><span style="color:green;">//}</span><br /></pre>
        <img width="0" height="0" src="http://martinwilley.com/blog/aggbug.ashx?id=70a11d6b-a7dd-47dd-803d-9c545b2adfeb" />
      </div>
    </content>
  </entry>
  <entry>
    <title>MCPD Web Developer .Net 4</title>
    <link rel="alternate" type="text/html" href="http://martinwilley.com/blog/2011/12/10/MCPDWebDeveloperNet4.aspx" />
    <id>http://martinwilley.com/blog/PermaLink,guid,14db91d2-0338-4ad9-bbd5-a916cccce5be.aspx</id>
    <published>2011-12-10T14:15:55.176-07:00</published>
    <updated>2011-12-10T14:17:51.8024008-07:00</updated>
    <category term=".net 4" label=".net 4" scheme="http://martinwilley.com/blog/CategoryView,category,net4.aspx" />
    <category term="VS2010" label="VS2010" scheme="http://martinwilley.com/blog/CategoryView,category,VS2010.aspx" />
    <author>
      <name>Martin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
I've just done all 4 of the exams for .Net 4.0 MCPD Web Developer. Overall, I quite
enjoyed it. I even learned a bit. 
</p>
        <p>
Programmer certifications, and particularly the Microsoft ones, get a lot of criticism.
In theory they prove someone is proficient in the technology. In practice, by itself
a certificate is unreliable. 
</p>
        <p>
Microsoft's Partner program insists that companies have staff with certifications.
The body shops put their new recruits through a brief course so they can pass and
then be sold on. Often, they memorised the questions and answers from internet dumps.
It's disappointing to google the exam codes: apart from the Microsoft syllabus, every
link is a site selling the answers. 
</p>
        <p>
If you're a consultant, or you're going to change jobs, experienced programmers probably
have to do the exams too. If you work for a Microsoft Partner you have to do it, and
HR departments filter their CVs using it. Really, the best measure of proficiency
is years of experience and types of projects. That's real-world practical knowledge.
Okay, I would say that, having been doing this for 25 years. But, as the company I
work for needs the certificate points, and they're paying, I'm happy to do the exams.
</p>
        <p>
For .net 1 we had to do exams for ASP, windows forms and web services, but most .net
programmers then only worked in one or two of those- certainly never windows forms
and ASP. I was actually quite impressed by the .Net 2 foundation exam, which covered
a lot of basics: collections, threads, tracing, serialization, globalization, encryption.
Specific projects may not involve some of it, but a good .net programmer should know
almost all of it (even if you have to google the details). Unfortunately they dropped
it for .Net 4, going back to technology areas (asp, web services) just like the original
.net 1 exams.  Now for .net 4 "web" we have asp, wcf and data access (ado/entity
framework). Broadly I agree you'd expect all web developers to know those topics,
so that's not too bad. 
</p>
        <p>
One big problem with certification questions is that they pick on obscure APIs and
ASP controls. Now, questions on the validation controls is probably a good basic requirement,
but frankly the gridview events are a nightmare anyway, so memorizing them for an
exam is painful. The .net 4 asp exam wasn't too bad although there was some API questions
that in real life you'd just google. One of the jQuery questions annoyed me too, using
an unusual API detail (I think an older syntax) when they could have used a better,
clearer replacement.
</p>
        <p>
The older exams had sections devoted to things nobody ever uses. On the asp .net 2
exam it was mobile controls, and web parts (cloned from Sharepoint, and never used
outside Sharepoint). Fortunately there seems less of that in the .net 4 exams, although
there's still some asp ajax library stuff in there, plus some dynamic data. The big
problem was that jQuery and MVC have moved on since the exam was written. All the
questions were about MVC 2, not 3. It's not that the questions were obsolete (there
was nothing much about webform views to confuse those who use Razor), it's just that
the pace of change is making exams less relevant. 
</p>
        <p>
The other exams had little used topics too. The WCF exam covered MSMQ, which I've
never seen used in real life. The data access exam was more problematic. Basic ADO
is useful, but there was still material about little used dataset features like constraints
and dataRelations. There was not much on Linq2Sql, perhaps just as well, but most
of the exam was Entity Framework. I know EF is used out there, but I've yet to encounter
EF and it seems to be in second place to NHibernate at least for ORM data access.
So I did learn something for this exam, and yes, I passed the exam as a novice with
no real world experience of Entity Framework. On the other hand, as an experienced
programmer I'd feel comfortable doing EF (even if I'd rather be doing NHibernate.)
</p>
        <p>
Two of the exams - the WCF and the ASP Pro exam - had "testlets" with a case study
and a small number of questions about the scenario. The WCF was over-elaborate, with
source listings and xml, but for all that I thought it was a little more realistic
and actually quite enjoyable. 
</p>
        <p>
To study, I used the Microsoft Training Kit books, MSDN and for the areas I was less
familiar with - mostly EF and some aspects of WCF - a little practice. The WCF exam
didn't have a book, so I had to use the .net 3.5 one and look up a couple of subjects
(routing and discovery). I skimmed the bits I knew well (the asp/ web side generally).
Generally I found you needed a bit more knowledge than was in the books, but only
a few things were really obscure. Overall, studying for the exam was interesting and
useful. Learning about WCF routing and discovery and EF, things I haven't actually
used, did bring me more up-to-date with the .net 4 stack. 
<br /></p>
        <p>
A pity Microsoft's "congratulations" email contains a link to a blog that closed 2
years ago. 
<br /></p>
        <img width="0" height="0" src="http://martinwilley.com/blog/aggbug.ashx?id=14db91d2-0338-4ad9-bbd5-a916cccce5be" />
      </div>
    </content>
  </entry>
  <entry>
    <title>.Net 4.0 Caching - not just for Asp</title>
    <link rel="alternate" type="text/html" href="http://martinwilley.com/blog/2011/07/08/Net40CachingNotJustForAsp.aspx" />
    <id>http://martinwilley.com/blog/PermaLink,guid,1fa03e20-76dc-4241-b343-74eb6c71e62f.aspx</id>
    <published>2011-07-08T01:57:57.9461346-07:00</published>
    <updated>2011-07-08T01:57:57.9461346-07:00</updated>
    <category term=".net 4" label=".net 4" scheme="http://martinwilley.com/blog/CategoryView,category,net4.aspx" />
    <author>
      <name>Martin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">A brief recap of ASP.Net cache:<br /><br /><pre style="font-family:Consolas;font-size:13;color:black;background:white;"><span style="color:green;">//in MVC use HttpRuntime.Cache or HttpContext.Cache</span><span style="color:green;">//in webforms Application is the original cache without expiration rules</span><span style="color:blue;">var</span> category = <span style="color:#2b91af;">HttpRuntime</span>.Cache[<span style="color:#a31515;">"Category"</span>] <span style="color:blue;">as</span> <span style="color:#2b91af;">CategoryModel</span>; <span style="color:blue;">if</span> (category == <span style="color:blue;">null</span>)
{      category = _dataAccess.Find(1);      <span style="color:#2b91af;">HttpRuntime</span>.Cache[<span style="color:#a31515;">"Category"</span>] = category;
     <span style="color:green;">// ...or...</span>      <span style="color:green;">//monitor some files and/or other cache items</span>      <span style="color:blue;">var</span> cd = <span style="color:blue;">new</span> <span style="color:#2b91af;">CacheDependency</span>(<span style="color:blue;">new</span>[] { <span style="color:#a31515;">@"C:\triggerFolder\"</span> }, <span style="color:blue;">new</span>[] { <span style="color:#a31515;">"OtherCacheItem"</span> });
     <span style="color:#2b91af;">HttpRuntime</span>.Cache.Insert(<span style="color:#a31515;">"Category1"</span>, category, 
              
cd, <span style="color:green;">//dependencies or null</span>                <span style="color:#2b91af;">DateTime</span>.Now.AddMinutes(5), <span style="color:green;">//absolute expiration (or Cache.NoAbsoluteExporation)</span>              <span style="color:#2b91af;">Cache</span>.NoSlidingExpiration <span style="color:green;">//sliding expiration (timespan)</span>     
); }</pre>Mocking this in tests (especially for MVC) is a bit ugly (.Net 3.5sp1 has
System.Web.Abstractions including HttpContextBase, but caching isn't included)<br /><br />
Now in .Net 4 we can reference <a href="http://msdn.microsoft.com/en-us/library/dd985642.aspx">System.Runtime.Caching</a>.dll.
And the really nice thing is this will run outside Asp.Net.<br /><pre style="font-family:Consolas;font-size:13;color:black;background:white;"><span style="color:green;">//get the static "default" cache. You can have multiple named caches.</span><span style="color:#2b91af;">ObjectCache</span> cache = <span style="color:#2b91af;">MemoryCache</span>.Default; <span style="color:green;">//you can't store null in the cache</span><span style="color:blue;">var</span> category = cache[<span style="color:#a31515;">"Category"</span>] <span style="color:blue;">as</span> <span style="color:#2b91af;">CategoryModel</span>; <span style="color:blue;">if</span> (category == <span style="color:blue;">null</span>)
{     category = _dataAccess.Find(1);     cache[<span style="color:#a31515;">"Category"</span>] = category;
    <span style="color:green;">// ...or...</span>     <span style="color:blue;">var</span> policy = <span style="color:blue;">new</span> <span style="color:#2b91af;">CacheItemPolicy</span>();
    policy.AbsoluteExpiration = <span style="color:#2b91af;">DateTime</span>.Now.AddMinutes(5);
    <span style="color:green;">//monitor some files and/or other cache items</span>     policy.ChangeMonitors.Add(
        <span style="color:blue;">new</span> <span style="color:#2b91af;">HostFileChangeMonitor</span>(<span style="color:blue;">new</span> <span style="color:#2b91af;">List</span>&lt;<span style="color:blue;">string</span>&gt; { <span style="color:#a31515;">@"C:\triggerFolder\"</span>})
        );     <span style="color:green;">//synchronize with another cache item</span>     policy.ChangeMonitors.Add(
        cache.CreateCacheEntryChangeMonitor(<span style="color:blue;">new</span> [] { <span style="color:#a31515;">"OtherCacheItem"</span>})
        );     cache.Add(<span style="color:#a31515;">"Category1"</span>, category, policy);
} </pre>For simple caching (no change monitors) you don't even need mocking in your
tests - in fact, you can test your caching with a real cache. You can move caching
down into your library classes that may be called from web pages, tests, WPF apps
and consoles.<br /><br /><br /><br /><p></p><img width="0" height="0" src="http://martinwilley.com/blog/aggbug.ashx?id=1fa03e20-76dc-4241-b343-74eb6c71e62f" /></div>
    </content>
  </entry>
  <entry>
    <title>T4 preprocessing</title>
    <link rel="alternate" type="text/html" href="http://martinwilley.com/blog/2011/06/10/T4Preprocessing.aspx" />
    <id>http://martinwilley.com/blog/PermaLink,guid,156ef515-1762-4604-84b9-d1213b895b03.aspx</id>
    <published>2011-06-10T04:50:55.699-07:00</published>
    <updated>2011-06-10T13:16:46.1202523-07:00</updated>
    <category term=".net 4" label=".net 4" scheme="http://martinwilley.com/blog/CategoryView,category,net4.aspx" />
    <category term="VS2010" label="VS2010" scheme="http://martinwilley.com/blog/CategoryView,category,VS2010.aspx" />
    <author>
      <name>Martin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">T4 preprocessed templates are a neat way
of generating text at run time, which can be deployed to machines without Visual Studio.
Here's <a href="http://msdn.microsoft.com/en-us/library/ee844259.aspx">MSDN</a><br /><br />
Here's a simple template, ClassWriter.tt, which must be marked CustomTool = "<b>TextTemplatingFilePreprocessor</b>"
in properties (not "<b>TextTemplatingFileGenerator</b>" which is a normal T4).<br /><pre style="font-family:Consolas;font-size:13;color:black;background:white;"><span style="background:gold;">&lt;#@</span> <span style="color:maroon;">template</span> <span style="color:maroon;">language</span><span style="color:gray;">=</span><span style="color:blue;">"C#"</span> <span style="background:gold;">#&gt;</span><span style="background:gold;">&lt;#@</span> <span style="color:maroon;">import</span> <span style="color:maroon;">namespace</span><span style="color:gray;">=</span><span style="color:blue;">"System.Linq"</span> <span style="background:gold;">#&gt;</span><span style="background:gold;">&lt;#@</span> <span style="color:maroon;">parameter</span> <span style="color:maroon;">type</span><span style="color:gray;">=</span><span style="color:blue;">"Generator.Model.Table"</span> <span style="color:maroon;">name</span><span style="color:gray;">=</span><span style="color:blue;">"table"</span> <span style="background:gold;">#&gt;</span><span style="color:gray;">using System;</span><span style="color:gray;">namespace </span><span style="background:gold;">&lt;#=</span> table.Namespace <span style="background:gold;">#&gt;</span><span style="color:gray;">{</span><span style="color:gray;">    [Serializable]</span><span style="color:gray;">    public class </span><span style="background:gold;">&lt;#=</span> table.Name <span style="background:gold;">#&gt;</span><span style="color:gray;">    {</span><span style="background:gold;">&lt;#</span>  <span style="color:blue;">foreach</span>(<span style="color:blue;">var</span> column <span style="color:blue;">in</span> table.Columns.Where(c=&gt; !c.Hidden)) { <span style="background:gold;">#&gt;</span><span style="color:gray;">        public virtual </span><span style="background:gold;">&lt;#=</span> column.Type <span style="background:gold;">#&gt;</span><span style="color:gray;"> </span><span style="background:gold;">&lt;#=</span> column.Name <span style="background:gold;">#&gt;</span><span style="color:gray;"> { get; set; }</span><span style="background:gold;">&lt;#</span>    } <span style="background:gold;">#&gt;</span><span style="color:gray;">    }</span><span style="color:gray;">}</span></pre><br />
At development time, Visual Studio generates the class in the corresponding namespace
which you can then call (yeah, it generates code for generating code...). 
<br /><br />
Notice we're passing a parameter, which has to have the full namespaced name (even
"string" has to be "System.String"). 
<br /><br />
The generated class is partial and the parameters are property getters with a backing
field. MSDN suggests that to pass in your parameters you should manually code a partial
class with conventional properties or a constructor. Actually, there's an easier no-code
way. Use the Session property (which is just a Dictionary&lt;string, object&gt;) which
you can use with an Initialize() method. Like this:<br /><br /><pre style="font-family:Consolas;font-size:13;color:black;background:white;"><span style="color:green;">//create the class generated by TextTemplatingFilePreprocessor </span><span style="color:blue;">var</span> generator = <span style="color:blue;">new</span> <span style="color:#2b91af;">ClassWriter</span>(); <span style="color:green;">//create a session dictionary, fill it and initialize</span> generator.Session = <span style="color:blue;">new</span> <span style="color:#2b91af;">Dictionary</span>&lt;<span style="color:blue;">string</span>, <span style="color:blue;">object</span>&gt;();
generator.Session.Add(<span style="color:#a31515;">"table"</span>, table); generator.Initialize(); <span style="color:green;">//transform!</span><span style="color:blue;">var</span> text = generator.TransformText();</pre>The
key things to watch out for: 
<br /><ul><li>
you must create the Session dictionary (it's not initialized internally)</li><li>
you must call Initialize() after it's populated.</li></ul><br />
You can also use System.Runtime.Remoting.Messaging.CallContext but weirdly you must
still initialize the Session dictionary (Initialize checks Session first, then CallContext).<br />
 <br />
You may be tempted to reuse the T4 template class like this.<br /><pre style="font-family:Consolas;font-size:13;color:black;background:white;"><span style="color:green;">//don't do this</span><span style="color:blue;">var</span> generator = <span style="color:blue;">new</span> <span style="color:#2b91af;">ClassWriter</span>(); <span style="color:blue;">foreach</span> (<span style="color:blue;">var</span> item <span style="color:blue;">in</span> list)
{     generator.Session = <span style="color:blue;">new</span> <span style="color:#2b91af;">Dictionary</span>&lt;<span style="color:blue;">string</span>, <span style="color:blue;">object</span>&gt;();
    generator.Session.Add(<span style="color:#a31515;">"table"</span>, item);
    generator.Initialize();     <span style="color:blue;">var</span> txt = generator.TransformText();
    WriteText(item, txt); }</pre>The template class actually
uses an internal StringBuilder called GenerationEnvironment. So each call returns
everything you wrote before. You can't actually reset the StringBuilder (although
you can append to it with Write overloads). So, always create the template class <i>within </i>the
loop.<br /><br /><br /><br /><p></p><img width="0" height="0" src="http://martinwilley.com/blog/aggbug.ashx?id=156ef515-1762-4604-84b9-d1213b895b03" /></div>
    </content>
  </entry>
  <entry>
    <title>ildasm and ilasm to sign an unsigned assembly</title>
    <link rel="alternate" type="text/html" href="http://martinwilley.com/blog/2011/05/02/ildasmAndIlasmToSignAnUnsignedAssembly.aspx" />
    <id>http://martinwilley.com/blog/PermaLink,guid,01ffea52-804a-4fd7-b807-4f05bb4c1b22.aspx</id>
    <published>2011-05-02T05:50:05.393362-07:00</published>
    <updated>2011-05-02T05:50:05.393362-07:00</updated>
    <category term=".net 4" label=".net 4" scheme="http://martinwilley.com/blog/CategoryView,category,net4.aspx" />
    <author>
      <name>Martin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Strong named assemblies cannot reference
assemblies which aren't strong named. 
<br /><br />
Decompile with ildasm and recompile with ilasm using your key.<br /><br />
Default ILDASM and ILASM locations as of .Net 4.0<br /><br />
"C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\ildasm.exe" ClassLibrary.dll /out:ClassLibrary.il<br />
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\ilasm.exe" ClassLibrary.il /res:ClassLibrary.res
/dll /key:myKey.snk /out:ClassLibrary.dll<br /><p></p><img width="0" height="0" src="http://martinwilley.com/blog/aggbug.ashx?id=01ffea52-804a-4fd7-b807-4f05bb4c1b22" /></div>
    </content>
  </entry>
  <entry>
    <title>Database Schema Reader with more SqlServerCE 4.0 love</title>
    <link rel="alternate" type="text/html" href="http://martinwilley.com/blog/2011/04/25/DatabaseSchemaReaderWithMoreSqlServerCE40Love.aspx" />
    <id>http://martinwilley.com/blog/PermaLink,guid,2374a274-7c2e-49a4-808f-8b33799b4fe3.aspx</id>
    <published>2011-04-25T03:13:17.769-07:00</published>
    <updated>2011-04-25T03:18:30.3625852-07:00</updated>
    <category term="Codeplex" label="Codeplex" scheme="http://martinwilley.com/blog/CategoryView,category,Codeplex.aspx" />
    <category term="Database Schema Reader" label="Database Schema Reader" scheme="http://martinwilley.com/blog/CategoryView,category,DatabaseSchemaReader.aspx" />
    <category term="SqlServerCe" label="SqlServerCe" scheme="http://martinwilley.com/blog/CategoryView,category,SqlServerCe.aspx" />
    <author>
      <name>Martin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
Shortly after the last release of <a href="http://dbschemareader.codeplex.com/" target="_blank">Database
Schema Reader</a>, here's another release.
</p>
        <p>
          <a href="http://martinwilley.com/blog/2011/04/09/DatabaseSchemaReaderNowWithExtraSQLite.aspx" target="_blank">Last
time</a> I added a CopyToSQLite tool, which reads (almost) any database and creates
a SQLite clone. I also added experimental support for SQLServer CE 4.0, but it had
some big limitations. 
</p>
        <p>
So the obvious next step was to fix some of those limitations, and that's what this
release focuses on. Unfortunately CopyToSQLite.exe is now a little misnamed. <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://www.martinwilley.com/blog/content/binary/Database-Schema-Reader-with-more-.0-love_9CD7/wlEmoticon-winkingsmile.png" /></p>
        <p>
I added a little bit of conversion code so VARCHAR(MAX) found in the origin database
gets converted to NTEXT (and VARBINARY to IMAGE). The reading of SQLServer CE 4 databases
got improved too (capturing the  foreign and unique keys and identity columns).
</p>
        <p>
SQLServer allows an integer column to be marked as "Identity" so it will be auto-generated
(the equivalent in Oracle is to create a sequence and an insert trigger). But you
can't include the identity column when you insert a row. So, when cloning data, SQLServer
also allows identity-inserts with SET IDENTITY_INSERT [MyTable] ON/OFF. When you've
done that, you should reset the identity seed with DBCC CHECKIDENT.
</p>
        <p>
But in SQLServer CE 4, there is no DBCC CHECKIDENT. You have to do an ALTER TABLE
[MyTable] ALTER COLUMN [IdentityColumn] IDENTITY (999,1) (where 999 is the new max(IdentityColumn)).
It's another of those little gotchas between SQLServer and SQLServer CE.
</p>
        <p>
SQLServer CE 4 has some great new paging syntax:
</p>
        <p>
SELECT Id, Name FROM MyTable 
<br />
ORDER BY Name 
<br />
OFFSET 10 ROWS 
<br />
FETCH NEXT 5 ROWS ONLY
</p>
        <p>
It's similar to the LIMIT/OFFSET syntax in MySQL and SQLite, but (reasonably enough)
must follow an ORDER BY. Rather than offset/skipping a number of rows, I'd like to
specify just page number and page size - or another formula. The <a href="http://msdn.microsoft.com/en-us/library/ms188385%28v=sql.110%29.aspx#Offset" target="_blank">SQLServer
2011/Denali documentation</a> shows the offset/fetch syntax for a start row/end row
expression:
</p>
        <p>
SELECT DepartmentID, Name, GroupName 
<br />
FROM HumanResources.Department 
<br />
ORDER BY DepartmentID ASC 
<br />
OFFSET @StartingRowNumber - 1 ROWS 
<br />
FETCH NEXT @EndingRowNumber - @StartingRowNumber + 1 ROWS ONLY
</p>
        <p>
But that doesn't work in SQLServer CE 4. You can use parameters, or constants, or
expressions with constants, but apparently not expressions with constants and parameters.
Oh well, it's still much better than horrible OVER subqueries.<br /></p>
        <p>
Overall, the "CopyToSQLite" to SQLServer CE 4 seems to work well. Using easily deployable
file databases like SQLServer CE and SQLite is simple and powerful. 
</p>
        <img width="0" height="0" src="http://martinwilley.com/blog/aggbug.ashx?id=2374a274-7c2e-49a4-808f-8b33799b4fe3" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Database Schema Reader now with extra SQLite</title>
    <link rel="alternate" type="text/html" href="http://martinwilley.com/blog/2011/04/09/DatabaseSchemaReaderNowWithExtraSQLite.aspx" />
    <id>http://martinwilley.com/blog/PermaLink,guid,b8fbbe6a-5e86-4963-a561-52f6b8aeb4e9.aspx</id>
    <published>2011-04-09T11:05:41.0678405-07:00</published>
    <updated>2011-04-09T11:05:41.0678405-07:00</updated>
    <category term=".net 4" label=".net 4" scheme="http://martinwilley.com/blog/CategoryView,category,net4.aspx" />
    <category term="Codeplex" label="Codeplex" scheme="http://martinwilley.com/blog/CategoryView,category,Codeplex.aspx" />
    <category term="Database Schema Reader" label="Database Schema Reader" scheme="http://martinwilley.com/blog/CategoryView,category,DatabaseSchemaReader.aspx" />
    <author>
      <name>Martin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
My Codeplex project, <a href="http://dbschemareader.codeplex.com/" target="_blank">Database
Schema Reader</a>, has a new version.
</p>
        <p>
I needed to create a SQLite database was a replica of a parent SQL Server database.
The existing project could easily read the schema, and the code generation tools could
give me the table DDL and the insert SQL. It was just a matter of executing the SQL
and creating the database file. 
</p>
        <p>
So I created another simple Windows Forms UI. The SqlWriter class needed some tweaks
for SQLite support (and I added integration tests).
</p>
        <p>
For fun, I decided to see if it could also support Microsoft's latest version of SQL
Server CE 4.0. 
</p>
        <p>
SQL Server CE 4.0 is, like SQLite, an in-process database which can be XCOPY deployed.
And unlike previous versions, it is easily able to run ASP.Net websites (it's the
default database behind WebMatrix). And 4.0 provides the standard ADO GetSchema which
my Database Schema Reader uses (3.5 throws a Not Implemented exception).
</p>
        <p>
It has some of the same limitations as SQLite, such as no stored procedures (good
riddance), and no output parameters. But it also has additional limitations. In SQLite
you can batch together multiple SQL statements in a single line and execute them in
one command. You can't in SQL Server CE.
</p>
        <p>
Unlike SQLite's weakly typed and very simple data types, SQL Server CE 4.0 has most
of the standard data types as SQL Server Express and full versions. Unfortunately,
this was the big problem. If your table is defined with an IDENTITY primary key, you
can't insert the data row with the same primary key, and subsequent foreign key relationships
are broken. It's a pretty critical limitation for my scenario. 
</p>
        <p>
SQL Server CE 4 only supports a subset of SQL Server data types. The one data type
it didn't support, which my database (and later versions of Northwind) use, is NVARCHAR(MAX).
You have to use the horrible old NTEXT data type. I could have written a DDL provider
that translates varchar max to ntext, but I don't think it's worth the effort.
</p>
        <p>
So my SQL Server CE creation program has major limitations, compared to the SQLite
version. It's built into CopyToSQLite.exe, and auto-detects if you've installed SQL
Server CE, but you have to have a very simple database for it to work.
</p>
        <p>
SQL Server CE 4 also doesn't support the ADO Sync framework which allows you to synchronize
a disconnected database to a parent SQL Server database. Even SQL Server 2008 R2 Management
Studio doesn't support it (you have to use Visual Studio 2010 with SP1).
</p>
        <p>
The new FETCH /OFFSET syntax for paging, that will be SQL Server 11, is very nice
though. I'm looking forward to that.
</p>
        <img width="0" height="0" src="http://martinwilley.com/blog/aggbug.ashx?id=b8fbbe6a-5e86-4963-a561-52f6b8aeb4e9" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Publish and Transform in MSBuild script</title>
    <link rel="alternate" type="text/html" href="http://martinwilley.com/blog/2011/04/07/PublishAndTransformInMSBuildScript.aspx" />
    <id>http://martinwilley.com/blog/PermaLink,guid,077263aa-3d47-480f-94f1-50ff5689888d.aspx</id>
    <published>2011-04-07T03:34:35.229-07:00</published>
    <updated>2011-04-07T06:46:06.0653986-07:00</updated>
    <category term=".net 4" label=".net 4" scheme="http://martinwilley.com/blog/CategoryView,category,net4.aspx" />
    <category term="VS2010" label="VS2010" scheme="http://martinwilley.com/blog/CategoryView,category,VS2010.aspx" />
    <author>
      <name>Martin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">VS 2010 web.config transformations are great.<br />
Change your development web.config which looks like this: 
<br /><br /><pre style="font-family:Consolas;font-size:13;color:black;background:white;"><span style="color:blue;">&lt;?</span><span style="color:#a31515;">xml</span><span style="color:blue;"> </span><span style="color:red;">version</span><span style="color:blue;">=</span>"<span style="color:blue;">1.0</span>"<span style="color:blue;">?&gt;</span><span style="color:blue;">&lt;</span><span style="color:#a31515;">configuration</span><span style="color:blue;">&gt;</span><span style="color:blue;">  &lt;</span><span style="color:#a31515;">connectionStrings</span><span style="color:blue;">&gt;</span><span style="color:blue;">    &lt;</span><span style="color:#a31515;">add</span><span style="color:blue;"> </span><span style="color:red;">name</span><span style="color:blue;">=</span>"<span style="color:blue;">ApplicationServices</span>" <span style="color:blue;">         </span><span style="color:red;">connectionString</span><span style="color:blue;">=</span>"<span style="color:blue;">data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true</span>" <span style="color:blue;">         </span><span style="color:red;">providerName</span><span style="color:blue;">=</span>"<span style="color:blue;">System.Data.SqlClient</span>"<span style="color:blue;"> /&gt;</span><span style="color:blue;">  &lt;/</span><span style="color:#a31515;">connectionStrings</span><span style="color:blue;">&gt;</span><span style="color:blue;">  &lt;</span><span style="color:#a31515;">system.web</span><span style="color:blue;">&gt;</span><span style="color:blue;">    &lt;</span><span style="color:#a31515;">compilation</span><span style="color:blue;"> </span><span style="color:red;">debug</span><span style="color:blue;">=</span>"<span style="color:blue;">true</span>"<span style="color:blue;"> </span><span style="color:red;">targetFramework</span><span style="color:blue;">=</span>"<span style="color:blue;">4.0</span>"<span style="color:blue;">&gt;</span></pre><br />
by adding a Web.<i>DeployTest</i>.config file which looks like this:<br /><br /><pre style="font-family:Consolas;font-size:13;color:black;background:white;"><span style="color:blue;">&lt;?</span><span style="color:#a31515;">xml</span><span style="color:blue;"> </span><span style="color:red;">version</span><span style="color:blue;">=</span>"<span style="color:blue;">1.0</span>"<span style="color:blue;">?&gt;</span><span style="color:blue;">&lt;</span><span style="color:#a31515;">configuration</span><span style="color:blue;"> </span><span style="color:red;">xmlns:xdt</span><span style="color:blue;">=</span>"<span style="color:blue;">http://schemas.microsoft.com/XML-Document-Transform</span>"<span style="color:blue;">&gt;</span><span style="color:blue;">  &lt;</span><span style="color:#a31515;">connectionStrings</span><span style="color:blue;">&gt;</span><span style="color:blue;">    &lt;</span><span style="color:#a31515;">add</span><span style="color:blue;"> </span><span style="color:red;">name</span><span style="color:blue;">=</span>"<span style="color:blue;">ApplicationServices</span>"<span style="color:blue;"> </span><span style="color:red;">connectionString</span><span style="color:blue;">=</span>"<span style="color:blue;">Data Source=StaticVoidSqlServer;Initial Catalog=Northwind;Integrated Security=SSPI;</span>"<span style="color:blue;"> </span><span style="color:red;">providerName</span><span style="color:blue;">=</span>"<span style="color:blue;">System.Data.SqlClient</span>" <span style="color:blue;">         </span><span style="color:red;">xdt:Transform</span><span style="color:blue;">=</span>"<span style="color:blue;">SetAttributes</span>"<span style="color:blue;"> </span><span style="color:red;">xdt:Locator</span><span style="color:blue;">=</span>"<span style="color:blue;">Match(name)</span>"<span style="color:blue;">/&gt;</span><span style="color:blue;">  &lt;/</span><span style="color:#a31515;">connectionStrings</span><span style="color:blue;">&gt;</span><span style="color:blue;">&lt;/</span><span style="color:#a31515;">configuration</span><span style="color:blue;">&gt;</span></pre><br />
Only by default it's tied up with the build configurations (Debug, Release etc) and
the Web deploy story. 
<br />
But I don't want a web deployment package. I want:<br /><ul><li>
a normal "Release" configuration build</li><li>
a directory containing all the website files that I can XCopy deploy (like old school
Visual Studio 2008 publish)</li><li>
the web.config transformed with my custom "DeployTest" name.<br /></li></ul>
Doing it this way means the web.DeployTest.config is not automatically nested under
the web.config (and I should mark it as BuildAction=None).<br />
But that's my requirements. So I wrote an MSBuild file.<br /><br /><h2>Batch file (build.bat)
</h2>
First here's a standard batch file, "build.bat", to launch it (I want MSBuild 4.0):<br /><pre style="font-family: Consolas; font-size: 13px; color: black; background: none repeat scroll 0% 0% white;">%systemroot%\Microsoft.Net\Framework\v4.0.30319\MSBuild.exe build.proj  /t:Release &amp; pause

<br /></pre><h2>MSBuild script (build.proj)
</h2><pre style="font-family: Consolas; font-size: 13px; color: black; background: none repeat scroll 0% 0% white;"><br /><span style="color:blue;">&lt;?</span><span style="color:#a31515;">xml</span><span style="color:blue;"> </span><span style="color:red;">version</span><span style="color:blue;">=</span>"<span style="color:blue;">1.0</span>"<span style="color:blue;"> </span><span style="color:red;">encoding</span><span style="color:blue;">=</span>"<span style="color:blue;">utf-8</span>"<span style="color:blue;"> ?&gt;</span><span style="color:blue;">&lt;</span><span style="color:#a31515;">Project</span><span style="color:blue;"> </span><span style="color:red;">ToolsVersion</span><span style="color:blue;">=</span>"<span style="color:blue;">4.0</span>"<span style="color:blue;"> </span><span style="color:red;">xmlns</span><span style="color:blue;">=</span>"<span style="color:blue;">http://schemas.microsoft.com/developer/msbuild/2003</span>"<span style="color:blue;"> </span><span style="color:red;">DefaultTargets</span><span style="color:blue;">=</span>"<span style="color:blue;">Release</span>"<span style="color:blue;">&gt;</span><span style="color:blue;">  &lt;</span><span style="color:#a31515;">UsingTask</span><span style="color:blue;"> </span><span style="color:red;">TaskName</span><span style="color:blue;">=</span>"<span style="color:blue;">TransformXml</span>"<span style="color:blue;"> </span><span style="color:red;">AssemblyFile</span><span style="color:blue;">=</span>"<span style="color:blue;">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll</span>"<span style="color:blue;"> /&gt;</span><span style="color:blue;">  &lt;</span><span style="color:#a31515;">PropertyGroup</span><span style="color:blue;">&gt;</span><span style="color:blue;">    &lt;!--</span><span style="color:green;"> properties that are used in this build file - referenced as $(PropertyName) </span><span style="color:blue;">--&gt;</span><span style="color:blue;">    &lt;</span><span style="color:#a31515;">ProjectName</span><span style="color:blue;">&gt;</span>StaticVoid<span style="color:blue;">&lt;/</span><span style="color:#a31515;">ProjectName</span><span style="color:blue;">&gt;</span><span style="color:blue;">    &lt;</span><span style="color:#a31515;">DeployConfiguration</span><span style="color:blue;">&gt;</span>DeployTest<span style="color:blue;">&lt;/</span><span style="color:#a31515;">DeployConfiguration</span><span style="color:blue;">&gt;</span><span style="color:blue;">    &lt;</span><span style="color:#a31515;">PublishPath</span><span style="color:blue;">&gt;</span>$(MSBuildProjectDirectory)\..\Publish\<span style="color:blue;">&lt;/</span><span style="color:#a31515;">PublishPath</span><span style="color:blue;">&gt;</span><span style="color:blue;">    &lt;</span><span style="color:#a31515;">OutputPath</span><span style="color:blue;">&gt;</span>$(PublishPath)\StaticVoid\<span style="color:blue;">&lt;/</span><span style="color:#a31515;">OutputPath</span><span style="color:blue;">&gt;</span><span style="color:blue;">    &lt;</span><span style="color:#a31515;">PackagePath</span><span style="color:blue;">&gt;</span>$(PublishPath)\StaticVoidPackage\<span style="color:blue;">&lt;/</span><span style="color:#a31515;">PackagePath</span><span style="color:blue;">&gt;</span><span style="color:blue;">    &lt;</span><span style="color:#a31515;">TransformInputFile</span><span style="color:blue;">&gt;</span>..\StaticVoid\Web.config<span style="color:blue;">&lt;/</span><span style="color:#a31515;">TransformInputFile</span><span style="color:blue;">&gt;</span><span style="color:blue;">    &lt;</span><span style="color:#a31515;">TransformFile</span><span style="color:blue;">&gt;</span>..\StaticVoid\Web.$(DeployConfiguration).config<span style="color:blue;">&lt;/</span><span style="color:#a31515;">TransformFile</span><span style="color:blue;">&gt;</span><span style="color:blue;">    &lt;</span><span style="color:#a31515;">TransformOutputFile</span><span style="color:blue;">&gt;</span>$(OutputPath)\Web.config<span style="color:blue;">&lt;/</span><span style="color:#a31515;">TransformOutputFile</span><span style="color:blue;">&gt;</span><span style="color:blue;">    &lt;</span><span style="color:#a31515;">ImageResourcesPath</span><span style="color:blue;">&gt;</span>..\ImageResources<span style="color:blue;">&lt;/</span><span style="color:#a31515;">ImageResourcesPath</span><span style="color:blue;">&gt;</span><span style="color:blue;">  &lt;/</span><span style="color:#a31515;">PropertyGroup</span><span style="color:blue;">&gt;</span><span style="color:blue;">  &lt;</span><span style="color:#a31515;">ItemGroup</span><span style="color:blue;">&gt;</span><span style="color:blue;">    &lt;</span><span style="color:#a31515;">ImageResources</span><span style="color:blue;"> </span><span style="color:red;">Include</span><span style="color:blue;">=</span>"<span style="color:blue;">$(ImageResourcesPath)\*.jpg</span>"<span style="color:blue;"> /&gt;</span><span style="color:blue;">  &lt;/</span><span style="color:#a31515;">ItemGroup</span><span style="color:blue;">&gt;</span><span style="color:blue;">  &lt;!--</span><span style="color:green;"> targets </span><span style="color:blue;">--&gt;</span><span style="color:blue;">  &lt;</span><span style="color:#a31515;">Target</span><span style="color:blue;"> </span><span style="color:red;">Name</span><span style="color:blue;">=</span>"<span style="color:blue;">PublishWebsite</span>"<span style="color:blue;">&gt;</span><span style="color:blue;">    &lt;</span><span style="color:#a31515;">Message</span><span style="color:blue;"> </span><span style="color:red;">Text</span><span style="color:blue;">=</span>"<span style="color:blue;">Publishing Website</span>"<span style="color:blue;"> /&gt;</span><span style="color:blue;">    &lt;</span><span style="color:#a31515;">RemoveDir</span><span style="color:blue;"> </span><span style="color:red;">Directories</span><span style="color:blue;">=</span>"<span style="color:blue;">$(PublishPath)</span>"<span style="color:blue;">/&gt;</span><span style="color:blue;">    &lt;!--</span><span style="color:green;"> do a deploy </span><span style="color:blue;">--&gt;</span><span style="color:blue;">    &lt;</span><span style="color:#a31515;">MSBuild</span><span style="color:blue;"> </span><span style="color:red;">Projects</span><span style="color:blue;">=</span>"<span style="color:blue;">..\StaticVoid\StaticVoid.csproj</span>" <span style="color:blue;"></span><span style="color:red;">Properties</span><span style="color:blue;">=</span>"<span style="color:blue;">Configuration=Release;OutputPath=$(PackagePath);DeployOnBuild=true;DeployTarget=PipelinePreDeployCopyAllFilesToOneFolder;AutoParameterizationWebConfigConnectionStrings=false;_PackageTempDir=$(OutputPath)</span>"<span style="color:blue;">/&gt;</span><span style="color:blue;">  &lt;/</span><span style="color:#a31515;">Target</span><span style="color:blue;">&gt;</span><span style="color:blue;">  &lt;</span><span style="color:#a31515;">Target</span><span style="color:blue;"> </span><span style="color:red;">Name</span><span style="color:blue;">=</span>"<span style="color:blue;">Transform</span>"<span style="color:blue;">&gt;</span><span style="color:blue;">    &lt;!--</span><span style="color:green;"> transform the web.config </span><span style="color:blue;">--&gt;</span><span style="color:blue;">    &lt;</span><span style="color:#a31515;">TransformXml</span><span style="color:blue;"> </span><span style="color:red;">Source</span><span style="color:blue;">=</span>"<span style="color:blue;">$(TransformInputFile)</span>" <span style="color:blue;">                  </span><span style="color:red;">Transform</span><span style="color:blue;">=</span>"<span style="color:blue;">$(TransformFile)</span>" <span style="color:blue;">                  </span><span style="color:red;">Destination</span><span style="color:blue;">=</span>"<span style="color:blue;">$(TransformOutputFile)</span>"<span style="color:blue;"> /&gt;</span><span style="color:blue;">  &lt;/</span><span style="color:#a31515;">Target</span><span style="color:blue;">&gt;</span><span style="color:blue;">  &lt;</span><span style="color:#a31515;">Target</span><span style="color:blue;"> </span><span style="color:red;">Name</span><span style="color:blue;">=</span>"<span style="color:blue;">BuildWebsite</span>"<span style="color:blue;"> </span><span style="color:red;">DependsOnTargets</span><span style="color:blue;">=</span>"<span style="color:blue;">PublishWebsite</span>"<span style="color:blue;">&gt;</span><span style="color:blue;">    &lt;!--</span><span style="color:green;"> we don't need the deployment package, we wanted the published files to
copy manually </span><span style="color:blue;">--&gt;</span><span style="color:blue;">    &lt;</span><span style="color:#a31515;">RemoveDir</span><span style="color:blue;"> </span><span style="color:red;">Directories</span><span style="color:blue;">=</span>"<span style="color:blue;">$(PackagePath)</span>"<span style="color:blue;">/&gt;</span><span style="color:blue;">    &lt;!--</span><span style="color:green;"> copy the unmanaged resources </span><span style="color:blue;">--&gt;</span><span style="color:blue;">    &lt;</span><span style="color:#a31515;">Copy</span><span style="color:blue;"> </span><span style="color:red;">SourceFiles</span><span style="color:blue;">=</span>"<span style="color:blue;">@(ImageResources)</span>"<span style="color:blue;"> </span><span style="color:red;">DestinationFolder</span><span style="color:blue;">=</span>"<span style="color:blue;">$(PublishPath)images</span>"<span style="color:blue;"> </span><span style="color:red;">SkipUnchangedFiles</span><span style="color:blue;">=</span>"<span style="color:blue;">true</span>"<span style="color:blue;"> /&gt;</span><span style="color:blue;">  &lt;/</span><span style="color:#a31515;">Target</span><span style="color:blue;">&gt;</span><span style="color:blue;">  </span><span style="color:blue;">  &lt;</span><span style="color:#a31515;">Target</span><span style="color:blue;"> </span><span style="color:red;">Name</span><span style="color:blue;">=</span>"<span style="color:blue;">Release</span>"<span style="color:blue;"> </span><span style="color:red;">DependsOnTargets</span><span style="color:blue;">=</span>"<span style="color:blue;">BuildWebsite; Transform;</span>"<span style="color:blue;">&gt;</span><span style="color:blue;">  &lt;/</span><span style="color:#a31515;">Target</span><span style="color:blue;">&gt;</span><span style="color:blue;">&lt;/</span><span style="color:#a31515;">Project</span><span style="color:blue;">&gt;</span><br />
 <br /></pre><h3>A little explanation
</h3><pre style="font-family:Consolas;font-size:13;color:black;background:white;">The MSBuild task for the website project (StaticVoid.csproj) has a whole set of extra properties set which make it do a deploy.<br />
(Broken here to be easier to read:)<br /><span style="color:blue;">    &lt;</span><span style="color:#a31515;">MSBuild</span><span style="color:blue;"> </span><span style="color:red;">Projects</span><span style="color:blue;">=</span>"<span style="color:blue;">..\StaticVoid\StaticVoid.csproj</span>" <span style="color:blue;"></span><span style="color:red;">Properties</span><span style="color:blue;">=</span>"<span style="color:blue;">Configuration=Release;<br />
OutputPath=$(PackagePath);<br />
DeployOnBuild=true;<br />
DeployTarget=PipelinePreDeployCopyAllFilesToOneFolder;<br />
AutoParameterizationWebConfigConnectionStrings=false;<br />
_PackageTempDir=$(OutputPath)</span>"<span style="color:blue;">/&gt;</span><br /><br /></pre>The regular deployment package is written to $(PackagePath). I don't care about
that, so I delete it.<br />
The actual directory and files that I wanted are written to $(OutputPath) using the
_PackageTempDir property.<br /><br />
For the transform, note the msbuild xml must have <span style="color:#a31515;">Project</span><span style="color:blue;"> </span><span style="color:red;">ToolsVersion</span><span style="color:blue;">=</span>"<span style="color:blue;">4.0</span>"
and 
<br /><pre style="font-family:Consolas;font-size:13;color:black;background:white;"><span style="color:blue;">&lt;</span><span style="color:#a31515;">UsingTask</span><span style="color:blue;"> </span><span style="color:red;">TaskName</span><span style="color:blue;">=</span>"<span style="color:blue;">TransformXml</span>"<span style="color:blue;"></span><span style="color:red;"><br />
AssemblyFile</span><span style="color:blue;">=</span>"<span style="color:blue;">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll</span>"<span style="color:blue;"> /&gt;</span><br />
And then the transformation:<br /><span style="color:blue;">    &lt;</span><span style="color:#a31515;">TransformXml</span><span style="color:blue;"> </span><span style="color:red;">Source</span><span style="color:blue;">=</span>"<span style="color:blue;">$(TransformInputFile)</span>" <span style="color:blue;">                  </span><span style="color:red;">Transform</span><span style="color:blue;">=</span>"<span style="color:blue;">$(TransformFile)</span>" <span style="color:blue;">                  </span><span style="color:red;">Destination</span><span style="color:blue;">=</span>"<span style="color:blue;">$(TransformOutputFile)</span>"<span style="color:blue;"> /&gt;</span><br /></pre>with $(TransformFile) defined as<br /><pre style="font-family:Consolas;font-size:13;color:black;background:white;"><span style="color:blue;">&lt;</span><span style="color:#a31515;">TransformFile</span><span style="color:blue;">&gt;</span>..\StaticVoid\Web.$(DeployConfiguration).config<span style="color:blue;">&lt;/</span><span style="color:#a31515;">TransformFile</span><span style="color:blue;">&gt;</span></pre>Simply
changing the DeployConfiguration property lets me have test and production builds
which transform things nicely.<br /><br /><h2>Update: the old _CopyWebApplication still works too
</h2>
In Visual Studio 2008 you could use this task:<br /><pre style="font-family:Consolas;font-size:13;color:black;background:white;"><span style="color:blue;">    &lt;</span><span style="color:#a31515;">MSBuild</span><span style="color:blue;"> </span><span style="color:red;">Projects</span><span style="color:blue;">=</span>"<span style="color:blue;">..\StaticVoid\StaticVoid.csproj</span>" <span style="color:blue;">             </span><span style="color:red;">Targets</span><span style="color:blue;">=</span>"<span style="color:blue;">ResolveReferences;_CopyWebApplication</span>" <span style="color:blue;">             </span><span style="color:red;">Properties</span><span style="color:blue;">=</span>"<span style="color:blue;">Configuration=Release;</span><span style="color:blue;">                         WebProjectOutputDir=$(OutputPath);</span><span style="color:blue;">                         OutDir=$(OutputPath)\bin\</span>"<span style="color:blue;"> /&gt;</span></pre>This
still works in Visual Studio 2010's MSBuild (and you don't have a package directory
to delete).<br />
The transforms can still be done manually.<br /><br /><br /><p></p><img width="0" height="0" src="http://martinwilley.com/blog/aggbug.ashx?id=077263aa-3d47-480f-94f1-50ff5689888d" /></div>
    </content>
  </entry>
  <entry>
    <title>Database Schema Reader</title>
    <link rel="alternate" type="text/html" href="http://martinwilley.com/blog/2011/02/14/DatabaseSchemaReader.aspx" />
    <id>http://martinwilley.com/blog/PermaLink,guid,88767024-09a7-413b-abc8-353bcae9b9db.aspx</id>
    <published>2011-02-14T14:02:01.4071885-07:00</published>
    <updated>2011-02-14T14:02:01.4071885-07:00</updated>
    <category term="Database Schema Reader" label="Database Schema Reader" scheme="http://martinwilley.com/blog/CategoryView,category,DatabaseSchemaReader.aspx" />
    <author>
      <name>Martin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
My little <a href="http://dbschemareader.codeplex.com/" target="_blank">Codeplex project</a> has
had a few updates lately, with a new release tonight. This weekend I was transferring
a SqlServer database onto MySQL, so I fixed up the SQL generation capabilities and
added it to the UI. 
</p>
        <p>
Simply, it now can read the SqlServer schema (or almost any other ADO database), and
write out the DDL for a MySQL database. Or an Oracle one. It should also work from
Oracle to SqlServer etc. 
</p>
        <p>
Of course this only works for simple databases. Mine had a couple of uniqueidentifer
columns (GUIDs), which don't translate to anything other than in SqlServer, so that
was fixed up manually. Check constraints can be problematic, and it doesn't touch
views or, God forbid, triggers and stored procedures. It won't roundtrip accurately
(say SqlServer to MySql to SqlServer) because we are generalizing datatypes each time. 
</p>
        <p>
It works on my database. <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://www.martinwilley.com/blog/content/binary/Database-Schema-Reader_13266/wlEmoticon-winkingsmile.png" /></p>
        <img width="0" height="0" src="http://martinwilley.com/blog/aggbug.ashx?id=88767024-09a7-413b-abc8-353bcae9b9db" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Database Schema Reader with codegen</title>
    <link rel="alternate" type="text/html" href="http://martinwilley.com/blog/2011/01/26/DatabaseSchemaReaderWithCodegen.aspx" />
    <id>http://martinwilley.com/blog/PermaLink,guid,55c9b8f0-5ef2-4814-a8b1-1715ca74d944.aspx</id>
    <published>2011-01-26T13:36:04.1330964-07:00</published>
    <updated>2011-01-26T13:36:04.1330964-07:00</updated>
    <author>
      <name>Martin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
I've updated the <a href="http://dbschemareader.codeplex.com/" target="_blank">Database
Schema Reader</a> CodePlex project with <em>basic</em> code generation.
</p>
        <p>
The original code (vintage 2005) did all sorts of things like generating ADO data
access classes and, over I added NHibernate mapping, Castle ActiveRecord, and Enterprise
Library validation block attributes. It's old code (that is, ugly and horrible), so
I stole bits of code and made it just do something a lot simpler.
</p>
        <p>
Now it reads the table schema and turns them into simple POCO classes that are NHibernate
compatible (virtual properties, override Equals and GetHashCode, composite keys are
made into Key classes). There's also (simplistic) NHibernate mapping. And finally
it has .Net 3.5's DataAnnotations for validation.
</p>
        <p>
For quick and simple data-driven code, it's an okay starting point. It is <em>just</em> a
starting point- not a data driven solution. There is a UI, but it's the most basic
one I could design - it's certainly not anything like the Linq2Sql or EF designers
(there are NHibernate mapping designers out there). But once you've got started in
NHibernate you'll prefer to continue in code-first mode anyway.
</p>
        <p>
If your database is a mess (I've seen a few with no primary keys .) it won't be much
help!
</p>
        <img width="0" height="0" src="http://martinwilley.com/blog/aggbug.ashx?id=55c9b8f0-5ef2-4814-a8b1-1715ca74d944" />
      </div>
    </content>
  </entry>
</feed>
