<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <atom:link href="http://rickdrizin.com/rss/" rel="self" type="application/rss+xml"></atom:link>
    <title>Rick Drizin</title>
    <link>http://rickdrizin.com</link>
    <description>You can do anything, but you can&#39;t do everything</description>
    <lastBuildDate>Fri, 03 Apr 2026 22:24:32 GMT</lastBuildDate>
    <image>
      <url>http://rickdrizin.com/images/2020/03/1583853327_3a76ea3fdc3443619eace2e23f7ffc54.jpg</url>
      <title>Rick Drizin</title>
      <link>http://rickdrizin.com</link>
    </image>
    <item>
      <title>Short-circuitable Pipelines</title>
      <link>http://rickdrizin.com/short-circuitable-pipelines</link>
      <description>&lt;h1&gt;Intro&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve been working in a multitenant application where some services need to know what&amp;rsquo;s the current tenant for each request. It would be possible to identify the tenant in upper layers (controllers) and pass that information all the way down to the services, but that generates a lot of repetitive/polluted code. A natural idea is to think about using Dependency Injection to pass this information around.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Injecting Runtime Data into Services&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Immutable data (like connection strings or any other configuration data that is used during app initializatio) are things that certainly need to be injected, and are NOT considered runtime data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Runtime data&lt;/strong&gt; is information that may change across requests, like current logged user, or current tenant (organization).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Using dependency-injection to &lt;strong&gt;inject runtime data&lt;/strong&gt; into your services is a &lt;a href=&#34;https://stackoverflow.com/questions/38291374/getting-the-claimsprincipal-in-a-logic-layer-in-an-aspnet-core-1-application&#34;&gt;common&lt;/a&gt; but controversial practice. The argument in favor of injecting runtime info is that it can improve code readability/maintenance by avoiding having to add a parameter all the way up the chain (in all direct and indirect consumers).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is an example of how we can inject runtime data into our services:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;// Registration&#xA;services.AddTransient&amp;lt;ClaimsPrincipal&amp;gt;(s =&amp;gt;&#xA;    s.GetService&amp;lt;IHttpContextAccessor&amp;gt;().HttpContext.User);&#xA;&#xA;// Usage&#xA;public class MyService&#xA;{&#xA;    public MyService(ClaimsPrincipal user)&#xA;    {&#xA;        // now you have user.Identity.Name;&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the example above&lt;code&gt;ClaimsPrincipal&lt;/code&gt; is calculated by ASP.NET Identity middleware (it&amp;rsquo;s a cheap call based solely on cookies) and it&amp;rsquo;s saved into &lt;code&gt;HttpContext.User&lt;/code&gt;. So whoever calls this service can just invoke it without having to pass the current logged user.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Using the same idea it would be possible to add to the pipeline a middleware to resolve the current tenant and make it available in &lt;code&gt;HttpContext&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;app.Use(async (context, next) =&amp;gt;&#xA;{&#xA;    var context = context.RequestServices&#xA;        .GetRequiredService&amp;lt;IHttpContextAccessor&amp;gt;().HttpContext;&#xA;    var tenant = await ResolveTenantAsync(context);&#xA;    context.Items[&amp;quot;Tenant&amp;quot;] = tenant;&#xA;    await next.Invoke();&#xA;});&#xA;&#xA;// Registration&#xA;services.AddTransient&amp;lt;ITenantContext&amp;gt;(s =&amp;gt;&#xA;    (ITenantContext) s.GetService&amp;lt;IHttpContextAccessor&amp;gt;().HttpContext.Items[&amp;quot;Tenant&amp;quot;]);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The first problem here is that this approach &lt;strong&gt;forces all requests in the pipeline to resolve a Tenant&lt;/strong&gt; (which might be expensive), so unless you really need it in all requests (or unless you can decide based on the request if you need it) then I think it&amp;rsquo;s a better idea to just &lt;strong&gt;rely on DI and let the container resolve your tenant only when required&lt;/strong&gt; (and cache it), instead of resolving in the request pipeline.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The other problem here is that your runtime data have a short lifetime and you don&amp;rsquo;t want to inject that by mistake into objects with a longer lifetime (like singletons). In other words, if &lt;code&gt;MyService&lt;/code&gt; is a singleton then it would be storing internally the identity of the user making the first request, and all subsequent requests (from other users) would be associated to the wrong user, so you will have to correctly (re)define the lifetime of your components.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;So injecting runtime data is a bad idea?&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://stackoverflow.com/questions/22840893/is-this-an-abuse-of-dependency-injection-when-are-dependencies-not-dependencie/&#34;&gt;Many developers believe that&lt;/a&gt; you should not inject runtime data to services. &lt;a href=&#34;https://blogs.cuttingedge.it/steven/posts/2015/code-smell-injecting-runtime-data-into-components/&#34;&gt;This article&lt;/a&gt; explains that components should ideally be &lt;strong&gt;stateless&lt;/strong&gt;, and that runtime data &lt;strong&gt;should not contain behavior&lt;/strong&gt; and should be &lt;strong&gt;passed across methods&lt;/strong&gt; (instead of injected into constructors).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But then the same article explains that passing runtime data across a chain of callers can pollute the code, and shows examples of components that can benefit from having runtime data injected into it (Repository and more specifically Unit of Work).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Injecting runtime data is &lt;strong&gt;especially helpful for lower layers&lt;/strong&gt; (like data-access) because the lowest you go the more layers you would have to modify just to pass repetitive/boilerplate data (all the way up to the layer where the runtime data can be obtained).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To sum we want a solution where we don&amp;rsquo;t need to pass repetitive runtime data through a bunch of layers but where we don&amp;rsquo;t have to directly inject transient runtime data as it would affect the lifetime of our components.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Adapters&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Those problems can be solved writing an &lt;strong&gt;adapter&lt;/strong&gt; to &lt;strong&gt;resolve&lt;/strong&gt; your runtime data (e.g. &lt;strong&gt;identify&lt;/strong&gt; your tenant). &lt;strong&gt;The lifetime mismatch is now handled in a single place&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;public class AspNetTenantAccessor : ITenantAccessor&#xA;{ &#xA;  private IHttpContextAccessor _accessor;&#xA;  public AspNetTenantAccessor(IHttpContextAccessor accessor)&#xA;  {&#xA;    _accessor = accessor;&#xA;  }&#xA;&#xA;  // or maybe Task&amp;lt;AppTenant&amp;gt; GetCurrentTenantAsync()&#xA;  public AppTenant CurrentTenant&#xA;  {&#xA;    get&#xA;    {&#xA;      // resolve (only when required) based on _accessor.HttpContext&#xA;      // cache it (per-request) in _acessor.HttpContext.Items[&amp;quot;Tenant&amp;quot;]&#xA;    }&#xA;  }&#xA;}&#xA;&#xA;// Registrations:&#xA;builder.Services.TryAddSingleton&amp;lt;IHttpContextAccessor, HttpContextAccessor&amp;gt;();&#xA;builder.Services.AddSingleton&amp;lt;ITenantAccessor, AspNetTenantAccessor&amp;gt;();&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now in your service layer you can just inject &lt;code&gt;ITenantAccessor&lt;/code&gt; and get the current tenant (or any other runtime data), and &lt;strong&gt;we won&amp;rsquo;t have runtime dependency-resolution problems&lt;/strong&gt; (we don&amp;rsquo;t need to test if all different consumers are correctly resolving the current tenant).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You may be wondering: Why can&amp;rsquo;t you just inject &lt;code&gt;IHttpContextAccessor&lt;/code&gt; and get the current tenant directly from &lt;code&gt;HttpContext.Items[&amp;quot;Tenant&amp;quot;]&lt;/code&gt;? That&amp;rsquo;s because it would be a &lt;strong&gt;leaky abstraction&lt;/strong&gt; - you don&amp;rsquo;t want your services to be tightly coupled to this Http abstraction (it would be harder to reuse them from other callers like unit tests).&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;So is that the &amp;ldquo;right way&amp;rdquo; of doing it? What does &amp;ldquo;Microsoft tells us to do&amp;rdquo;?&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;In 2015 David Fowler (from ASP.NET Core team) showed an example of how to &lt;a href=&#34;https://github.com/dotnet/aspnetcore/issues/1078&#34;&gt;Inject ClaimsPrincipal in Service Layer&lt;/a&gt; by using an &lt;code&gt;IUserAccessor&lt;/code&gt; adapter (exactly like our example above):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;public class UserAccessor : IUserAccessor&#xA;{ &#xA;      private IHttpContextAccessor _accessor;&#xA;      public UserAccessor(IHttpContextAccessor accessor)&#xA;      {&#xA;           _accessor = accessor;&#xA;      }&#xA;      public ClaimsPrincipal User =&amp;gt; _accessor. HttpContext.User;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;That example alone might be interpreted as if injecting transient runtime data is just plain wrong, but then more recently in 2021 someone suggested that &lt;a href=&#34;https://github.com/dotnet/aspnetcore/issues/33870&#34;&gt;&lt;code&gt;ClaimsPrincipal&lt;/code&gt; should be made available (as injectable) in ASP.NET Core Minimal APIs&lt;/a&gt; (avoiding dependence on &lt;code&gt;IHttpContext(Accessor)&lt;/code&gt;, and the same David Fowler accepted that suggestion and the &lt;a href=&#34;https://github.com/dotnet/aspnetcore/pull/33883/commits/fe899627fc8a462c49ebf762d40efe9bab4205bd&#34;&gt;PR&lt;/a&gt; that registers &lt;code&gt;ClaimsPrincipal&lt;/code&gt; / &lt;code&gt;HttpRequest&lt;/code&gt; / &lt;code&gt;HttpResponse&lt;/code&gt; (they are all transient runtime data) - so this is a hint that the &amp;ldquo;don&amp;rsquo;t inject runtime info&amp;rdquo; rule is not set in stone, and might be just a design choice.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Configurable Pipeline&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;So now I have an &lt;code&gt;ITenantAccessor&lt;/code&gt; interface, and I can switch between multiple implementations.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For ASP.NET I could have an accessor that would identify tenants by the hostname, for local (localhost) debugging or for tests I can use a different accessor that would fake my test tenant.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But then there was another requirement: tenants will be usually identified by their hostnames, but in some cases the same hostname will be shared among all tenants and they should be identified by the request path or by some request header or cookie. So I wanted a configurable &lt;strong&gt;pipeline&lt;/strong&gt; where I can eventually add or remove some steps, and more importantly: I don&amp;rsquo;t need to run all steps - each step may short-circuit the next steps.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The Pipeline Design Pattern is a common design-pattern where we have a Pipeline with a list of steps and they are processed in order, usually one task builds upon the results of the previous task. One nice implementation of this pattern is the ASP.NET Core Request Pipeline, where each step creates (and runs) a Task that receive the next step as input and it can can short-circuit the request (skip the next steps) or it can proceed to the next step in the pipeline. I was familiar with &lt;strong&gt;using&lt;/strong&gt; this request pipeline (e.g. adding middlewares) but I hadn&amp;rsquo;t had a chance to look how it works &lt;strong&gt;internally&lt;/strong&gt;, so I decided to make something similar, which led me to this &lt;a href=&#34;https://stackoverflow.com/questions/76801069/how-does-use-method-finds-next-delegate-in-net-core-middleware/76806222#76806222&#34;&gt;StackOveflow answer&lt;/a&gt; that led me to the source of &lt;a href=&#34;https://github.com/dotnet/aspnetcore/blob/main/src/Http/Http/src/Builder/ApplicationBuilder.cs#L195&#34;&gt;&lt;code&gt;Microsoft.AspNetCore.Builder.ApplicationBuilder.Build()&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Basically this is how it works:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Each step in the pipeline is a &lt;code&gt;Task&lt;/code&gt;, but they are registered as a factory &lt;code&gt;Func&lt;/code&gt; that get the next Task (if any) and create the step &lt;code&gt;Task&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Since those &lt;code&gt;Func&lt;/code&gt; factories always get the next pipeline step (the next &lt;code&gt;Task&lt;/code&gt;) each &lt;code&gt;Task&lt;/code&gt; can decide to run the next step or skip it (short-circuit).&lt;/li&gt;&#xA;&lt;li&gt;The &lt;code&gt;Build()&lt;/code&gt; method starts by creating the Task for the last step, which is a fallback step to check if things went fine or if there is a misconfigured pipeline. Then it goes &lt;strong&gt;in reverse order&lt;/strong&gt; through the previous pipeline steps, chaining each step with the subsequent step. The last &lt;code&gt;Task&lt;/code&gt; created in the loop is actually the first step where the pipeline starts, and that&amp;rsquo;s what&amp;rsquo;s returned by &lt;code&gt;Build()&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Tasks&lt;/code&gt; from ASP.NET request pipeline don&amp;rsquo;t return anything and besides the next &lt;code&gt;Task&lt;/code&gt; they also get &lt;code&gt;HttpContext&lt;/code&gt; as input.&lt;/li&gt;&#xA;&lt;li&gt;In my case I don&amp;rsquo;t get any input but each step can return a Tenant.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Based on that code I&amp;rsquo;ve created a quick implementation to resolve tenants using a generic/configurable pipeline:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;public class PipelineTenantResolver&amp;lt;TTenant&amp;gt; : ITenantAccessor&#xA;{&#xA;    // Steps from my pipeline don&#39;t get anything, &#xA;    // and may short-circuit to return a TTenant&#xA;    public delegate Task&amp;lt;TTenant&amp;gt; IPipelineTenantRepositoryDelegate();&#xA;&#xA;    // Steps from ASP.NET pipeline (for comparison) get HttpContext &#xA;    // but don&#39;t return anything:&#xA;    //public delegate Task RequestDelegate(HttpContext context)&#xA;&#xA;    protected List&amp;lt;Func&amp;lt;IPipelineTenantRepositoryDelegate,&#xA;        IPipelineTenantRepositoryDelegate&amp;gt;&amp;gt; _steps = new();&#xA;&#xA;    // After Build() we cache pipeline first step&#xA;    protected IPipelineTenantRepositoryDelegate? _built;&#xA;&#xA;    public void Use(Func&amp;lt;IPipelineTenantRepositoryDelegate,&#xA;        IPipelineTenantRepositoryDelegate&amp;gt; step)&#xA;    {&#xA;        _steps.Add(step);&#xA;        _built = null;&#xA;    }&#xA;&#xA;    protected IPipelineTenantRepositoryDelegate Build()&#xA;    {&#xA;        // We start building pipeline with last step&#xA;        IPipelineTenantRepositoryDelegate app = () =&amp;gt;&#xA;        {&#xA;            // If we reach the end of the pipeline then no Tenant was found&#xA;            throw new TenantNotFoundException();&#xA;&#xA;            // A non-throwing alternative would be:&#xA;            //return Task.FromResult(default(TTenant)!);&#xA;        };&#xA;&#xA;        // Then we go back passing the next step to each previous step&#xA;        for (var c = _steps.Count - 1; c &amp;gt;= 0; c--)&#xA;            app = _steps[c](app);&#xA;&#xA;        _built = app;&#xA;        return app;&#xA;    }&#xA;&#xA;    public async Task&amp;lt;TTenant?&amp;gt; GetTenantAsync() =&amp;gt; await (_built ?? Build()).Invoke();&#xA;}&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Sample test:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;var pipelineResolver = new PipelineTenantResolver&amp;lt;AppTenant&amp;gt;();&#xA;&#xA;// First step&#xA;Task&amp;lt;AppTenant&amp;gt; resolveTenant = Task.FromResult(new AppTenant());&#xA;pipelineResolver.Use((next) =&amp;gt; {&#xA;    if (shouldShortCircuit)&#xA;        return () =&amp;gt; resolveTenant;&#xA;    return next;&#xA;});&#xA;// next steps...&#xA;//pipelineResolver.Use(next =&amp;gt; next); // etc..&#xA;// Last step (defined in Build()) will just throw&#xA;&#xA;var tenant = await pipelineResolver.GetTenantAsync();&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Finally, in my services registration I register different implementations for &lt;code&gt;ITenantResolver&lt;/code&gt; depending on the entry-point (web app, web api, unit tests, etc), and &lt;code&gt;Task&amp;lt;AppTenant&amp;gt;&lt;/code&gt; is registered with a factory that depends on &lt;code&gt;ITenantResolver.ResolveAsync()&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;builder.Services.AddTransient&amp;lt;Task&amp;lt;AppTenant&amp;gt;&amp;gt;(sp =&amp;gt; sp.GetRequiredService&amp;lt;ITenantAccessor&amp;gt;().ResolveAsync());&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;PS: all code above assumes that resolving a tenant is an async call, that&amp;rsquo;s why I&amp;rsquo;ve registered a &lt;code&gt;Task&amp;lt;&amp;gt;&lt;/code&gt; (if the code wasn&amp;rsquo;t async it would be even easier). If you want to inject directly the resolved &lt;code&gt;AppTenant&lt;/code&gt; (instead of a &lt;code&gt;Task&amp;lt;AppTenant&amp;gt;&lt;/code&gt;) that would be a blocking call (not recommended in constructors) and mixing sync with async (not recommended). In &lt;code&gt;Autofac&lt;/code&gt; that&amp;rsquo;s possible (registering a factory that uses async code), I&amp;rsquo;m not sure if that&amp;rsquo;s also possible in &lt;code&gt;Microsoft.Extensions.DependencyInjection&lt;/code&gt; - but anyway - blocking calls during injection/constructors is not recommended so it&amp;rsquo;s best to inject &lt;code&gt;Task&amp;lt;AppTenant&amp;gt;&lt;/code&gt; instead.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s been a while since I don&amp;rsquo;t write anything, so I hope you enjoyed this article.&lt;/p&gt;&#xA;</description>
      <dc:creator>Rick Drizin</dc:creator>
      <guid isPermaLink="false">e8c24fff-7d9c-4e51-b220-49e58ba3ac6b</guid>
      <pubDate>Thu, 01 Aug 2024 00:39:17 GMT</pubDate>
    </item>
    <item>
      <title>WhatsApp Recovery Tools for Android</title>
      <link>http://rickdrizin.com/whatsapp-recovery-tools-for-android</link>
      <description>&lt;p&gt;A few days ago my wife just deleted by mistake some old videos from our daughter (when she was like saying her first words) which were only stored in her WhatsApp.&#xA;I don&amp;rsquo;t even have to mention how those videos were important to us (she wasn&amp;rsquo;t following my advice about how to backup her media) - so I had to help recover the videos.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Since WhatsApp stores backups in Google Drive I thought I could just uninstall and reinstall and it would get the backups. That WOULD be easy, but her WhatsApp was still using an old phone number from Brazil which wasn&amp;rsquo;t even here with us in America (yeah, I know - she just didn&amp;rsquo;t want to change the number that all her family had, etc). Since we wouldn&amp;rsquo;t be able to reactivate WhatsApp using that old number the first thing I made was updating her number, to allow me to restore from the Google Drive backup of previous week.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;After we updated her WhatsApp number, I disabled backups or else I would be overwriting the backup of the previous week and would lose the videos she was looking for.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So after uninstalling and reinstalling the app, I&amp;rsquo;ve learned the hard way that WhatsApp backups (both the messages and the media) which were taken using one phone number cannot be restored to a new number. So basically I lost not only all her messages but also all her media.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So then I found this great tool which allows us to Extract (download) the full WhatsApp backup from Google Drive:&#xA;&lt;a href=&#34;https://github.com/YuriCosta/WhatsApp-GD-Extractor-Multithread&#34;&gt;https://github.com/YuriCosta/WhatsApp-GD-Extractor-Multithread&lt;/a&gt;.&lt;br&gt;&#xA;Basically you get your device id, then you fill it together with your Google username/password, and the script will download all pictures/videos and even the encrypted backup of the chats (msgstore.db.crypt14).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Then to restore her chat history back we had to change her number again back to the old number in Brazil, and ask her family in Brazil to get the activation code for us, so we could restore from the Google Drive Backup.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the end of the day, I didn&amp;rsquo;t even had to dump the Google Drive backup, but at least I learned something new that can be useful.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;And also, while trying to recover her messages, I learned about this other &lt;a href=&#34;https://github.com/B16f00t/whapa&#34;&gt;whapa&lt;/a&gt; toolkit which contains tools to encrypt or decrypt WhatsApp datastore (requires private key), merge two data stores (merge chat histories from different phones, also requires private key), as well as extracting media from Google Drive (I haven&amp;rsquo;t tested) or iCloud. If you&amp;rsquo;re trying to decrypt new format (15) you may need &lt;a href=&#34;https://github.com/ElDavoo/WhatsApp-Crypt14-Crypt15-Decrypter/blob/main/README.md&#34;&gt;this other tool&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;And last: if you need to extract the private key of your WhatsApp and your Android is not rooted, you can use this tool - &lt;a href=&#34;https://github.com/YuvrajRaghuvanshiS/WhatsApp-Key-Database-Extractor&#34;&gt;https://github.com/YuvrajRaghuvanshiS/WhatsApp-Key-Database-Extractor&lt;/a&gt; (I had to use &lt;code&gt;python wa_kdbe.py --allow-reboot&lt;/code&gt;) which basically will install an old build of WhatsApp and exploit it to dump the private key using adb.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Fun learning anyway.&lt;/p&gt;&#xA;</description>
      <dc:creator>Rick Drizin</dc:creator>
      <guid isPermaLink="false">f2ec463b-c7ba-4049-9389-7cfedff0017c</guid>
      <pubDate>Mon, 11 Jul 2022 23:18:03 GMT</pubDate>
    </item>
    <item>
      <title>Using Multiple Return Values instead of Exceptions</title>
      <link>http://rickdrizin.com/using-multiple-return-values-instead-of-exceptions</link>
      <description>&lt;h1&gt;Exceptions vs Error Codes&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;A question that frequently arises in software engineering is whether/when you should &lt;a href=&#34;https://stackoverflow.com/questions/253314/conventions-for-exceptions-or-error-codes&#34;&gt;throw exceptions or return error codes&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are many different opinions about this subject, and there&amp;rsquo;s a large number of C#/Java developers who &lt;strong&gt;throw Exceptions to indicate all kinds of errors&lt;/strong&gt;. However, there&amp;rsquo;s also a large number of developers who believe that &lt;strong&gt;&lt;a href=&#34;https://stackoverflow.com/a/729404/3606250&#34;&gt;Exceptions should not be used as control flow&lt;/a&gt;&lt;/strong&gt; and argue that exceptions act like  &lt;strong&gt;non-local GOTO statements&lt;/strong&gt; but even more evil because it&amp;rsquo;s difficult to know where the control goes to (some people compare exceptions to &lt;strong&gt;invisible gotos&lt;/strong&gt; or gotos which lead to invisible labels).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://stackoverflow.com/a/46823898/3606250&#34;&gt;I tend to agree with the second group&lt;/a&gt;: I think exceptions are for &lt;strong&gt;unexpected and unhandleable situations&lt;/strong&gt; - when there&amp;rsquo;s nothing I can do with the error code, and the only expected action is to bubble-up the error in the stack and let the upper levels handle it (to display  the error, maybe offer a retry mechanism). This means that for all kinds of &lt;strong&gt;&amp;ldquo;expected errors&amp;rdquo;&lt;/strong&gt; I expect them to be &lt;strong&gt;returned&lt;/strong&gt; by my methods, and &lt;strong&gt;treated&lt;/strong&gt; (or intentionally ignored) by the caller method.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;GO Language: Panic vs Errors, and Explicit Error Checking&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;When talking about Exceptions vs Error Codes I usually mention the GO language which has some clear guidelines about error handling.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One of their design principles is that they have &lt;strong&gt;&amp;ldquo;panic&amp;rdquo;&lt;/strong&gt; for fatal unexpected situations (which is pretty much like Exceptions in Java/C#) and they also have &lt;strong&gt;&amp;ldquo;Errors&amp;rdquo;&lt;/strong&gt; (any object that you return which implements &lt;code&gt;Error&lt;/code&gt; interface) which should be used for regular expected situations. This is pretty much like the distinction which I explained above about when I like to use exceptions and when I like to use error codes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means that the language encourages you to explicitly check for errors where they occur, as opposed to the paradigm that expects you to throw (and catch) exceptions even for expected errors. Since the language has this clear distinction between exceptions and return errors, it has some &lt;a href=&#34;https://blog.golang.org/error-handling-and-go&#34;&gt;conventions and constructs for error handling&lt;/a&gt; that allows developers to easily (and concisely) get and test errors.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Basically, all functions where errors are expected to happen should always return an error object, and if the function is also expected to return some other object (in case of success) then it should use &lt;a href=&#34;https://gobyexample.com/multiple-return-values&#34;&gt;&lt;strong&gt;multiple return values&lt;/strong&gt;&lt;/a&gt; so that it can simultaneously return both the expected result objects (at the first position) and then return the possible errors (at the last position), like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;file, err := os.Open(&amp;quot;filename.txt&amp;quot;)&#xA;if err != nil {&#xA;    // abort the program...&#xA;}&#xA;fmt.Print(string(file))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This &lt;strong&gt;multiple return values&lt;/strong&gt; feature makes the code more concise and it&amp;rsquo;s now also available in C# 7. And by receiving the error as a regular return value our error handling becomes &lt;strong&gt;less verbose&lt;/strong&gt;, &lt;strong&gt;more explicit&lt;/strong&gt;, and &lt;strong&gt;easier to read&lt;/strong&gt; since it uses regular if/else statements.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Another nice convention is that when returning multiple parameters &lt;strong&gt;the return should always be ONE OR ANOTHER&lt;/strong&gt;, meaning that if there&amp;rsquo;s an error you can expect that the other object is null, and vice-versa. A simple convention that makes error handling even easier.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Last, another major benefit of explicitly returning error codes is that &lt;strong&gt;exceptions can easily be ignored while it&amp;rsquo;s much harder to ignore errors if your methods force you to receive the returned error&lt;/strong&gt;. Returning codes obviously don&amp;rsquo;t allow us to bubble-up automatically (as exceptions do), but the idea is exactly that - you want to check (and act) on your errors right where they occur.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Returning Errors as Enums instead of Classes&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;As I&amp;rsquo;ve explained above, errors are about regular expected situations where the caller code should know the possible results and should decide how to handle each possible error. If what you get is a class instance (either as a thrown Exception or as a regular returned object) you really don&amp;rsquo;t know what kind of errors you might receive.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The first problem about using exceptions is that the &lt;strong&gt;caller code (or compiler) doesn&amp;rsquo;t know what exceptions each method may throw&lt;/strong&gt;. Java has &lt;a href=&#34;https://www.geeksforgeeks.org/checked-vs-unchecked-exceptions-in-java/&#34;&gt;checked exceptions&lt;/a&gt; but all other languages learned that &lt;a href=&#34;https://phauer.com/2015/checked-exceptions-are-evil/&#34;&gt;checked exceptions are evil&lt;/a&gt; and don&amp;rsquo;t even have that alternative. Obviously you could describe in your documentation instructions like &lt;em&gt;&amp;ldquo;This CreateUser() method may throw an exception of CreateUserException&amp;rdquo;&lt;/em&gt;, and then the caller code would know what to expect, but what&amp;rsquo;s the point if you could just define what your method returns in the return type?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The second problem about returning classes (either as exceptions or return objects) is that &lt;strong&gt;developers usually design the different errors as subtypes (subtype polymorphism), and the caller code (or compiler) can&amp;rsquo;t know/test for all possible errors&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;try&#xA;{&#xA;    // CreateUserCommand xmldoc will warn me that it may throw a CreateUserCommandException&#xA;    User createdUser = CreateUserCommand(newUserInfo);&#xA;}&#xA;catch (CreateUserCommandException)&#xA;{&#xA;    // How many possibilities do we have here?&#xA;    // Which subtypes should we check?&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;One alternative for this second problem is adding an enum &lt;code&gt;CreateUserCommandErrorEnum&lt;/code&gt; inside &lt;code&gt;CreateUserCommandException&lt;/code&gt;. Then we could use if/switch statements, and the compiler can check if we cover all possible errors. But that looks too complex (both an exception and an enum for each possible method) and without any benefit - in the end it&amp;rsquo;s all about Enums, since there are a predefined number of possible outcomes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To sum, I prefer returning enums directly (instead of throwing exceptions or returning error classes) because:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The caller code is forced to receive the error, &lt;strong&gt;less prone to ignore the possibility of an error&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;The caller code will know in advance all possible errors&lt;/li&gt;&#xA;&lt;li&gt;We can treat the possible errors with &lt;strong&gt;switch statements&lt;/strong&gt; and we can easily &lt;strong&gt;ensure that all possible returns are handled&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;If I add a new possible return in my method, I can even check all callers if they are covering that new value in a switch statement for example.&lt;/li&gt;&#xA;&lt;li&gt;I believe that we should explicitly test for expected errors right where they occur.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Given the reasons above, for the rest of this post I&amp;rsquo;ll assume that your methods are returning errors as enum, like this one:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;public enum CreateUserCommandError&#xA;{&#xA;    USERNAME_NOT_AVAILABLE,&#xA;    WEAK_PASSWORD,&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the next sections I&amp;rsquo;ll show a few different ways of returning multiple parameters in C#.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Using OUT parameters&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Using out parameters is as simple as this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;public User CreateUserCommand(UserDTO newUserInfo, out CreateUserCommandError? error)&#xA;{&#xA;    if (somethingBad)&#xA;    {&#xA;        error = CreateUserCommandError.USERNAME_NOT_AVAILABLE;&#xA;        return null;&#xA;    }&#xA;    // ...&#xA;    error = null; // out parameters need to be assigned even if null&#xA;    return user;&#xA;}&#xA;&#xA;CreateUserCommandError? error = null;&#xA;User createdUser = CreateUserCommand(newUserInfo, out error);&#xA;if (error != null)&#xA;{&#xA;    // early abort..&#xA;}&#xA;LoginUser(createdUser);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the new C# 7 we don&amp;rsquo;t even have to define the out variables anymore, we can use &lt;strong&gt;implicitly typed local variable&lt;/strong&gt; (&lt;strong&gt;&lt;code&gt;out var&lt;/code&gt;&lt;/strong&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;User createdUser = CreateUserCommand(newUserInfo, out var error);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h1&gt;Using regular Tuples&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Using Tuples is a little more verbose, but returns all parameters in a single Tuple object:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;public Tuple&amp;lt;User, CreateUserCommandError?&amp;gt; CreateUserCommand(UserDTO newUserInfo)&#xA;{&#xA;    if (somethingBad)&#xA;        return new Tuple&amp;lt;User, CreateUserCommandError?&amp;gt;(null, CreateUserCommandError.USERNAME_NOT_AVAILABLE);&#xA;    // ...&#xA;    return new Tuple&amp;lt;User, CreateUserCommandError?&amp;gt;(user, null);&#xA;}&#xA;&#xA;var result = CreateUserCommand(newUserInfo);&#xA;if (result.Item2 != null) // Item2 is the Error&#xA;{&#xA;    // early abort..&#xA;}&#xA;LoginUser(result.Item1); // Item1 is the User returned&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h1&gt;Using the new ValueTuple&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;In the new C# 7 there&amp;rsquo;s this new &lt;strong&gt;ValueTuple struct&lt;/strong&gt;, where we can give more &lt;strong&gt;meaningful names to the tuple members&lt;/strong&gt;, and we can also use a &lt;strong&gt;simplified syntax both for creating new ValueTuple and for deconstructing the ValueTuple&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;public (User createdUser, CreateUserCommandError? error) CreateUserCommand(UserDTO newUserInfo)&#xA;{&#xA;    if (somethingBad)&#xA;        return (null, CreateUserCommandError.USERNAME_NOT_AVAILABLE);&#xA;    // ...&#xA;    return (user, null);&#xA;}&#xA;&#xA;var result = CreateUserCommand(newUserInfo);&#xA;// The names &amp;quot;error&amp;quot; and &amp;quot;createdUser&amp;quot; come directly from the method signature above&#xA;if (result.error != null)&#xA;{&#xA;    // early abort..&#xA;}&#xA;LoginUser(result.createdUser);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can deconstruct the ValueTuple in a single statement which can both declare the variables and assign values to them:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;var (user, error) = CreateUserCommand(newUserInfo);&#xA;// or: (var user, var error) = CreateUserCommand(newUserInfo);&#xA;// or: (User user, CreateUserCommandError? error) = CreateUserCommand(newUserInfo);&#xA;&#xA;if (error != null) // Error&#xA;{&#xA;    // early abort..&#xA;}&#xA;LoginUser(user);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h1&gt;Using Generics&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Another popular method is to Wrap your returns in a generic class which wraps both your return object and the possible error (actually it should return ONE OR ANOTHER, but not both).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;public class CommandResult&amp;lt;TEntity, TError&amp;gt;&#xA;        where TEntity : class&#xA;        where TError : struct, Enum&#xA;{&#xA;    public TEntity Entity { get; set; }&#xA;    public TError? Error { get; set; }&#xA;    public bool IsSuccess =&amp;gt; (Error == null);&#xA;&#xA;    // Many developers also include a &amp;quot;Message&amp;quot; property&#xA;    // which usually can be both the success message or the error description&#xA;    // public string Message { get; set; }&#xA;&#xA;    public static CommandResult&amp;lt;TEntity, TError&amp;gt; Success(TEntity entity)&#xA;    {&#xA;        return new CommandResult&amp;lt;TEntity, TError&amp;gt;() { Entity = entity };&#xA;    }&#xA;&#xA;    public static CommandResult&amp;lt;TEntity, TError&amp;gt; Fail(TError errorCode)&#xA;    {&#xA;        return new CommandResult&amp;lt;TEntity, TError&amp;gt;() { Error = errorCode };&#xA;    }&#xA;}&#xA;&#xA;public CommandResult&amp;lt;User, CreateUserCommandError&amp;gt; CreateUserCommand(UserDTO newUserInfo)&#xA;{&#xA;    if (somethingBad)&#xA;        return CommandResult&amp;lt;User, CreateUserCommandError&amp;gt;.Fail(CreateUserCommandError.USERNAME_NOT_AVAILABLE);&#xA;    // ...&#xA;    return CommandResult&amp;lt;User, CreateUserCommandError&amp;gt;.Success(user);&#xA;}&#xA;&#xA;var result = CreateUserCommand(newUserInfo);&#xA;if (result.Error != null) // Error&#xA;{&#xA;    // early abort..&#xA;}&#xA;LoginUser(result.Entity);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Using generics is more verbose than the ValueTuple syntax but it&amp;rsquo;s much more powerful since we can enhance the class with extra information. Later I&amp;rsquo;ll show how to enhance this class with more information.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But this verbose syntax makes me a little annoyed, so let&amp;rsquo;s try to get the best of both solutions&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Combining Generics with the concise ValueTuple Syntax&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;There are a few tricks that we can use to make the Generics version more friendly and less verbose.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;First, inside the &lt;code&gt;CommandResult&amp;lt;&amp;gt;&lt;/code&gt; class we can create an &lt;strong&gt;implicit conversion operator&lt;/strong&gt; that will convert (at the compiler level) a ValueTuple to a &lt;code&gt;CommandResult&amp;lt;&amp;gt;&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;public static implicit operator CommandResult&amp;lt;TEntity, TError&amp;gt;(ValueTuple&amp;lt;TEntity, TError?&amp;gt; tuple)&#xA;{&#xA;    if (tuple.Item1 != null &amp;amp;&amp;amp; tuple.Item2 == null)&#xA;        return Success(tuple.Item1);&#xA;    if (tuple.Item1 == null &amp;amp;&amp;amp; tuple.Item2 != null)&#xA;        return Fail(tuple.Item2.Value);&#xA;    throw new NotImplementedException(&amp;quot;When error is returned you cannot return any other value together&amp;quot;);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Then we can return our results as if they were ValueTuples:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;//return CommandResult&amp;lt;User, CreateUserCommandError&amp;gt;.Fail(CreateUserCommandError.USERNAME_NOT_AVAILABLE);&#xA;return (null, CreateUserCommandError.USERNAME_NOT_AVAILABLE);&#xA;&#xA;//return CommandResult&amp;lt;User, CreateUserCommandError&amp;gt;.Success(user);&#xA;return (user, null);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Inside the &lt;code&gt;CommandResult&amp;lt;&amp;gt;&lt;/code&gt; class we can also &lt;strong&gt;create a deconstruct method&lt;/strong&gt; so that &lt;code&gt;CommandResult&amp;lt;&amp;gt;&lt;/code&gt; can be deconstructed into its two parts:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;public void Deconstruct(out TEntity entity, out TError error) =&amp;gt; (entity, error) = (this.Entity, this.Error);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This mean that we can deconstruct (declare the variables deconstruct the different parts) in a single call like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;var (user, error) = CreateUserCommand(newUserInfo);&#xA;if (error != null) // Error&#xA;{&#xA;    // early abort..&#xA;}&#xA;LoginUser(user);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;So cool and so easy, isn’t it?&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Enhancing the Error enum&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;In all previous examples the returned error was only an enum. In the last example above (Generics with concise syntax) the enum was part of the Generic class:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;public class CommandResult&amp;lt;TEntity, TError&amp;gt;&#xA;        where TEntity : class&#xA;        where TError : struct, Enum&#xA;{&#xA;    public TEntity Entity { get; set; }&#xA;    public TError? Error { get; set; }&#xA;    public ErrorResult&amp;lt;TError&amp;gt; Error { get; set; }&#xA;    public bool IsSuccess =&amp;gt; (Error == null);&#xA;    // ...&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But we can enhance the error object (&lt;code&gt;TError?&lt;/code&gt;) with more information by wrapping in inside another class:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;public class ErrorResult&amp;lt;TError&amp;gt;&#xA;    where TError : struct, Enum&#xA;{&#xA;    /// &amp;lt;summary&amp;gt;&#xA;    /// This MAY or may not be defined (even if an error happened!).&#xA;    /// If this is null, you should check the &amp;lt;see cref=&amp;quot;ValidationErrors&amp;quot;/&amp;gt; to see why the command failed.&#xA;    /// &amp;lt;/summary&amp;gt;&#xA;    public TError? ErrorCode { get; set; }&#xA;    public string ErrorMessage { get; set; }&#xA;    public IList&amp;lt;ValidationError&amp;gt; ValidationErrors;&#xA;}&#xA;public class ValidationError&#xA;{&#xA;    public string PropertyName { get; set; }&#xA;    public string ErrorMessage { get; set; }&#xA;}&#xA;&#xA;public class CommandResult&amp;lt;TEntity, TError&amp;gt;&#xA;        where TEntity : class&#xA;        where TError : struct, Enum&#xA;{&#xA;    public TEntity Entity { get; set; }&#xA;    public ErrorResult&amp;lt;TError&amp;gt; Error { get; set; } // THIS!&#xA;    public bool IsSuccess =&amp;gt; (Error == null);&#xA;    // ...&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This design gives us a few advantages over a simple enum:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;We can add a descriptive &lt;strong&gt;&lt;code&gt;string ErrorMessage&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;We can add a &lt;strong&gt;list of ValidationErrors&lt;/strong&gt; which can be helpful to display in the UI&lt;/li&gt;&#xA;&lt;li&gt;We &lt;strong&gt;don&amp;rsquo;t need to define enums for all possible situations&lt;/strong&gt; - the caller code can just assume that if &lt;code&gt;CommandResult.Error&lt;/code&gt; is non-null then some error happened, and it can use the &lt;code&gt;ErrorMessage&lt;/code&gt; and/or &lt;code&gt;ValidationErrors&lt;/code&gt;. It only needs to test the &lt;code&gt;TError? ErrorResult.ErrorCode&lt;/code&gt; if it needs to handle specific cases - else it can just have this &amp;ldquo;general&amp;rdquo; error handling.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;ValidationErrors&lt;/code&gt; could be filled automatically.&#xA;In my next post, I&amp;rsquo;ll show how this can be done using MediatR pipeline (behaviors) to check for validation errors using &lt;code&gt;FluentValidation&lt;/code&gt; and automatically fill &lt;code&gt;CommandResult.ValidationErrors&lt;/code&gt;, without even hitting our Command Handlers.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Well, at the beginning of this post I wrote that I would return simple enums, and in the end I&amp;rsquo;m returning classes. But basically, this is just a thin wrapper to enhance the enum with additional features - but it doesn&amp;rsquo;t invalidate the downsides that I&amp;rsquo;ve mentioned earlier (about type polymorphism uncertainty, and about how throwing exceptions is bad when you need to handle the outcomes).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Last, this wrapper around &lt;code&gt;ErrorCode&lt;/code&gt; enum shouldn&amp;rsquo;t stop us from doing direct comparisons. We can still compare the error with the enum values as long as we &lt;strong&gt;overload the equality operators&lt;/strong&gt; like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;public static bool operator ==(ErrorResult&amp;lt;TError&amp;gt; left, TError right)&#xA;{&#xA;    return left.ErrorCode != null &amp;amp;&amp;amp; left.ErrorCode.Value.Equals(right)&#xA;}&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;var (user, error) = CreateUserCommand(newUserInfo);&#xA;if (error == CreateUserCommandError.USERNAME_NOT_AVAILABLE) { ... }&#xA;else if (error == CreateUserCommandError.WEAK_PASSWORD) { ... }&#xA;else if (error == null)&#xA;{&#xA;   // ...&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can find &lt;a href=&#34;https://github.com/Drizin/MultipleReturnValues&#34;&gt;full source code here&lt;/a&gt;.&lt;/p&gt;&#xA;</description>
      <dc:creator>Rick Drizin</dc:creator>
      <guid isPermaLink="false">2e8354bb-282a-4758-bc51-34d3be8882fc</guid>
      <pubDate>Sat, 02 Jan 2021 21:28:34 GMT</pubDate>
    </item>
    <item>
      <title>Troubleshooting High CPU in IIS Application Pool</title>
      <link>http://rickdrizin.com/troubleshooting-high-cpu-in-iis-application-pool</link>
      <description>&lt;p&gt;My client had this issue where their web application (deployed across multiple servers) was randomly making the servers unresponsive with 100% cpu usage.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The first action we took was to configure the IIS to automatically recycle the Application Pools when they are using high CPU for more than a few minutes. In the example below we kill AppPools after 3 minutes of using more than 80% cpu.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-powershell&#34;&gt;dir IIS:\AppPools  | ForEach-Object {&#xA;&#x9;Write-Host  &amp;quot;Updating $($_.Name) ...&amp;quot;&#xA;&#xA;&#x9;$appPoolName = $_.Name&#xA;&#x9;$appPool = Get-Item &amp;quot;IIS:\AppPools\$appPoolName&amp;quot;&#xA;&#x9;$appPool.cpu.limit = 80000&#xA;&#x9;$appPool.cpu.action = &amp;quot;KillW3wp&amp;quot;&#xA;&#x9;$appPool.cpu.resetInterval = &amp;quot;00:03:00&amp;quot;&#xA;&#x9;$appPool | Set-Item&#xA;}&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;That solved the problems, servers stopped getting unresponsive, but we had to investigate what was eating all CPU.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;See below how I proceeded with the troubleshooting:&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;1. Create a Memory Dump&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Task Manager - Right Button in the IIS Worker Process, and create a Dump File&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2020/11/1604868090_ecde36d5752d4a31a38a09912d9d92c7.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;2. Install Debug Diagnostic Tool&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Download and install &lt;a href=&#34;https://www.microsoft.com/en-us/download/details.aspx?id=58210&#34;&gt;Debug Diagnostic Tool&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2020/11/1604868196_1acbe937174c412ab78cb64fe13bdb11.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;3. Run Crash &amp;amp; Hang Analysis for ASP.NET / IIS&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Add your dump (DMP) file, select &amp;ldquo;CrashHangAnalysis&amp;rdquo;, and click &amp;ldquo;Start Analysis&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2020/11/1604868378_ee9b937dbab2437e82aae01f5cf123e2.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;4. Review Analysis for Problems&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;The first page immediately suggests that there&amp;rsquo;s a Generic Dictionary&lt;T&gt; which is being used by multiple threads and is blocking one thread.&#xA;&lt;img src=&#34;/images/2020/11/1604868515_04b0addeb30b4011b5e1f411ebef7f21.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A few pages later we can find the threads which are consuming the most of the CPU:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2020/11/1604868532_18aeb453615a4578869b447bc43acaf9.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we check those top threads we can see that both are blocked in the same call which is invoking GetVersion() on an API client-wrapper. One thread is trying to Insert on the dictionary (cache the API version), while the other is trying to Find (FindEntry) on the dictionary.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2020/11/1604868770_26d729ead3d546d7b4c816564b961ab5.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2020/11/1604868770_796fe395e99b47a7978bddcaaf2515de.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;5. What was the issue?&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Long Explanation&lt;/strong&gt;:&lt;br&gt;&#xA;&lt;code&gt;Dictionary&amp;lt;T&amp;gt;&lt;/code&gt; is a HashMap implementation, and like most HashMap implementations it internally uses LinkedLists (to store multiple elements in case different keys result into the same bucket position after being hashed and after taking the hash modulo). The problem is that since &lt;code&gt;Dictionary&amp;lt;T&amp;gt;&lt;/code&gt; is not thread-safe, multiple threads trying to change the dictionary may put it into an invalid state (race condition).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Probably there were different threads trying to add the same element to the dictionary at the same time (invoking &lt;code&gt;Insert&lt;/code&gt; method which internally invokes the &lt;code&gt;Resize&lt;/code&gt; method which modifies the LinkedList), which was putting the LinkedList (and therefore the whole HashMap) into an inconsistent state. If the LinkedList goes into an inconsistent state it can put the threads into an infinite loop, since both &lt;code&gt;Insert()&lt;/code&gt; and &lt;code&gt;FindEntry()&lt;/code&gt; iterate through the LinkedList and &lt;a href=&#34;https://stackoverflow.com/a/33153868/3606250&#34;&gt;could go into an infinite loop&lt;/a&gt; if the LinkedList was inconsistent.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Short Explanation&lt;/strong&gt;:&lt;br&gt;&#xA;Since &lt;code&gt;Dictionary&amp;lt;T&amp;gt;&lt;/code&gt; is not thread-safe, multiple threads trying to change the dictionary may put it into an invalid state (race condition). So if you want to share a dictionary across multiple threads you should use a &lt;code&gt;ConcurrentDictionary&amp;lt;T&amp;gt;&lt;/code&gt; which as the name implies is a thread-safe class.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s a known-issue that concurrent access to Dictionary&lt;T&gt; can cause an infinite-loop and high-CPU in IIS: &lt;a href=&#34;https://www.imzjy.com/blog/fix-high-cpu-caused-by-dictionary-thread-safe-issue&#34;&gt;Link 1&lt;/a&gt;, &lt;a href=&#34;https://blog.bock.rocks/csharp-dictionaries-and-multithreading&#34;&gt;Link 2&lt;/a&gt;, &lt;a href=&#34;https://improve.dk/debugging-in-production-part-1-analyzing-100-cpu-usage-using-windbg/&#34;&gt;Link 3&lt;/a&gt;, &lt;a href=&#34;https://www.toptal.com/dot-net/hunting-high-cpu-usage-in-dot-net&#34;&gt;Link 4&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;6. Advanced Troubleshooting using WinDbg&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;If the Debug Diagnostic Tool didn&amp;rsquo;t gave us any obvious clue about the root cause, we could use WinDbg to inspect a memory dump (it also supports .NET/CLR). &lt;a href=&#34;https://improve.dk/debugging-in-production-part-1-analyzing-100-cpu-usage-using-windbg/&#34;&gt;See example here&lt;/a&gt;.&lt;/p&gt;&#xA;</description>
      <dc:creator>Rick Drizin</dc:creator>
      <guid isPermaLink="false">0deda02a-65ea-4b7c-b1da-9a67ba46cde9</guid>
      <pubDate>Sun, 08 Nov 2020 21:09:34 GMT</pubDate>
    </item>
    <item>
      <title>Install Redis Server on a Windows Server using WSL</title>
      <link>http://rickdrizin.com/install-redis-server-on-a-windows-server-wsl</link>
      <description>&lt;h1&gt;Windows Subsystem for Linux (WSL)&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;If you’re a Windows developer that needs to compile or run Linux binaries in Windows, then the Windows Subsystem for Linux (WSL) is for you. WSL is a tool for developers and sysadmins that need Linux interoperability in Windows.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The most important thing to understand about WSL is that &lt;strong&gt;it isn’t based on virtual machines or containers&lt;/strong&gt; - when you download a supported Linux distro from the Microsoft Store, it doesn’t mean that a virtual machine is created. &lt;strong&gt;What WSL provides is just a layer for mapping Windows kernel system calls to Linux kernel system calls&lt;/strong&gt; - this allows Linux binaries to run in Windows unmodified. WSL also maps Windows services, like the filesystem and networking, as devices that Linux can access.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Instead of using a VM or container, WSL virtualizes a Linux kernel interface on top of the Windows kernel. This means that running WSL only requires a minimal amount of RAM. And when not in use, the WSL driver isn’t loaded into memory, making it much more efficient than a solution based on a VM or container.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Installing WSL and Ubuntu in a Windows Server&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Run this in a Powershell Administrator Prompt (you&amp;rsquo;ll have to reboot after this):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-powershell&#34;&gt;Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Run this in a Powershell Administrator Prompt to install Ubuntu 18.04:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-powershell&#34;&gt;curl.exe -L -o ubuntu-1804.appx https://aka.ms/wsl-ubuntu-1804&#xA;Rename-Item ubuntu-1804.appx ubuntu-1804.zip&#xA;Expand-Archive ubuntu-1804.zip ubuntu1804&#xA;&#xA;cd ubuntu1804&#xA;.\ubuntu1804.exe &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll be asked to choose a Linux username and password.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Installing Redis on Ubuntu (under Windows Server WSL)&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Invoke a bash shell as superuser (for the next commands which require root):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;sudo bash&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;(you&amp;rsquo;ll be asked for administrator&amp;rsquo;s password created earlier)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Update apt-get and install redis:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;apt-get update &amp;amp;&amp;amp; apt-get upgrade&#xA;apt-get install redis-server&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h1&gt;Configuring Redis for external access (Optional)&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;If you&amp;rsquo;ll only use Redis in your internal protected network you don&amp;rsquo;t need this.&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;WSL only provides a translation layer between the Linux apps and the Windows kernel, so some core parts of the Ubuntu system (including networking) are just not there - WSL just translates the Linux system calls into windows ones so the Ubuntu network data flows through the exact same TCP/IP stack as the windows data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means that to open Redis server to other servers (or to the public internet) you just have to configure Redis to listen on the correct interfaces, and open the appropriate ports (there&amp;rsquo;s no need to do &amp;ldquo;port forwarding&amp;rdquo; since this is not a VM with its own networking interfaces).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By default Redis will only bind to loopback (localhost) interfaces. If you open &lt;code&gt;/etc/redis/redis.conf&lt;/code&gt; (by running &lt;code&gt;nano /etc/redis/redis.conf&lt;/code&gt;) you&amp;rsquo;ll find a line like &lt;code&gt;bind 127.0.0.1 ::1&lt;/code&gt; which means that Redis by default listens on ipv4 loopback (&lt;code&gt;127.0.0.1&lt;/code&gt;) and ipv6 loopback (&lt;code&gt;::1&lt;/code&gt;).  Just change it to &lt;code&gt;bind 0.0.0.0 ::1&lt;/code&gt; to make Redis listen in all interfaces (including public IPs), or if it&amp;rsquo;s just for internal network you can add the internal ips in which this server should listen on.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;And in case you&amp;rsquo;re exposing it through the internet you&amp;rsquo;ll also have to open your Windows Firewall ports:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-powershell&#34;&gt;netsh advfirewall firewall add rule name=&amp;quot;Redis Port 6379&amp;quot; dir=in action=allow protocol=TCP localport=6379&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2&gt;Authentication&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re exposing your server to public internet you&amp;rsquo;ll have to configure a password, because by default Redis does not accept external connections without a password.&lt;br&gt;&#xA;Yet in &lt;code&gt;/etc/redis/redis.conf&lt;/code&gt; you just have to uncomment the line &lt;code&gt;requirepass&lt;/code&gt; and set next to it a very-strong password (since it&amp;rsquo;s very fast to run a brute-force attack on a Redis server).&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Start and test server&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Start service:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;sudo service redis-server restart&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To test the service, run &lt;code&gt;redis-cli&lt;/code&gt; and use the following commands:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;AUTH yourstrongpassword  (if you have enabled authentication, above)&#xA;set user:1 &amp;quot;Oscar&amp;quot;&#xA;get user:1&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To stop your server you can use:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;sudo service redis-server stop&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you want to put your Windows Server to automatically start this Linux service on every boot you can configure this command to be executed on every boot:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;C:\windows\system32\wsl.exe -u root service redis-server start&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h1&gt;References:&lt;/h1&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/6476945/how-do-i-run-redis-on-windows/58853971#58853971&#34;&gt;https://stackoverflow.com/questions/6476945/how-do-i-run-redis-on-windows/58853971#58853971&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://computingforgeeks.com/run-linux-on-windows-server/&#34;&gt;https://computingforgeeks.com/run-linux-on-windows-server/&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://petri.com/what-is-windows-subsystem-for-linux-2&#34;&gt;https://petri.com/what-is-windows-subsystem-for-linux-2&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <dc:creator>Rick Drizin</dc:creator>
      <guid isPermaLink="false">71e03058-37fc-4165-b46b-13ea01439ad5</guid>
      <pubDate>Sat, 26 Sep 2020 21:37:20 GMT</pubDate>
    </item>
    <item>
      <title>String Interpolation and Dynamic Query Builder for Dapper</title>
      <link>http://rickdrizin.com/string-interpolation-and-dynamic-query-builder-for-dapper</link>
      <description>&lt;p&gt;We all love &lt;a href=&#34;https://github.com/StackExchange/Dapper/&#34;&gt;Dapper&lt;/a&gt; micro-ORM.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Many developers have realized that although Entity Framework offers some features that Dapper doesn&amp;rsquo;t, Dapper is still more flexible (and much much faster) than EF. And many have realized that the right tool for the right job sometimes involving using both EF for some things and Dapper for others. And one of the usages where Dapper is the king is for building dynamic queries.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Dynamic SQL&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Old-school developers (those who have been coding since the late 90s or early 2000s, probably in VB6, ASP3, or PHP) will probably remember code like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;string sql = &amp;quot;SELECT * FROM [Product] WHERE 1=1&amp;quot;;&#xA;&#xA;if (!string.IsNullOrEmpty(Request[&amp;quot;ProductName&amp;quot;]))&#xA;   sql += &amp;quot; AND Name LIKE &#39;&amp;quot; + Request[&amp;quot;ProductName&amp;quot;].Replace(&amp;quot;&#39;&amp;quot;, &amp;quot;&#39;&#39;&amp;quot;) + &amp;quot;&#39;&amp;quot;; // this replace!&#xA;if (!string.IsNullOrEmpty(Request[&amp;quot;SubCategoryId&amp;quot;]))&#xA;    sql += &amp;quot; AND ProductSubcategoryID = &amp;quot; + Request[&amp;quot;SubCategoryId&amp;quot;].Replace(&amp;quot;&#39;&amp;quot;, &amp;quot;&#39;&#39;&amp;quot;);  // this replace!&#xA;&#xA;// here is where you pray that you&#39;ve correctly sanitized inputs against sql-injection&#xA;var products = cn.Query&amp;lt;Product&amp;gt;(sql);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Basically we were all sending dynamic SQL statements directly to our databases. And since user-input can be malicious (see below), we had to manually sanitize user-input to avoid &lt;a href=&#34;https://en.wikipedia.org/wiki/SQL_injection&#34;&gt;SQL-Injection attacks&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Hello Bobby Tables&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;If you weren&amp;rsquo;t sanitizing your input correctly, you were at serious risk. SQL-injection is probably the most popular web-hacking technique. If you forgot to sanitize something like an &amp;ldquo;id&amp;rdquo; querystring, you could be opening a huge vulnerability and possibly exposing all your database, not only for reading but also for modifications.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2020/08/1596752055_e6b3d1c53cbe4d4083b328a69bbb2f75.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Parameterized SQL&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Even if you&amp;rsquo;re old school (hey VB6 guy, I&amp;rsquo;m looking at you again) you probably know that Dynamically building SQL like that is not only error-prone (vulnerable to SQL-injection) but also does not benefit from &lt;a href=&#34;https://www.sqlshack.com/understanding-sql-server-query-plan-cache/&#34;&gt;SQL Server Cached Execution Plans&lt;/a&gt;. You probably used some kind of code-generation tool which helped you to build code like this (maybe to invoke a stored procedure, since 3-tier-architecture and &amp;ldquo;Windows DNA&amp;rdquo; were in the hype in the early 2000s):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;Dim strSQL As String&#xA;Dim cmd As New ADODB.Command&#xA;&#xA;strSQL = &amp;quot;UPDATE MyTable SET &amp;quot; &amp;amp; vbNewLine _&#xA;    &amp;amp; &amp;quot; NEEDS_ID     = @NEEDS_ID, &amp;quot; &amp;amp; vbNewLine _&#xA;    &amp;amp; &amp;quot; OBJ_ID       = @OBJ_ID, &amp;quot; &amp;amp; vbNewLine _&#xA;    &amp;amp; &amp;quot; OBJ_COMMENTS = @OBJ_COMMENTS, &amp;quot; &amp;amp; vbNewLine _&#xA;    &amp;amp; &amp;quot; TIME21_ID    = @TIME21_ID, &amp;quot; &amp;amp; vbNewLine _&#xA;    &amp;amp; &amp;quot; WHERE ID     = @WHEREID&amp;quot;&#xA;&#xA;With cmd&#xA;    .ActiveConnection = Cn&#xA;    .CommandText = strSQL&#xA;    .Parameters.Append .CreateParameter(&amp;quot;@NEEDS_ID&amp;quot;, adInteger, adParamInput, 2, 12)&#xA;    .Parameters.Append .CreateParameter(&amp;quot;@OBJ_ID&amp;quot;, adInteger, adParamInput, 2, 23)&#xA;    .Parameters.Append .CreateParameter(&amp;quot;@OBJ_COMMENTS&amp;quot;, adVarChar, adParamInput, 250, &amp;quot;Some text&amp;quot;)&#xA;    .Parameters.Append .CreateParameter(&amp;quot;@TIME21_ID&amp;quot;, adInteger, adParamInput, 2, 34)&#xA;    .Parameters.Append .CreateParameter(&amp;quot;@ID&amp;quot;, adInteger, adParamInput, 18, 456)&#xA;    .Execute&#xA;End With &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I hope the millennial developers are not so surprised that parameterized SQL already existed in the past century.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Back to modern software&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Time flew by, Java and .NET emerged (and maybe submerged a little?), Reflection, Bytecode emission, Full-ORMs, Micro-ORMs, 3-tier was deprecated in favor of dozens of modern architectures, and now database access is much easier, right?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now we don&amp;rsquo;t have to manually describe each one of our parameters to SQL. Our favorite ORMs will do that for us.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Dapper Example:&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;var dynamicParams = new DynamicParameters();&#xA;&#xA;string sql = &amp;quot;SELECT * FROM [Product] WHERE 1=1&amp;quot;;&#xA;&#xA;if (productName != null)&#xA;{&#xA;    sql += &amp;quot; AND Name LIKE @productName&amp;quot;; &#xA;    dynamicParams.Add(&amp;quot;productName&amp;quot;, productName);&#xA;}&#xA;&#xA;&#xA;if (subCategoryId != null)&#xA;{&#xA;    sql += &amp;quot; AND ProductSubcategoryID = @subCategoryId&amp;quot;; &#xA;    dynamicParams.Add(&amp;quot;subCategoryId&amp;quot;, subCategoryId);&#xA;}&#xA;&#xA;var products = cn.Query&amp;lt;Product&amp;gt;(sql, dynamicParams);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h1&gt;Don&amp;rsquo;t Repeat Yourself&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;The example below makes me a little upset for 2 reasons:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I have to pass productName twice, both to the &lt;code&gt;sql&lt;/code&gt; string and to the &lt;code&gt;dynamicParams&lt;/code&gt; dictionary.&lt;br&gt;&#xA;Their names should match.&lt;/li&gt;&#xA;&lt;li&gt;I have to keep those two variables (the SQL statement and the list of parameters) separated, even though they are closely related to each other.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h1&gt;String Interpolation Internals&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://weblog.west-wind.com/posts/2016/Dec/27/Back-to-Basics-String-Interpolation-in-C&#34;&gt;String Interpolation&lt;/a&gt; was introduced in C# in 2016.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Instead of doing code like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;string name = &amp;quot;Rick&amp;quot;;&#xA;int accesses = 10;&#xA;string output = string.Format(&amp;quot;{0}, you&#39;ve been here {1:n0} times.&amp;quot;,&#xA;                              name, accesses);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You could do like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;string name = &amp;quot;Rick&amp;quot;;&#xA;int accesses = 10;&#xA;string output = $&amp;quot;{name}, you&#39;ve been here {accesses:n0} times.&amp;quot;;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Internally, when you write an interpolated string (starting with &lt;code&gt;$&lt;/code&gt;), the compiler generates a &lt;code&gt;FormattableString&lt;/code&gt; class, which contains both the template (as if it was &lt;code&gt;{0}, you&#39;ve been here {1:n0} times.&lt;/code&gt;), and also the list of parameters (&lt;code&gt;string name&lt;/code&gt; and &lt;code&gt;int accesses&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If your method expects a regular string, the &lt;code&gt;FormattableString&lt;/code&gt; will be implicitly converted into a regular string, and you get the same behavior as if you just passed a &lt;code&gt;string.format&lt;/code&gt; to your method. However, if your method expects a &lt;code&gt;FormattableString&lt;/code&gt; class, then you have access to format and arguments isolated from each other.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;FormattableString can be useful for example if we wanted to build parameterized SQL statements while letting users build their strings as if it was just regular string concatenation:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;QueryBuilder ParseSQL(FormattableString query)&#xA;{&#xA;    QueryBuilder myWrapper = new QueryBuilder();&#xA;&#xA;    string dapperSql = query.Format;&#xA;    // replace {0} by &amp;quot;@p0&amp;quot;, &#xA;    // replace {1} by &amp;quot;@p1&amp;quot;, etc..&#xA;    myWrapper.SQL = dapperSql;&#xA;&#xA;    var dapperArgs = new Dapper.DynamicParameters();&#xA;    var args = query.GetArguments();&#xA;    // dapperArgs.Add(&amp;quot;p0&amp;quot;, args[0]);&#xA;    // dapperArgs.Add(&amp;quot;p1&amp;quot;, args[1]); ...&#xA;    myWrapper.Arguments = dapperArgs;&#xA;&#xA;    return myWrapper;&#xA;    // now anyone can use Dapper like  &#xA;    // var pocos = connection.Query&amp;lt;POCO&amp;gt;(myWrapper.SQL, myWrapper.Parameters);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h1&gt;DapperQueryBuilder&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Based on the idea above, I&amp;rsquo;ve created &lt;strong&gt;&lt;a href=&#34;https://github.com/Drizin/DapperQueryBuilder/&#34;&gt;DapperQueryBuilder&lt;/a&gt; - which is a simple wrapper around Dapper which allows us to pass SQL parameters using string interpolation.&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can code like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;var query = cn.QueryBuilder($&amp;quot;SELECT * FROM [Product] WHERE 1=1&amp;quot;);&#xA;&#xA;if (productName != null)&#xA;    query.Append($&amp;quot;AND Name LIKE {productName}&amp;quot;); &#xA;&#xA;if (subCategoryId != null)&#xA;    query.Append($&amp;quot;AND ProductSubcategoryID = {subCategoryId}&amp;quot;); &#xA;&#xA;var products = query.Query&amp;lt;Product&amp;gt;(); &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Although it looks like you&amp;rsquo;re just building a dynamic SQL (with values as inline literals), actually what you get is parameterized SQL.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In case, &lt;code&gt;query&lt;/code&gt; will have this underlying statement: &lt;code&gt;SELECT * FROM [Product] WHERE 1=1 AND Name LIKE @p0 AND ProductSubcategoryId = @p1&lt;/code&gt;, and will also hold the parameters &lt;code&gt;@p0 = productName&lt;/code&gt; and &lt;code&gt;@p1 = subCategoryId&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To sum, instead of using Dapper&amp;rsquo;s extension &lt;code&gt;.Query&amp;lt;T&amp;gt;&lt;/code&gt; which extends IDbConnection and accepts a SQL string and a list of parameters, you use &lt;code&gt;QueryBuilder()&lt;/code&gt; extension which creates a QueryBuilder where you can dynamically (and in a single statement) add new parameters and add the associated SQL clause.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Quickstart&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;If you liked and want to start using right now,&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Install the &lt;a href=&#34;https://www.nuget.org/packages/Dapper-QueryBuilder&#34;&gt;NuGet package Dapper-QueryBuilder&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;Start using like this:&lt;br&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;using DapperQueryBuilder;&#xA;// ...&#xA;&#xA;cn = new SqlConnection(connectionString);&#xA;&#xA;// If you have all your parameters at once and just want to benefit from string interpolation:&#xA;var products = cn.QueryBuilder($@&amp;quot;&#xA;    SELECT ProductId, Name, ListPrice, Weight&#xA;    FROM [Product]&#xA;    WHERE [ListPrice] &amp;lt;= {maxPrice}&#xA;    AND [Weight] &amp;lt;= {maxWeight}&#xA;    AND [Name] LIKE {search}&#xA;    ORDER BY ProductId&amp;quot;).Query&amp;lt;Product&amp;gt;();&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Or building dynamic conditions like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;using DapperQueryBuilder;&#xA;// ...&#xA;&#xA;cn = new SqlConnection(connectionString);&#xA;&#xA;// If you want to dynamically add conditions&#xA;var q = cn.QueryBuilder($@&amp;quot;&#xA;    SELECT ProductId, Name, ListPrice, Weight&#xA;    FROM [Product]&#xA;    WHERE 1=1 &amp;quot;);&#xA;&#xA;q.AppendLine(&amp;quot;AND [ListPrice] &amp;lt;= {maxPrice}&amp;quot;);&#xA;q.AppendLine(&amp;quot;AND [Weight] &amp;lt;= {maxWeight}&amp;quot;);&#xA;q.AppendLine(&amp;quot;AND [Name] LIKE {search}&amp;quot;);&#xA;q.AppendLine(&amp;quot;ORDER BY ProductId&amp;quot;);&#xA;&#xA;var products = q.Query&amp;lt;Product&amp;gt;();&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h1&gt;Filters list&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Some people believe incorrectly that &lt;code&gt;WHERE 1=1&lt;/code&gt; causes a performance hit. &lt;a href=&#34;https://dba.stackexchange.com/a/33958/85815&#34;&gt;It doesn&amp;rsquo;t.&lt;/a&gt; So using this fake condition is a great trick so that you can just append additional conditions (if any) like shown in the example above.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Another option is that you can build your whole query but leave the filters to be dynamically defined (and rendered) later. DapperQueryBuilder has this special command &lt;code&gt;Where()&lt;/code&gt; which is used to save the filters internally, and later they are replaced.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;int maxPrice = 1000;&#xA;int maxWeight = 15;&#xA;string search = &amp;quot;%Mountain%&amp;quot;;&#xA;&#xA;var cn = new SqlConnection(connectionString);&#xA;&#xA;// You can build the query manually and just use QueryBuilder to replace &amp;quot;where&amp;quot; filters (if any)&#xA;var q = cn.QueryBuilder(@&amp;quot;SELECT ProductId, Name, ListPrice, Weight&#xA;    FROM [Product]&#xA;    /**where**/&#xA;    ORDER BY ProductId&#xA;    &amp;quot;);&#xA;    &#xA;// You just pass the parameters as if it was an interpolated string, &#xA;// and QueryBuilder will automatically convert them to Dapper parameters (injection-safe)&#xA;q.Where($&amp;quot;[ListPrice] &amp;lt;= {maxPrice}&amp;quot;);&#xA;q.Where($&amp;quot;[Weight] &amp;lt;= {maxWeight}&amp;quot;);&#xA;q.Where($&amp;quot;[Name] LIKE {search}&amp;quot;);&#xA;&#xA;// Query() will automatically build your query and replace your /**where**/ (if any filter was added)&#xA;var products = q.Query&amp;lt;Product&amp;gt;();&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can also create OR filters like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;q.Where(new Filters(Filters.FiltersType.OR)&#xA;{&#xA;    new Filter($&amp;quot;[Weight] &amp;lt;= {maxWeight}&amp;quot;),&#xA;    new Filter($&amp;quot;[Name] LIKE {search}&amp;quot;)&#xA;});&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Or you can mix and match OR/AND like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;q.Where(new Filters(Filters.FiltersType.OR)&#xA;{&#xA;    new Filters(Filters.FiltersType.AND)&#xA;    {&#xA;        $&amp;quot;[Weight] &amp;lt;= {maxWeight}&amp;quot;,&#xA;        $&amp;quot;[Weight] &amp;gt;= {minWeight}&amp;quot;,&#xA;    }&#xA;    new Filter($&amp;quot;[Name] LIKE {search}&amp;quot;)&#xA;});&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;And even arrays can be used as interpolated strings:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;var categories = new string[] { &amp;quot;Components&amp;quot;, &amp;quot;Clothing&amp;quot;, &amp;quot;Acessories&amp;quot; };&#xA;q.Append($&amp;quot;WHERE c.[Name] IN {categories}&amp;quot;);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h1&gt;Fluent API (Chained-methods)&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;For those who like method-chaining guidance (or for those who allow end-users to build their own queries), there&amp;rsquo;s a Fluent API that allows you to build queries step-by-step mimicking dynamic SQL concatenation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So, basically, instead of starting with a full query and just appending new filters (.Where()), the QueryBuilder will build the whole query for you:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;var q = cn.QueryBuilder()&#xA;    .Select($&amp;quot;ProductId&amp;quot;)&#xA;    .Select($&amp;quot;Name&amp;quot;)&#xA;    .Select($&amp;quot;ListPrice&amp;quot;)&#xA;    .Select($&amp;quot;Weight&amp;quot;)&#xA;    .From($&amp;quot;[Product]&amp;quot;)&#xA;    .Where($&amp;quot;[ListPrice] &amp;lt;= {maxPrice}&amp;quot;)&#xA;    .Where($&amp;quot;[Weight] &amp;lt;= {maxWeight}&amp;quot;)&#xA;    .Where($&amp;quot;[Name] LIKE {search}&amp;quot;)&#xA;    .OrderBy($&amp;quot;ProductId&amp;quot;);&#xA;    &#xA;var products = q.Query&amp;lt;Product&amp;gt;();&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You would get this query:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;SELECT ProductId, Name, ListPrice, Weight&#xA;FROM [Product]&#xA;WHERE [ListPrice] &amp;lt;= @p0 AND [Weight] &amp;lt;= @p1 AND [Name] LIKE @p2&#xA;ORDER BY ProductId&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Hope you enjoyed this post as much as I did when I wrote this library!&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Full source code &lt;a href=&#34;https://github.com/Drizin/DapperQueryBuilder/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&#xA;</description>
      <dc:creator>Rick Drizin</dc:creator>
      <guid isPermaLink="false">b51d536d-34e4-4945-886a-13aa30ef5113</guid>
      <pubDate>Thu, 06 Aug 2020 23:01:05 GMT</pubDate>
    </item>
    <item>
      <title>Code Generation in C# / CSX - Extracting SQL Server Schema</title>
      <link>http://rickdrizin.com/code-generation-in-c-csx-extracting-sql-server-schema</link>
      <description>&lt;p&gt;&lt;strong&gt;This is the second part of a multi-part post series I&amp;rsquo;m going to write about Code Generation using C#&lt;/strong&gt;.&#xA;In the &lt;a href=&#34;https://drizin.io/code-generation-csx-scripts-part1/&#34;&gt;previous part&lt;/a&gt; I&amp;rsquo;ve shown how to invoke C# Scripts (and CSX files) from PowerShell and Visual Studio. In this part, &lt;strong&gt;I&amp;rsquo;ll create a simple extractor to read the physical schema of a SQL Server Database and save it as a JSON file&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Creating the Project&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;The first step is creating a .NET project&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Running CSX scripts do not require csproj (or Visual Studio), but it&amp;rsquo;s very helpful to have a csproj for many reasons:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;You get intellisense (mostly on CS, not so much on CSX - so try to use CSX as little as possible)&lt;/li&gt;&#xA;&lt;li&gt;You can check for compilation-errors&lt;/li&gt;&#xA;&lt;li&gt;You can configure a Console App (or any other entry point) to launch and debug your scripts&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;csproj is required for automatically restoring NuGet packages&lt;/strong&gt; (although if you already have the NuGet packages you may just use them without csproj)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;All libraries which I&amp;rsquo;ll use in my generator (Dapper and Newtonsoft) are compatible with netstandard2.0.&lt;br&gt;&#xA;This means that the project type can be either &lt;strong&gt;.NET Framework&lt;/strong&gt; (net472, which used to be called &amp;ldquo;full framework&amp;rdquo;) or .NET Core (netcore21 or netcore31) - both should work.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;NuGet Packages&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ll use two third-party libraries: &lt;strong&gt;Dapper&lt;/strong&gt; (micro-ORM, for loading objects from SQL Queries) and &lt;strong&gt;Newtonsoft.Json&lt;/strong&gt; (JSON library, just for serialization). All we need is their dlls, but the easiest way to getting those is by installing their NuGet packages to our csproj (which will automatically install those packages to anyone who tries to build our csproj, so it&amp;rsquo;s hassle-free collaboration among multiple developers).&lt;br&gt;&#xA;If you&amp;rsquo;re not using Visual Studio IDE you can install those packages by running&lt;br&gt;&#xA;&lt;code&gt;dotnet add package Dapper&lt;/code&gt; and  &lt;code&gt;dotnet add package Newtonsoft.Json&lt;/code&gt;&lt;br&gt;&#xA;in the same folder of your csproj.&lt;br&gt;&#xA;If you&amp;rsquo;re using Visual Studio you can use the &lt;strong&gt;Package Manager Console&lt;/strong&gt; and run this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Install-Package Dapper&#xA;Install-Package Newtonsoft.Json&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h1&gt;Sql Server Schema objects&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Next, I&amp;rsquo;ll create my objects that will represent my physical SQL database. One important thing to remember is that C# scripting engines do NOT allow the use of namespaces.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;SqlServerTable.cs&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;using System;&#xA;using System.Collections.Generic;&#xA;&#xA;public class SqlServerTable&#xA;{&#xA;    public string Database { get; set; }&#xA;    public string TableSchema { get; set; }&#xA;    public string TableName { get; set; }&#xA;&#xA;    /// &amp;lt;summary&amp;gt;&#xA;    /// Can be &amp;quot;TABLE&amp;quot; or &amp;quot;VIEW&amp;quot;&#xA;    /// &amp;lt;/summary&amp;gt;&#xA;    public string TableType { get; set; }&#xA;&#xA;    public string TableDescription { get; set; }&#xA;&#xA;    public List&amp;lt;SqlServerColumn&amp;gt; Columns { get; set; } = new List&amp;lt;SqlServerColumn&amp;gt;();&#xA;&#xA;    /// &amp;lt;summary&amp;gt;&#xA;    /// FKs which point from THIS (Child) table to the primary key of OTHER (Parent) tables&#xA;    /// &amp;lt;/summary&amp;gt;&#xA;    public List&amp;lt;SqlServerForeignKey&amp;gt; ForeignKeys { get; set; } = new List&amp;lt;SqlServerForeignKey&amp;gt;();&#xA;&#xA;    /// &amp;lt;summary&amp;gt;&#xA;    /// FKs which point from OTHER (Child) tables to the primary key of THIS (Parent) table&#xA;    /// &amp;lt;/summary&amp;gt;&#xA;    public List&amp;lt;SqlServerForeignKey&amp;gt; ChildForeignKeys { get; set; } = new List&amp;lt;SqlServerForeignKey&amp;gt;();&#xA;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ll omit other classes for brevity, but you can refer to all code &lt;a href=&#34;x&#34;&gt;here&lt;/a&gt; (classes &lt;a href=&#34;x&#34;&gt;SqlServerColumn.cs&lt;/a&gt;, &lt;a href=&#34;x&#34;&gt;SqlServerForeignKey.cs&lt;/a&gt;, &lt;a href=&#34;x&#34;&gt;SqlServerForeignKeyMember.cs&lt;/a&gt; ).&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Schema Reader&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Finally, I&amp;rsquo;ll create the class which will read SQL metadata - &lt;strong&gt;SqlServerSchemaReader.cs&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;using Dapper;&#xA;using System;&#xA;using System.Data;&#xA;using System.IO;&#xA;using System.Linq;&#xA;&#xA;public class SqlServerSchemaReader&#xA;{&#xA;  public Func&amp;lt;IDbConnection&amp;gt; CreateDbConnection { get; set; }&#xA;&#xA;  public SqlServerSchemaReader(Func&amp;lt;IDbConnection&amp;gt; createDbConnection)&#xA;  {&#xA;    CreateDbConnection = createDbConnection;&#xA;  }&#xA;&#xA;  public void ExportSchemaToJSON(string outputJsonSchema)&#xA;  {&#xA;    Console.WriteLine(&amp;quot;Reading Database...&amp;quot;);&#xA;&#xA;    using (var cn = CreateDbConnection())&#xA;    {&#xA;      var tables = cn.Query&amp;lt;SqlServerTable&amp;gt;(@&amp;quot;&#xA;        SELECT &#xA;          t.TABLE_CATALOG as [Database], &#xA;          t.TABLE_SCHEMA as [TableSchema], &#xA;          t.TABLE_NAME as [TableName], &#xA;          CASE WHEN t.TABLE_TYPE=&#39;VIEW&#39; THEN &#39;VIEW&#39; ELSE &#39;TABLE&#39; END as [TableType],&#xA;          ep.value as [TableDescription]&#xA;&#x9;&#x9;    FROM  INFORMATION_SCHEMA.TABLES t&#xA;&#x9;&#x9;    INNER JOIN sys.schemas sc ON t.TABLE_SCHEMA = sc.[name]&#xA;          ... full code omitted for brevity - please refer to: &#xA;          ... https://github.com/Drizin/CodegenCS/tree/master/src/CodegenCS.SqlServer&#xA;      &amp;quot;).AsList();&#xA;&#xA;      var allColumns = cn.Query&amp;lt;SqlServerColumn&amp;gt;(@&amp;quot;&#xA;          ... full code omitted for brevity... &#xA;      &amp;quot;).AsList();&#xA;&#xA;      var fks = cn.Query&amp;lt;SqlServerForeignKey&amp;gt;(@&amp;quot;&#xA;          ... full code omitted for brevity... &#xA;      &amp;quot;).AsList();&#xA;&#xA;      var fkCols = cn.Query&amp;lt;SqlServerForeignKeyMember&amp;gt;(@&amp;quot;&#xA;          ... full code omitted for brevity... &#xA;      &amp;quot;).AsList();&#xA;      foreach (var fk in fks)&#xA;      {&#xA;        fk.Columns = fkCols.Where(c =&amp;gt; &#xA;            c.ForeignKeyConstraintName == fk.ForeignKeyConstraintName &amp;amp;&amp;amp; &#xA;            c.FKTableSchema == fk.FKTableSchema&#xA;        ).OrderBy(c =&amp;gt; c.PKColumnOrdinalPosition).ToList();&#xA;      }&#xA;&#xA;      foreach (var table in tables)&#xA;      {&#xA;        table.Columns = allColumns.Where(c =&amp;gt; c.TableSchema == table.TableSchema &amp;amp;&amp;amp; c.TableName == table.TableName).ToList();&#xA;        foreach(var column in table.Columns)&#xA;          column.ClrType = GetClrType(table, column);&#xA;        table.Columns.ForEach(c =&amp;gt; { c.Database = null; c.TableSchema = null; c.TableName = null; });&#xA;&#xA;        // We copy FKs and remove redundant properties of the parent object (table) which we&#39;re attaching this FK into&#xA;        table.ForeignKeys = Clone(fks.Where(fk =&amp;gt; fk.FKTableSchema == table.TableSchema &amp;amp;&amp;amp; fk.FKTableName == table.TableName).ToList());&#xA;        table.ForeignKeys.ForEach(fk =&amp;gt; { fk.FKTableSchema = null; fk.FKTableName = null; });&#xA;&#xA;        // We copy FKs and remove redundant properties of the parent object (table) which we&#39;re attaching this FK into&#xA;        table.ChildForeignKeys = Clone(fks.Where(fk =&amp;gt; fk.PKTableSchema == table.TableSchema &amp;amp;&amp;amp; fk.PKTableName == table.TableName).ToList());&#xA;        table.ChildForeignKeys.ForEach(fk =&amp;gt; { fk.PKTableSchema = null; fk.PKTableName = null; });&#xA;&#xA;      }&#xA;&#xA;      SqlServerDatabaseSchema schema = new SqlServerDatabaseSchema()&#xA;      {&#xA;        LastRefreshed = DateTimeOffset.Now,&#xA;        Tables = tables,&#xA;      };&#xA;&#xA;      Console.WriteLine($&amp;quot;Saving into {outputJsonSchema}...&amp;quot;);&#xA;      File.WriteAllText(outputJsonSchema, Newtonsoft.Json.JsonConvert.SerializeObject(schema, Newtonsoft.Json.Formatting.Indented));&#xA;    }&#xA;&#xA;    Console.WriteLine(&amp;quot;Success!&amp;quot;);&#xA;  }&#xA;&#xA;  string GetClrType(SqlServerTable table, SqlServerColumn column)&#xA;  {&#xA;    string sqlDataType = column.SqlDataType;&#xA;    switch (sqlDataType)&#xA;    {&#xA;      case &amp;quot;bigint&amp;quot;:&#xA;        return typeof(long).FullName;&#xA;      case &amp;quot;smallint&amp;quot;:&#xA;        return typeof(short).FullName;&#xA;      case &amp;quot;int&amp;quot;:&#xA;        return typeof(int).FullName;&#xA;      case &amp;quot;uniqueidentifier&amp;quot;:&#xA;        return typeof(Guid).FullName;&#xA;      case &amp;quot;smalldatetime&amp;quot;:&#xA;      case &amp;quot;datetime&amp;quot;:&#xA;      case &amp;quot;datetime2&amp;quot;:&#xA;      case &amp;quot;date&amp;quot;:&#xA;      case &amp;quot;time&amp;quot;:&#xA;        return typeof(DateTime).FullName;&#xA;      case &amp;quot;datetimeoffset&amp;quot;:&#xA;        return typeof(DateTimeOffset).FullName;&#xA;      case &amp;quot;float&amp;quot;:&#xA;        return typeof(double).FullName;&#xA;      case &amp;quot;real&amp;quot;:&#xA;        return typeof(float).FullName;&#xA;      case &amp;quot;numeric&amp;quot;:&#xA;      case &amp;quot;smallmoney&amp;quot;:&#xA;      case &amp;quot;decimal&amp;quot;:&#xA;      case &amp;quot;money&amp;quot;:&#xA;        return typeof(decimal).FullName;&#xA;      case &amp;quot;tinyint&amp;quot;:&#xA;        return typeof(byte).FullName;&#xA;      case &amp;quot;bit&amp;quot;:&#xA;        return typeof(bool).FullName;&#xA;      case &amp;quot;image&amp;quot;:&#xA;      case &amp;quot;binary&amp;quot;:&#xA;      case &amp;quot;varbinary&amp;quot;:&#xA;      case &amp;quot;timestamp&amp;quot;:&#xA;        return typeof(byte[]).FullName;&#xA;      case &amp;quot;nvarchar&amp;quot;:&#xA;      case &amp;quot;varchar&amp;quot;:&#xA;      case &amp;quot;nchar&amp;quot;:&#xA;      case &amp;quot;char&amp;quot;:&#xA;      case &amp;quot;text&amp;quot;:&#xA;      case &amp;quot;ntext&amp;quot;:&#xA;      case &amp;quot;xml&amp;quot;:&#xA;        return typeof(string).FullName;&#xA;      default:&#xA;        Console.WriteLine($&amp;quot;Unknown sqlDataType for {table.TableName}.{column.ColumnName}: {sqlDataType}&amp;quot;);&#xA;        return null;&#xA;&#xA;      // Vendor-specific types&#xA;      case &amp;quot;hierarchyid&amp;quot;:&#xA;        return &amp;quot;Microsoft.SqlServer.Types.SqlHierarchyId&amp;quot;; // requires Microsoft.SqlServer.Types.dll (EF or Dapper 1.34+)&#xA;      case &amp;quot;geography&amp;quot;:&#xA;        return &amp;quot;Microsoft.SqlServer.Types.SqlGeography&amp;quot;;  // requires Microsoft.SqlServer.Types.dll (EF or Dapper 1.32+)&#xA;      case &amp;quot;geometry&amp;quot;:&#xA;        return &amp;quot;Microsoft.SqlServer.Types.SqlGeometry&amp;quot;;  // requires Microsoft.SqlServer.Types.dll (EF or Dapper 1.33)+&#xA;    }&#xA;  }&#xA;&#xA;  public static T Clone&amp;lt;T&amp;gt;(T source)&#xA;  {&#xA;    var serialized = JsonConvert.SerializeObject(source);&#xA;    return JsonConvert.DeserializeObject&amp;lt;T&amp;gt;(serialized);&#xA;  }&#xA;&#xA;}&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h1&gt;CSX&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;The idea is that we should put as much as possible into &lt;code&gt;.cs&lt;/code&gt; files (and as little as possible in &lt;code&gt;csx&lt;/code&gt; script), since intellisense and compile-time checks work better than in the CSX. The script file &lt;strong&gt;RefreshDatabaseSchema.csx&lt;/strong&gt; will basically load libraries, define connection strings and paths, and invoke SqlServerSchemaReader.cs:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;&#xA;/// This CSX Script will invoke SqlServerSchemaReader, which extracts the schema of SQL database and saves into a JSON file.&#xA;/// The easiest way to launch csi.exe (which is shipped with Visual Studio) to run this script is by using PowerShell script RefreshDatabaseSchema.ps1&#xA;/// You can do that from Visual Studio (see instructions in RefreshDatabaseSchema.ps1) or you can just execute &amp;quot;Powershell RefreshDatabaseSchema.ps1&amp;quot;&#xA;/// &amp;lt;/summary&amp;gt;&#xA;&#xA;// System libraries&#xA;#r &amp;quot;System.Data.dll&amp;quot;&#xA;&#xA;// Load 3rd-party libraries by their relative paths, relative to &amp;quot;$Env:userprofile\.nuget\packages\&amp;quot;&#xA;#r &amp;quot;dapper\2.0.35\lib\netstandard2.0\Dapper.dll&amp;quot;&#xA;#r &amp;quot;newtonsoft.json\12.0.3\lib\netstandard2.0\Newtonsoft.Json.dll&amp;quot;&#xA;&#xA;// CS files are better than CSX because Intellisense and Compile-time checks works better. &#xA;#load &amp;quot;SqlServerTable.cs&amp;quot;&#xA;#load &amp;quot;SqlServerColumn.cs&amp;quot;&#xA;#load &amp;quot;SqlServerForeignKey.cs&amp;quot;&#xA;#load &amp;quot;SqlServerForeignKeyMember.cs&amp;quot;&#xA;#load &amp;quot;SqlServerDatabaseSchema.cs&amp;quot;&#xA;#load &amp;quot;SqlServerSchemaReader.cs&amp;quot;&#xA;&#xA;using System;&#xA;using System.IO;&#xA;using System.Runtime.CompilerServices;&#xA;using System.Data;&#xA;using System.Data.SqlClient;&#xA;&#xA;// Helpers to get the location of the current CSX script&#xA;public static string GetScriptPath([CallerFilePath] string path = null) =&amp;gt; path;&#xA;public static string GetScriptFolder([CallerFilePath] string path = null) =&amp;gt; Path.GetDirectoryName(path);&#xA;&#xA;&#xA;// location relative to the CSX script&#xA;string outputJsonSchema = Path.GetFullPath(Path.Combine(GetScriptFolder(), &amp;quot;AdventureWorksSchema.json&amp;quot;)); &#xA;string connectionString = @&amp;quot;Data Source=MYWORKSTATION\SQLEXPRESS;&#xA;                            Initial Catalog=AdventureWorks;&#xA;                            Integrated Security=True;&amp;quot;;&#xA;&#xA;Func&amp;lt;IDbConnection&amp;gt; connectionFactory = () =&amp;gt; new SqlConnection(connectionString);&#xA;var reader = new SqlServerSchemaReader(connectionFactory);&#xA;reader.ExportSchemaToJSON(outputJsonSchema);&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h1&gt;Powershell&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Last, I&amp;rsquo;ll create a PowerShell to invoke the CSX file, which is useful because it can locate the csi.exe in multiple locations and because it can provide to csi.exe the location of per-user NuGet packages, so that CSX can load libraries by their relative-locations, without having to hard-code user-specific folders. &lt;strong&gt;RefreshDatabaseSchema.ps1&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-powershell&#34;&gt;# To Execute Powershell Scripts from Visual Studio:&#xA;# 1) Right-button PS1 file - &amp;quot;Open With...&amp;quot;&amp;quot;&#xA;# 2) Configure:&#xA;#      Program: Powershell.exe&#xA;#      Arguments: -noexit -File %1&#xA;#      Friendly Name: Execute PowerShell Script&#xA;&#xA;# To execute CSX scripts you&#39;ll need CSI.EXE (C# REPL) which is shipped with Visual Studio&#xA;# but can also be installed by using the NuGet package Microsoft.Net.Compilers.Toolset - https://www.nuget.org/packages/Microsoft.Net.Compilers.Toolset/&#xA;&#xA;# For more info about launching CSX scripts from PowerShell or from Visual Studio, check https://drizin.io/code-generation-csx-scripts-part1/&#xA;&#xA;$dir = Split-Path $MyInvocation.MyCommand.Path &#xA;$script = Join-Path $dir &amp;quot;.\RefreshDatabaseSchema.csx&amp;quot;&#xA;&#xA;&#xA;# Locate CSI.EXE by searching common paths&#xA;$csi = ( &#xA;    &amp;quot;$Env:userprofile\.nuget\packages\microsoft.net.compilers.toolset\3.6.0\tasks\net472\csi.exe&amp;quot;,&#xA;    &amp;quot;$Env:programfiles (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Roslyn\csi.exe&amp;quot;,&#xA;    &amp;quot;$Env:programfiles (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\Roslyn\csi.exe&amp;quot;,&#xA;    &amp;quot;$Env:programfiles (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Roslyn\csi.exe&amp;quot;,&#xA;    &amp;quot;$Env:programfiles (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\Roslyn\csi.exe&amp;quot;,&#xA;    &amp;quot;$Env:programfiles (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\Roslyn\csi.exe&amp;quot;,&#xA;    &amp;quot;$Env:programfiles (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\Roslyn\csi.exe&amp;quot;&#xA;) | Where-Object { Test-Path $_ } | Select-Object -first 1&#xA;&#xA;if (!$csi)&#xA;{&#xA;    Write-Host &amp;quot;---------------------------------------&amp;quot; -for red&#xA;    Write-Host &amp;quot;Can&#39;t find csi.exe&amp;quot; -for red&#xA;    Write-Host &amp;quot;Please fix search paths above, or install NuGet Microsoft.Net.Compilers.Toolset&amp;quot; -for red&#xA;    Write-Host &amp;quot;---------------------------------------&amp;quot; -for red&#xA;    Exit 1&#xA;}&#xA;&#xA;&#xA;$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()&#xA;&#xA;Write-host &amp;quot;Starting csi.exe $script ...&amp;quot; -for yellow&#xA;&amp;amp; $csi /lib:&amp;quot;$Env:userprofile\.nuget\packages\&amp;quot; $script&#xA;&#xA;Write-Host &amp;quot;Finished in $($stopwatch.Elapsed.TotalMilliSeconds) milliseconds&amp;quot;&#xA;&#xA;# Since I configured &amp;quot;-noexit&amp;quot; parameter in Visual Studio I don&#39;t need this&#xA;#if ($host.Name -notmatch &#39;ISE&#39;) { Write-Host -NoNewLine &amp;quot;(Just press Enter to exit)&amp;quot; -for cyan; read-host; }  &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Running Powershell:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2020/07/1593969610_a9fb0bd0ee174dbabbdb72ab66b9af8c.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Result file &lt;strong&gt;AdventureWorksSchema.json&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2020/07/1593969618_4304d846a25842dc8fd9fbe57aa3eaa9.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Full Source code available &lt;a href=&#34;x&#34;&gt;here&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;This is the second part of a multi-part post series I&amp;rsquo;m going to write about Code Generation using C#&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Part 1 - &lt;a href=&#34;https://drizin.io/code-generation-csx-scripts-part1/&#34;&gt;Code Generation in Pure C# (and CSX scripts) directly from inside Visual Studio&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;Part 2 - &lt;a href=&#34;https://drizin.io/code-generation-in-c-csx-extracting-sql-server-schema/&#34;&gt;Extracting SQL Server Schema&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <dc:creator>Rick Drizin</dc:creator>
      <guid isPermaLink="false">22e1c561-d412-4b45-9ca7-a019ff5f365d</guid>
      <pubDate>Sun, 05 Jul 2020 16:35:40 GMT</pubDate>
    </item>
    <item>
      <title>Code Generation in Pure C# (and CSX scripts) directly from inside Visual Studio</title>
      <link>http://rickdrizin.com/code-generation-csx-scripts-part1</link>
      <description>&lt;p&gt;&lt;strong&gt;This is the first part of a multi-part post series I&amp;rsquo;m going to write about Code Generation using C#&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve mentioned &lt;a href=&#34;https://drizin.io/yet-another-code-generator/&#34;&gt;before&lt;/a&gt; that I&amp;rsquo;ve been a fan of code generation for a long-time. I have used &lt;a href=&#34;https://www.codesmithtools.com/product/generator&#34;&gt;CodeSmith generator&lt;/a&gt;,  &lt;a href=&#34;http://mygeneration.sourceforge.net/&#34;&gt;MyGeneration Code Generator&lt;/a&gt;, and in the past few years, I&amp;rsquo;ve been using &lt;a href=&#34;https://docs.microsoft.com/en-us/visualstudio/modeling/writing-a-t4-text-template?view=vs-2019&#34;&gt;T4 templates&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The main advantage of code generation (which includes &lt;strong&gt;DB scaffolding&lt;/strong&gt;, also called &lt;strong&gt;database first&lt;/strong&gt; by some ORMs) is that it does the work for you, is repeatable, and &lt;strong&gt;less error-prone&lt;/strong&gt; than manually writing everything. So it&amp;rsquo;s mostly about productivity and consistency. &lt;strong&gt;If you&amp;rsquo;re writing repetitive code by hand, you&amp;rsquo;re stealing from your employer or clients&lt;/strong&gt;. And if you have a data-oriented application, almost certainly you have repetitive code to some degree.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;The right tool for the job&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Until recently the gold standard for code generation in Microsoft stack was using &lt;a href=&#34;https://docs.microsoft.com/en-us/visualstudio/modeling/writing-a-t4-text-template?view=vs-2019&#34;&gt;T4 templates&lt;/a&gt;, which is the out-of-the-box tool provided by Microsoft and shipped with Visual Studio. The major problem with T4 is that it has terrible syntax, terrible tooling and debugging support, and can get as ugly as this:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2020/07/1593787605_376bc2e84f6d43f183dabab464c72259.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;C# Script Files (CSX files)&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;In the search of a modern code-generation tool I&amp;rsquo;ve explored Razor Templates, Mustache, and Mustache-like templates (like DotLiquid and Handlebars), and others. I&amp;rsquo;ve noticed that there&amp;rsquo;s a growing popularity of using C# code (Roslyn or not) to do the code-generation using pure C# - which makes sense, since you can get &lt;strong&gt;strong typing&lt;/strong&gt;, &lt;strong&gt;compile-time checking&lt;/strong&gt;, &lt;strong&gt;full IDE support&lt;/strong&gt; (with &lt;strong&gt;debugging&lt;/strong&gt;), &lt;strong&gt;cross-platform&lt;/strong&gt; (dotnet core), full access to all .NET Framework (SqlServer, Dapper, Newtonsoft JSON, etc). So you get a full-fledged language instead of using a templating-engine which only offers a subset of features of the underlying language.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;C# Script Files (CSX) were introduced with Roslyn, and can be executed in Roslyn or in other compatible cross-platform &lt;a href=&#34;https://stackoverflow.com/a/25406049/3606250&#34;&gt;scripting engines&lt;/a&gt; like &lt;a href=&#34;https://github.com/filipw/dotnet-script&#34;&gt;dotnet-script&lt;/a&gt; or even with &lt;a href=&#34;https://docs.microsoft.com/en-us/archive/msdn-magazine/2016/january/essential-net-csharp-scripting&#34;&gt;C# REPL&lt;/a&gt; called &lt;code&gt;csi.exe&lt;/code&gt;.&#xA;Those scripting engines certainly have some limitations (like using namespaces), but they allow us to virtually invoke any C# code, with essential features like loading external assemblies, loading code organized across multiple source files, etc. And it&amp;rsquo;s much easier than using &lt;a href=&#34;https://stackoverflow.com/a/11572108/3606250&#34;&gt;Powershell&lt;/a&gt; to invoke C#.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Sample CSX Script&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;CSX scripts inside Visual Studio have some support for Intellisense (auto-completion) and compile-time checks, but those features work much better in CS files. So it&amp;rsquo;s a good idea to put as much as possible into cs files and as little as possible in CSX scripts. I like to use CSX only for basic things like loading libraries, setting connection strings, settings paths, and invoking the real code in CS files.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;MyProgram.cs&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;public class MyProgram&#xA;{&#xA;   public void MyMethod()&#xA;   {&#xA;      Console.WriteLine(&amp;quot;Hello from MyMethod&amp;quot;);&#xA;   }  &#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;MyScript.csx&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;#load &amp;quot;MyProgram.cs&amp;quot; &#xA;&#xA;new MyProgram().MyMethod(); &#xA;Console.WriteLine(&amp;quot;Hello Code-Generation!&amp;quot;);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h1&gt;Running CSX Script using C# REPL (CSI.EXE)&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Visual Studio ships with a &lt;a href=&#34;https://www.hanselman.com/blog/InteractiveCodingWithCAndFREPLsScriptCSOrTheVisualStudioInteractiveWindow.aspx&#34;&gt;command line REPL called &lt;strong&gt;CSI&lt;/strong&gt;&lt;/a&gt; that &lt;a href=&#34;https://stackoverflow.com/q/38060860/3606250&#34;&gt;can be used to run &lt;code&gt;.csx&lt;/code&gt; scripts&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can run CSI.EXE directly from Visual Studio Developer Command Prompt (&lt;code&gt;csi MyScript.csx&lt;/code&gt;):&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2020/07/1593791279_1861afc753cc46eba981cbc2787851cb.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2020/07/1593791293_87f444c17ee1483db9ea490b617a510b.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Assembly References&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;In the same sense that it&amp;rsquo;s a good idea to use simple statements in CSX to invoke more complex CS code, it&amp;rsquo;s also a good idea to load external assemblies when you can rely on existing libraries.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;CSX allows loading assembly references&lt;/strong&gt; by using the #r directive in the top of your scripts:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;// CSI.EXE requires absolute paths for loading external assemblies: &#xA;#r &amp;quot;C:\Users\drizin\.nuget\packages\dapper\2.0.35\lib\netstandard2.0\Dapper.dll&amp;quot; &#xA;&#xA;#load &amp;quot;File1.cs&amp;quot; &#xA;#load &amp;quot;File2.cs&amp;quot; &#xA;#load &amp;quot;MyProgram.cs&amp;quot; &#xA;&#xA;new MyProgram().MyMethod(); &#xA;Console.WriteLine(&amp;quot;Hello Code-Generation!&amp;quot;);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h1&gt;NuGet Packages&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;If you need to reference a NuGet package, you can just rely on NuGet tools (and Visual Studio build process) to automatically restore the packages required by your script. For achieving that, you can &lt;strong&gt;just add the CSX as part of a Visual Studio project, so when each developer tries to build the project Visual Studio will download the missing packages&lt;/strong&gt;, and the developer just needs to fix the assemblies location.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Another alternative, which does not require to use csproj at all, is using PowerShell to download the required nugets (see script at the end of this post).&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Invoking C# REPL (CSI running CSX scripts) from PowerShell&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Although you can run CSI.exe directly from Visual Studio Developer Command Prompt, invoking it through PowerShell is very helpful for a few reasons:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;You can run outside of Visual Studio. You don&amp;rsquo;t even need Visual Studio to run CSX.&lt;/li&gt;&#xA;&lt;li&gt;Allows us to find NuGet locations and reference external assemblies with relative paths on the CSX (more about this below).&lt;/li&gt;&#xA;&lt;li&gt;Restoring NuGet files (example script at the end of the post)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;To invoke CSI using Powershell, we must know the location of csi.exe.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;CSI is shipped with Visual Studio but can also be installed by using the NuGet package &lt;a href=&#34;https://www.nuget.org/packages/Microsoft.Net.Compilers.Toolset/&#34;&gt;Microsoft.Net.Compilers.Toolset&lt;/a&gt; (&lt;strong&gt;warning&lt;/strong&gt;: as &lt;a href=&#34;https://stackoverflow.com/a/47371408/3606250&#34;&gt;described here&lt;/a&gt; the installation script for the package changes .csproj file to use the compiler provided by the package - this is likely not what you want, so make sure to roll-back such changes if they are made during installation).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So the first step is to search for csi.exe in multiple locations as I show in the sample Powershell script &lt;strong&gt;RunMyScript.ps1&lt;/strong&gt; below:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-powershell&#34;&gt;# Locate CSI.EXE by searching common paths&#xA;$csi = ( &#xA;    &amp;quot;$Env:userprofile\.nuget\packages\microsoft.net.compilers.toolset\3.6.0\tasks\net472\csi.exe&amp;quot;,&#xA;    &amp;quot;$Env:programfiles (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Roslyn\csi.exe&amp;quot;,&#xA;    &amp;quot;$Env:programfiles (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\Roslyn\csi.exe&amp;quot;,&#xA;    &amp;quot;$Env:programfiles (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Roslyn\csi.exe&amp;quot;,&#xA;    &amp;quot;$Env:programfiles (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\Roslyn\csi.exe&amp;quot;,&#xA;    &amp;quot;$Env:programfiles (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\Roslyn\csi.exe&amp;quot;,&#xA;    &amp;quot;$Env:programfiles (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\Roslyn\csi.exe&amp;quot;&#xA;) | Where-Object { Test-Path $_ } | Select-Object -first 1&#xA;&#xA;$dir = Split-Path $MyInvocation.MyCommand.Path &#xA;$script = Join-Path $dir &amp;quot;MyScript.csx&amp;quot;&#xA;&#xA;&amp;amp; $csi $script&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To launch the PowerShell script from the command line, it&amp;rsquo;s just about running &lt;code&gt;Powershell Full-Path-To-Your-Script-ps1&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Running from Visual Studio IDE&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To run from Visual Studio, you can just add the PS1 to your project or solution, right-click the file, and click the option &amp;ldquo;&lt;strong&gt;Open with PowerShell ISE&lt;/strong&gt;&amp;rdquo;, which is the IDE for editing/running PowerShell scripts.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2020/07/1593793796_8fd2ea9192454b6499042526255be39d.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Another alternative is that you can add new actions to your right-button actions -&#xA;you can click &amp;ldquo;&lt;strong&gt;Open With&amp;hellip;&lt;/strong&gt;&amp;rdquo; and configure PowerShell to be executed directly from Visual Studio:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2020/07/1593793804_cf2bf4560e2943c8b930c491dcd2ed02.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The list of possible actions will include this new option of invoking PS1 scripts directly from the IDE, and you can also set this as the default action for opening PS1 files.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2020/07/1593793812_247544fbb0494bf9a5370e048b2f1231.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Allowing Unsigned Scripts&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you have never executed unsigned PowerShell scripts you&amp;rsquo;ll have to enable PowerShell unsigned scripts by running Powershell as Administrator and running this command:&lt;br&gt;&#xA;&lt;code&gt;Set-ExecutionPolicy -ExecutionPolicy Unrestricted&lt;/code&gt;.&lt;br&gt;&#xA;Don&amp;rsquo;t forget to enable for both &lt;code&gt;Windows PowerShell&lt;/code&gt; (64-bits) and for &lt;code&gt;Windows PowerShell (x86)&lt;/code&gt;, which is the one that is invoked from inside Visual Studio IDE.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2020/07/1593798755_53ec77215ec44c508036a7b4c8db0d97.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Relative Assembly References&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;As we&amp;rsquo;ve seen before, CSX accepts absolute references like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;#r &amp;quot;C:\Users\drizin\.nuget\packages\dapper\2.0.35\lib\netstandard2.0\Dapper.dll&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;One of the major problems with CSI is that the &lt;code&gt;#r&lt;/code&gt; directive  (for loading assembly references) doesn&amp;rsquo;t accept &lt;a href=&#34;https://github.com/dotnet/roslyn/issues/5654&#34;&gt;nuget-like references&lt;/a&gt; or environment variables so &lt;strong&gt;all assembly references should be specified with full paths&lt;/strong&gt;. This is not a showstopper but it&amp;rsquo;s a little annoying since it makes it harder to share code among multiple developers since each developer would have to fix their references.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One of the advantages of using PowerShell (as described above) is that &lt;strong&gt;we can use environment-variables and use #r directive with relative paths&lt;/strong&gt;. In the PowerShell script, we just have to locate the &lt;strong&gt;base path&lt;/strong&gt; where your assemblies are located and pass that to CSI so it can use this folder to search for referenced assemblies, like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-powershell&#34;&gt;$assemblies = &amp;quot;${env:userprofile}\.nuget\packages\&amp;quot;;&#xA;&amp;amp; $csi /lib:&amp;quot;$assemblies&amp;quot; $script&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;And then in the CSX, you can use relative paths like this&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;#r &amp;quot;dapper\2.0.35\lib\netstandard2.0\Dapper.dll&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h1&gt;PackageReference (NuGet 4) vs packages.config (NuGet 3)&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;The new MSBuild format (&amp;ldquo;SDK-Style&amp;rdquo;, which uses PackageReference inside the csproj) installs the NuGet packages in this per-user folder.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The old MSBuild format (&amp;ldquo;non-SDK-Style&amp;rdquo;, before Visual Studio 2017, which uses packages.config) installs the NuGet packages in the &amp;ldquo;packages&amp;rdquo; folder under the Solution folder.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We can adjust our PowerShell scripts according to where our project will restore NuGet packages:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-powershell&#34;&gt;$csi = ... # (locate your csi.exe)&#xA;$dir = Split-Path $MyInvocation.MyCommand.Path &#xA;$script = Join-Path $dir &amp;quot;MyScript.csx&amp;quot;&#xA;&#xA;# Call csi.exe and specify that libraries referenced by #r directives &#xA;# should search in a few nuget locations&#xA;&#xA;# New NuGet 4.0+ (PackageReference) saves User-specific packages&#xA;# in &amp;quot;%userprofile%\.nuget\packages\&amp;quot;&#xA;$nuget1 = &amp;quot;${env:userprofile}\.nuget\packages\&amp;quot;;&#xA;&#xA;# New NuGet 4.0+ (PackageReference) saves Machine-wide packages &#xA;# in &amp;quot;%ProgramFiles(x86)%\Microsoft SDKs\NuGetPackages\&amp;quot;&#xA;$nuget2 = &amp;quot;${env:ProgramFiles(x86)}\Microsoft SDKs\NuGetPackages\&amp;quot;;&#xA;&#xA;# Old NuGet (packages.config) saves packages in &amp;quot;\packages&amp;quot; folder at solution level.&#xA;# Locate by searching a few levels above&#xA;$nuget3 = ( &#xA;    (Join-Path $dir &amp;quot;.\packages\&amp;quot;),&#xA;    (Join-Path $dir &amp;quot;..\packages\&amp;quot;),&#xA;    (Join-Path $dir &amp;quot;..\..\packages\&amp;quot;),&#xA;    (Join-Path $dir &amp;quot;..\..\..\packages\&amp;quot;),&#xA;    (Join-Path $dir &amp;quot;..\..\..\..\packages\&amp;quot;)&#xA;) | Where-Object { Test-Path $_ } | Select-Object -first 1&#xA;&#xA;# if you&#39;re using new NuGet format (PackageReference defined inside csproj) &#xA;&amp;amp; $csi /lib:&amp;quot;$nuget1&amp;quot; $script  &#xA;&#xA;# if you&#39;re using old NuGet format (packages.config)&#xA;# &amp;amp; $csi /lib:&amp;quot;$nuget3&amp;quot; $script  &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;And our CSX would use relative references:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;// CSX can load libraries by defining their relative paths&#xA;&#xA;// New NuGets (PackageReference) are installed under &amp;quot;${env:userprofile}\.nuget\packages\&amp;quot; &#xA;// or &amp;quot;${env:ProgramFiles(x86)}\Microsoft SDKs\NuGetPackages\&amp;quot;)&#xA;// and have this format:&#xA;#r &amp;quot;dapper\2.0.35\lib\netstandard2.0\Dapper.dll&amp;quot;&#xA;&#xA;// Old NuGets (packages.config) are installed under &amp;quot;(SolutionFolder)\packages&amp;quot;&#xA;// and have this format&#xA;// #r &amp;quot;Dapper.2.0.35\lib\netstandard2.0\Dapper.dll&amp;quot;&#xA;&#xA;//...&#xA;new MyProgram().MyMethod();&#xA;Console.WriteLine(&amp;quot;Hello Code-Generation!&amp;quot;);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;So cool and so easy, isn’t it?&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Other tools&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;I have played with other tools like &lt;a href=&#34;https://github.com/filipw/dotnet-script&#34;&gt;dotnet-script&lt;/a&gt;, &lt;a href=&#34;https://github.com/yevhen/Nake&#34;&gt;nake&lt;/a&gt;, and the popular &lt;a href=&#34;https://github.com/scriptcs/scriptcs&#34;&gt;scriptcs&lt;/a&gt;. For different reasons I couldn&amp;rsquo;t make any of them work fine (some weren&amp;rsquo;t even installing in a traditional .net framework project, some had complex methods for using nugets, and some simply weren&amp;rsquo;t working (not finding include files, etc)). So I decided to stick with the plain csi.exe, which most users will already have installed.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Final PowerShell Script&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;This script below has some nice features:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Allows to search for assemblies in multiple paths, including all NuGet locations&lt;/li&gt;&#xA;&lt;li&gt;Can pass multiple paths to csi.exe, even though csi does not accept spaces in paths&lt;/li&gt;&#xA;&lt;li&gt;Can restore missing NuGet packages (will even download nuget.exe)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-powershell&#34;&gt;# To Execute Powershell Scripts from Visual Studio:&#xA;# 1) Right-button PS1 file - &amp;quot;Open With...&amp;quot;&amp;quot;&#xA;# 2) Configure:&#xA;#      Program: Powershell.exe&#xA;#      Arguments: -noexit -File %1&#xA;#      Friendly Name: Execute PowerShell Script&#xA;&#xA;# To execute CSX scripts you&#39;ll need CSI.EXE (C# REPL) which is shipped with Visual Studio&#xA;# but can also be installed by using the NuGet package Microsoft.Net.Compilers.Toolset - https://www.nuget.org/packages/Microsoft.Net.Compilers.Toolset/&#xA;&#xA;# For more info about launching CSX scripts from PowerShell or from Visual Studio, check https://drizin.io/code-generation-csx-scripts-part1/&#xA;&#xA;$dir = Split-Path $MyInvocation.MyCommand.Path &#xA;$script = Join-Path $dir &amp;quot;.\GenerateSimplePOCOs.csx&amp;quot;&#xA;$requiredLibs = @(&#xA;    @{ Name = &amp;quot;Newtonsoft.Json&amp;quot;; Version = &amp;quot;12.0.3&amp;quot; },&#xA;    @{ Name = &amp;quot;CodegenCS&amp;quot;; Version = &amp;quot;1.0.5&amp;quot; }&#xA;);&#xA;&#xA;# By default we&#39;ll only use NuGet 4 locations. But you can change to 3 if you&#39;re hosting &#xA;# your scripts in a project with the old packages.config format and want to rely on existing project packages&#xA;$NuGetVersion = 4; &#xA;&#xA;&#xA;&#xA;$ErrorActionPreference = &amp;quot;Stop&amp;quot;&#xA;&#xA;# Locate CSI.EXE by searching common paths&#xA;$csi = ( &#xA;    &amp;quot;$Env:userprofile\.nuget\packages\microsoft.net.compilers.toolset\3.6.0\tasks\net472\csi.exe&amp;quot;,&#xA;    &amp;quot;$Env:programfiles (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Roslyn\csi.exe&amp;quot;,&#xA;    &amp;quot;$Env:programfiles (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\Roslyn\csi.exe&amp;quot;,&#xA;    &amp;quot;$Env:programfiles (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Roslyn\csi.exe&amp;quot;,&#xA;    &amp;quot;$Env:programfiles (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\Roslyn\csi.exe&amp;quot;,&#xA;    &amp;quot;$Env:programfiles (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\Roslyn\csi.exe&amp;quot;,&#xA;    &amp;quot;$Env:programfiles (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\Roslyn\csi.exe&amp;quot;&#xA;) | Where-Object { Test-Path $_ } | Select-Object -first 1&#xA;&#xA;if (!$csi)&#xA;{&#xA;    Write-Host &amp;quot;---------------------------------------&amp;quot; -for red&#xA;    Write-Host &amp;quot;Can&#39;t find csi.exe&amp;quot; -for red&#xA;    Write-Host &amp;quot;Please fix search paths above, or install NuGet Microsoft.Net.Compilers.Toolset&amp;quot; -for red&#xA;    Write-Host &amp;quot;---------------------------------------&amp;quot; -for red&#xA;    Exit 1&#xA;}&#xA;Write-Host &amp;quot;Found csi.exe: $csi&amp;quot; -for cyan&#xA;&#xA;# List of locations to search for assembly references&#xA;$libPaths = @()&#xA;$libPaths += $dir&#xA;&#xA;if ($NuGetVersion -eq 4)&#xA;{&#xA;    # New NuGet 4.0+ (PackageReference) saves User-specific packages in %userprofile%\.nuget\packages\&#xA;    $libPaths += &amp;quot;${env:userprofile}\.nuget\packages&amp;quot;;&#xA;    if (Test-Path &amp;quot;${env:userprofile}\.nuget\packages&amp;quot;) { $missingNuGetPackagesLocation = &amp;quot;${env:userprofile}\.nuget\packages&amp;quot; }&#xA;&#xA;    # New NuGet 4.0+ (PackageReference) saves Machine-wide packages in %ProgramFiles(x86)%\Microsoft SDKs\NuGetPackages\&amp;quot;&#xA;    $libPaths += &amp;quot;${env:ProgramFiles(x86)}\Microsoft SDKs\NuGetPackages&amp;quot;;&#xA;}&#xA;&#xA;if ($NuGetVersion -eq 3)&#xA;{&#xA;    # Old NuGet (packages.config) saves packages in &amp;quot;\packages&amp;quot; folder at solution level.&#xA;    # Locate by searching a few levels above the script&#xA;    $missingNuGetPackagesLocation = ( &#xA;        (Join-Path $dir &amp;quot;.\packages&amp;quot;),&#xA;        (Join-Path $dir &amp;quot;..\packages&amp;quot;),&#xA;        (Join-Path $dir &amp;quot;..\..\packages&amp;quot;),&#xA;        (Join-Path $dir &amp;quot;..\..\..\packages&amp;quot;),&#xA;        (Join-Path $dir &amp;quot;..\..\..\..\packages&amp;quot;)&#xA;    ) | Where-Object { Test-Path $_ } | Select-Object -first 1&#xA;    $libPaths += $missingNuGetPackagesLocation&#xA;}&#xA;&#xA;# where to download missing NuGet packages&#xA;if ((Test-Path $missingNuGetPackagesLocation) -eq $false)&#xA;{&#xA;    $missingNuGetPackagesLocation = $dir&#xA;}&#xA;&#xA;&#xA;# csi /lib parameter allows multiple paths but does not accept spaces (or quotes) so we have to use short DOS 8.3 paths&#xA;$fso = New-Object -ComObject Scripting.FileSystemObject&#xA;$libPaths = ($libPaths | Where-Object { Test-Path $_ } | ForEach { $fso.GetFolder($_).shortpath  });&#xA;&#xA;&#xA;Write-Host &amp;quot;CSI will use the following paths to search for assembly references:`r`n   - $($libPaths -Join &amp;quot;`r`n   - &amp;quot;)&amp;quot; -for cyan&#xA;&#xA;&#xA;$missingLibs = @()&#xA;$requiredLibs | foreach {&#xA;    $requiredLib = $_;&#xA;    Write-Host &amp;quot;Checking for $($requiredLib.Name) version $($requiredLib.Version)...&amp;quot; -for Cyan -NoNewLine&#xA;&#xA;    if ($NuGetVersion -eq 4)&#xA;    {&#xA;        # NuGet 4+ format&#xA;        $found = $libPaths | &#xA;        ForEach { Join-Path $_ ($requiredLib.Name + &#39;\&#39; + $requiredLib.Version) } | &#xA;        Where-Object { Test-Path $_ } | Select-Object -first 1&#xA;&#xA;        if ($found -eq $null)&#xA;        {&#xA;            Write-Host &amp;quot;`n$($requiredLib.Name) not found. Will install using NuGet&amp;quot; -for Yellow&#xA;            $missingLibs += $requiredLib&#xA;        }&#xA;        else&#xA;        {&#xA;             Write-Host &amp;quot;Found: $found&amp;quot; -for Cyan&#xA;        }&#xA;    }&#xA;&#xA;    if ($NuGetVersion -eq 3)&#xA;    {&#xA;        # NuGet &amp;lt;=3 format&#xA;        $found = $libPaths | &#xA;        ForEach { Join-Path $_ ($requiredLib.Name + &#39;.&#39; + $requiredLib.Version) } | &#xA;        Where-Object { Test-Path $_ } | Select-Object -first 1&#xA;&#xA;        if ($found -eq $null)&#xA;        {&#xA;            Write-Host &amp;quot;`n$($requiredLib.Name) not found. Will install using NuGet&amp;quot; -for Yellow&#xA;            $missingLibs += $requiredLib&#xA;        }&#xA;        else&#xA;        {&#xA;             Write-Host &amp;quot;Found: $found4 $found3&amp;quot; -for Cyan&#xA;        }&#xA;    }&#xA;}&#xA;&#xA;if ($missingLibs)&#xA;{&#xA;    $nuget = Join-Path $env:TEMP &amp;quot;nuget.exe&amp;quot;&#xA;    if ((Test-Path $nuget) -eq $False)&#xA;    {&#xA;        Write-Host &amp;quot;Downloading NuGet.exe into $nuget&amp;quot; -for cyan&#xA;        $webClient = New-Object System.Net.WebClient &#xA;        $webClient.DownloadFile(&amp;quot;https://dist.nuget.org/win-x86-commandline/latest/nuget.exe&amp;quot;, $nuget)&#xA;    }&#xA;&#xA;    $missingLibs | foreach {&#xA;        $missingLib = $_&#xA;        Write-Host &amp;quot;Downloading $missingLib...&amp;quot;;&#xA;        $libName = $missingLib.Name&#xA;        $libVersion = $missingLib.Version&#xA;        if ($libVersion -eq $null)&#xA;        {&#xA;            &amp;amp; $nuget install $libName -OutputDirectory $missingNuGetPackagesLocation&#xA;        }&#xA;        else&#xA;        {&#xA;            &amp;amp; $nuget install $libName -Version $libVersion -OutputDirectory $missingNuGetPackagesLocation&#xA;        }&#xA;        if ($lastExitCode -ne 0)&#xA;        {&#xA;            Write-host &amp;quot;-------------`nError downloading $missingLib - aborting...`n-------------&amp;quot; -for red&#xA;            Exit 1&#xA;        }&#xA;    }&#xA;}&#xA;&#xA;&#xA;$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()&#xA;Write-host &amp;quot;Starting csi.exe $script ...&amp;quot; -for yellow&#xA;&amp;amp; $csi /lib:$($libPaths -Join &#39;;&#39;) $script&#xA;&#xA;$stopwatch.Stop()&#xA;Write-Host &amp;quot;Finished in $($stopwatch.Elapsed.TotalMilliSeconds) milliseconds&amp;quot;&#xA;&#xA;# Since I configured &amp;quot;-noexit&amp;quot; parameter in Visual Studio I don&#39;t need this&#xA;#if ($host.Name -notmatch &#39;ISE&#39;) { Write-Host -NoNewLine &amp;quot;(Just press Enter to exit)&amp;quot; -for cyan; read-host; }  &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;And my final CSX&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;/// &amp;lt;summary&amp;gt;&#xA;/// This CSX Script will invoke SimplePOCOGenerator, which builds simple POCO classes based on a JSON file with schema of SQL database&#xA;/// The easiest way to launch csi.exe (which is shipped with Visual Studio) to run this script is by using PowerShell script GenerateSimplePOCOs.ps1&#xA;/// You can do that from Visual Studio (see instructions in RefreshDatabaseSchema.ps1) or you can just execute &amp;quot;Powershell GenerateSimplePOCOs.ps1&amp;quot;&#xA;/// &amp;lt;/summary&amp;gt;&#xA;&#xA;// System libraries&#xA;#r &amp;quot;System.Data.dll&amp;quot;&#xA;&#xA;// Load third-party libraries by their relative paths, relative to &amp;quot;$Env:userprofile\.nuget\packages\&amp;quot;&#xA;#r &amp;quot;newtonsoft.json\12.0.3\lib\netstandard2.0\Newtonsoft.Json.dll&amp;quot;&#xA;#r &amp;quot;codegencs\1.0.5\lib\netstandard2.0\CodegenCS.dll&amp;quot;&#xA;&#xA;// CS files are better than CSX because Intellisense and Compile-time checks works better. &#xA;#load &amp;quot;DatabaseSchema.cs&amp;quot;&#xA;#load &amp;quot;SimplePOCOGenerator.cs&amp;quot;&#xA;&#xA;using System;&#xA;using System.IO;&#xA;using System.Runtime.CompilerServices;&#xA;using System.Data;&#xA;using System.Data.SqlClient;&#xA;&#xA;// Helpers to get the location of the current CSX script&#xA;public static string GetScriptPath([CallerFilePath] string path = null) =&amp;gt; path;&#xA;public static string GetScriptFolder([CallerFilePath] string path = null) =&amp;gt; Path.GetDirectoryName(path);&#xA;&#xA;&#xA;// locations relative to the CSX script&#xA;string inputJsonSchema = Path.GetFullPath(Path.Combine(GetScriptFolder(), &amp;quot;AdventureWorksSchema.json&amp;quot;));&#xA;string targetFolder = Path.GetFullPath(Path.Combine(GetScriptFolder(), @&amp;quot;.\POCOs\&amp;quot;));&#xA;string csProj = Path.GetFullPath(Path.Combine(GetScriptFolder(), @&amp;quot;.\CSX-PowerShell-VisualStudio2015.csproj&amp;quot;));&#xA;&#xA;var generator = new SimplePOCOGenerator(inputJsonSchema);&#xA;generator.Namespace = &amp;quot;CSX_PowerShell_VisualStudio2015&amp;quot;;&#xA;generator.Generate(targetFolder, null);&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Full source code is available &lt;a href=&#34;https://github.com/Drizin/CSX-PowerShell-VisualStudio&#34;&gt;here&lt;/a&gt;, with a sample project that reads a JSON file with AdventureWorks database schema and generates POCOs, both for SDK-Style (new csproj format) and for non-SDK-style (old Visual Studio 2015 format).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;So cool and so easy, isn&amp;rsquo;t it?&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In my next post, I&amp;rsquo;ll create a SQL schema extractor, and this schema will be used in next posts to build code generator for POCOs, EFCore, and other related services.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Enjoy!&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;This was the first part of a multi-part post series I&amp;rsquo;m going write do about Code Generation using C#&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Part 1 - &lt;a href=&#34;https://drizin.io/code-generation-csx-scripts-part1/&#34;&gt;Code Generation in Pure C# (and CSX scripts) directly from inside Visual Studio&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;Part 2 - &lt;a href=&#34;https://drizin.io/code-generation-in-c-csx-extracting-sql-server-schema/&#34;&gt;Extracting SQL Server Schema&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <dc:creator>Rick Drizin</dc:creator>
      <guid isPermaLink="false">5953ebbc-3275-4b17-8d05-2720bb0a2415</guid>
      <pubDate>Fri, 03 Jul 2020 02:48:29 GMT</pubDate>
    </item>
    <item>
      <title>Web API 2 - API versioning &amp; Multiple Controllers with Same Name</title>
      <link>http://rickdrizin.com/web-api-2-api-versioning-multiple-controllers-with-same-name</link>
      <description>&lt;p&gt;ASP.NET Web API by default does not allow 2 controllers with same name.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Basically, this is what happens:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;IHttpControllerSelector&lt;/code&gt; is resolved (by default it&amp;rsquo;s &lt;a href=&#34;https://github.com/mono/aspnetwebstack/blob/master/src/System.Web.Http/Dispatcher/DefaultHttpControllerSelector.cs&#34;&gt;&lt;code&gt;DefaultHttpControllerSelector&lt;/code&gt;&lt;/a&gt;) to call &lt;code&gt;IHttpControllerSelector.GetControllerMapping()&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;IHttpControllerSelector.GetControllerMapping()&lt;/code&gt; will resolve (through a &lt;a href=&#34;https://github.com/mono/aspnetwebstack/blob/master/src/System.Web.Http/Dispatcher/HttpControllerTypeCache.cs&#34;&gt;&lt;code&gt;HttpControllerTypeCache&lt;/code&gt; cache manager&lt;/a&gt;) &lt;code&gt;IHttpControllerTypeResolver&lt;/code&gt; to call &lt;code&gt;IHttpControllerTypeResolver.GetControllerTypes()&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;By default &lt;code&gt;IHttpControllerTypeResolver&lt;/code&gt; is &lt;a href=&#34;https://github.com/mono/aspnetwebstack/blob/master/src/System.Web.Http/Dispatcher/DefaultHttpControllerTypeResolver.cs&#34;&gt;&lt;code&gt;DefaultHttpControllerTypeResolver&lt;/code&gt;&lt;/a&gt;, in which &lt;code&gt;GetControllerTypes()&lt;/code&gt; will loop through all loaded assemblies and will return all types which implement &lt;code&gt;IHttpController&lt;/code&gt; and which end with &lt;code&gt;&amp;quot;Controller&amp;quot;&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Going back&amp;hellip; &lt;code&gt;IHttpControllerSelector.GetControllerMapping()&lt;/code&gt; will return a map of all controllers, but in case will &lt;strong&gt;ignore namespace, strip &lt;code&gt;&amp;quot;Controller&amp;quot;&lt;/code&gt; suffix, and will also ignore duplicates&lt;/strong&gt; (they are moved into another dictionary which is used just to throw an exception that there are multiple matching controllers).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;IHttpControllerSelector.SelectController&lt;/code&gt; is invoked on each request and will also use a cached map of controllers (cached by that same cache manager &lt;code&gt;HttpControllerTypeCache&lt;/code&gt;) which will lookup controller name in the route (like &lt;code&gt;{controller}&lt;/code&gt;) and will choose the correct controller.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve found &lt;a href=&#34;https://stackoverflow.com/questions/32778955/asp-net-webform-web-api-version-handling-using-namespace-and-persist-old-api&#34;&gt;some&lt;/a&gt; some &lt;a href=&#34;https://stackoverflow.com/questions/26437924/controllers-with-same-name-in-different-namespace-asp-net-web-api&#34;&gt;solutions&lt;/a&gt; to solve the problem of duplicated names, but most sounded too complex to me, since they were based on tagging the namespaces of each controller as DataTokens applied to the routes registered.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Since I&amp;rsquo;m using Attribute-Based routes and since I have (for legacy reasons) some non-attribute-based (regular explicitly defined routes), I ended up developing my own solution.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This &lt;code&gt;NamespaceHttpControllerSelector&lt;/code&gt; below allows the use of multiple controllers with same name (obviously in different namespaces) by prepending controller identifier with their namespaces (if they have &lt;code&gt;[RoutePrefix]&lt;/code&gt; attribute). And if there are controllers without &lt;code&gt;[RoutePrefix]&lt;/code&gt; they are just registered as usual, without their namespace, and will be matched by their route &lt;code&gt;{controller}&lt;/code&gt; as usual.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;using System;&#xA;using System.Collections.Generic;&#xA;using System.Linq;&#xA;using System.Net;&#xA;using System.Net.Http;&#xA;using System.Web.Http;&#xA;using System.Web.Http.Controllers;&#xA;using System.Web.Http.Dispatcher;&#xA;using System.Web.Http.Routing;&#xA;&#xA;/// &amp;lt;summary&amp;gt;&#xA;/// Allows the use of multiple controllers with same name (obviously in different namespaces) &#xA;/// by prepending controller identifier with their namespaces (if they have [RoutePrefix] attribute).&#xA;/// Allows attribute-based controllers to be mixed with explicit-routes controllers without conflicts.&#xA;/// &amp;lt;/summary&amp;gt;&#xA;public class NamespaceHttpControllerSelector : DefaultHttpControllerSelector&#xA;{&#xA;    // Some sample references: &#xA;    // https://www.strathweb.com/2013/08/customizing-controller-discovery-in-asp-net-web-api/&#xA;    // https://github.com/WebApiContrib/WebAPIContrib/blob/master/src/WebApiContrib/Selectors/NamespaceHttpControllerSelector.cs &#xA;    // https://github.com/umbraco/Umbraco-CMS/blob/7.2.0/src/Umbraco.Web/WebApi/NamespaceHttpControllerSelector.cs&#xA;    // https://github.com/mono/aspnetwebstack/blob/master/src/System.Web.Http/Dispatcher/DefaultHttpControllerSelector.cs&#xA;    // https://github.com/mono/aspnetwebstack/blob/master/src/System.Web.Http/Dispatcher/HttpControllerTypeCache.cs&#xA;&#xA;    private HttpConfiguration _configuration;&#xA;    private IHttpControllerSelector _previousSelector;&#xA;    private readonly Lazy&amp;lt;Dictionary&amp;lt;string, HttpControllerDescriptor&amp;gt;&amp;gt; _controllers;&#xA;&#xA;    public NamespaceHttpControllerSelector(HttpConfiguration httpConfiguration) : base(httpConfiguration)&#xA;    {&#xA;        _configuration = httpConfiguration;&#xA;        _previousSelector = _configuration.Services.GetService(typeof(IHttpControllerSelector)) as IHttpControllerSelector;&#xA;        _controllers = new Lazy&amp;lt;Dictionary&amp;lt;string, HttpControllerDescriptor&amp;gt;&amp;gt;(InitializeControllerDictionary);&#xA;    }&#xA;&#xA;    public override IDictionary&amp;lt;string, HttpControllerDescriptor&amp;gt; GetControllerMapping()&#xA;    {&#xA;        return _controllers.Value; // just cache the list of controllers, so we load only once at first use&#xA;    }&#xA;&#xA;    /// &amp;lt;summary&amp;gt;&#xA;    /// The regular DefaultHttpControllerSelector.InitializeControllerDictionary() does not &#xA;    ///  allow 2 controller types to have same name even if they are in different namespaces (they are ignored!)&#xA;    /// &#xA;    /// This method will map ALL controllers, even if they have same name, &#xA;    /// by prepending controller names with their namespaces if they have [RoutePrefix] attribute&#xA;    /// &amp;lt;/summary&amp;gt;&#xA;    /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&#xA;    private Dictionary&amp;lt;string, HttpControllerDescriptor&amp;gt; InitializeControllerDictionary()&#xA;    {&#xA;        IAssembliesResolver assembliesResolver = _configuration.Services.GetAssembliesResolver();&#xA;        IHttpControllerTypeResolver controllersResolver = _configuration.Services.GetHttpControllerTypeResolver(); &#xA;        ICollection&amp;lt;Type&amp;gt; controllerTypes = controllersResolver.GetControllerTypes(assembliesResolver); &#xA;&#xA;        // simple alternative? in case you want to map maybe &amp;quot;UserAPI&amp;quot; instead of &amp;quot;UserController&amp;quot;&#xA;        // var controllerTypes = System.Reflection.Assembly.GetExecutingAssembly().GetTypes()&#xA;        // .Where(t =&amp;gt; t.IsClass &amp;amp;&amp;amp; t.IsVisible &amp;amp;&amp;amp; !t.IsAbstract &amp;amp;&amp;amp; typeof(IHttpController).IsAssignableFrom(t));&#xA;&#xA;        var controllers = new Dictionary&amp;lt;string, HttpControllerDescriptor&amp;gt;(StringComparer.OrdinalIgnoreCase);&#xA;        foreach (Type t in controllerTypes)&#xA;        {&#xA;            var controllerName = t.Name;&#xA;&#xA;            // ASP.NET by default removes &amp;quot;Controller&amp;quot; suffix, let&#39;s keep that convention&#xA;            if (controllerName.EndsWith(ControllerSuffix))&#xA;                controllerName = controllerName.Remove(controllerName.Length - ControllerSuffix.Length);&#xA;&#xA;            // For controllers with [RoutePrefix] we&#39;ll register full name (namespace+name). &#xA;            // Those routes when matched they provide the full type name, so we can match exact controller type.&#xA;            // For other controllers we&#39;ll register as usual&#xA;            bool hasroutePrefixAttribute = t.GetCustomAttributes(typeof(RoutePrefixAttribute), false).Any();&#xA;            if (hasroutePrefixAttribute)&#xA;                controllerName = t.Namespace + &amp;quot;.&amp;quot; + controllerName;&#xA;&#xA;            if (!controllers.Keys.Contains(controllerName))&#xA;                controllers[controllerName] = new HttpControllerDescriptor(_configuration, controllerName, t);&#xA;        }&#xA;        return controllers;&#xA;    }&#xA;&#xA;    /// &amp;lt;summary&amp;gt;&#xA;    /// For &amp;quot;regular&amp;quot; MVC routes we will receive the &amp;quot;{controller}&amp;quot; value in route, and we lookup for the controller as usual.&#xA;    /// For attribute-based routes we receive the ControllerDescriptor which gives us &#xA;    /// the full name of the controller as registered (with namespace), so we can version our APIs&#xA;    /// &amp;lt;/summary&amp;gt;&#xA;    /// &amp;lt;param name=&amp;quot;request&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&#xA;    /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&#xA;    public override HttpControllerDescriptor SelectController(HttpRequestMessage request)&#xA;    {&#xA;        HttpControllerDescriptor controller;&#xA;        IDictionary&amp;lt;string, HttpControllerDescriptor&amp;gt; controllers = GetControllerMapping();&#xA;        IDictionary&amp;lt;string, HttpControllerDescriptor&amp;gt; controllersWithoutAttributeBasedRouting =&#xA;            GetControllerMapping().Where(kv =&amp;gt; !kv.Value.ControllerType&#xA;               .GetCustomAttributes(typeof(RoutePrefixAttribute), false).Any())&#xA;            .ToDictionary(kv =&amp;gt; kv.Key, kv =&amp;gt; kv.Value);&#xA;&#xA;        var route = request.GetRouteData();&#xA;&#xA;        // regular routes are registered explicitly using {controller} route - and in case we&#39;ll match by the controller name,&#xA;        // as usual (&amp;quot;CourseController&amp;quot; is looked up in dictionary as &amp;quot;Course&amp;quot;).&#xA;        if (route.Values != null &amp;amp;&amp;amp; route.Values.ContainsKey(&amp;quot;controller&amp;quot;))&#xA;        {&#xA;            string controllerName = (string)route.Values[&amp;quot;controller&amp;quot;];&#xA;            if (controllersWithoutAttributeBasedRouting.TryGetValue(controllerName, out controller))&#xA;                return controller;&#xA;        }&#xA;&#xA;        // For attribute-based routes, the matched route has subroutes, &#xA;        // and we can get the ControllerDescriptor (with the exact name that we defined - with namespace) associated, to return correct controller&#xA;        if (route.GetSubRoutes() != null)&#xA;        {&#xA;            route = route.GetSubRoutes().First(); // any sample route, we&#39;re just looking for the controller&#xA;&#xA;            // Attribute Routing registers a single route with many subroutes, and we need to inspect any action of the route to get the controller&#xA;            if (route.Route != null &amp;amp;&amp;amp; route.Route.DataTokens != null &amp;amp;&amp;amp; route.Route.DataTokens[&amp;quot;actions&amp;quot;] != null)&#xA;            {&#xA;                // if it wasn&#39;t for attribute-based routes which give us the ControllerDescriptor for each route, &#xA;                // we could pick the correct controller version by inspecting version in accepted mime types in request.Headers.Accept&#xA;                string controllerTypeFullName = ((HttpActionDescriptor[])route.Route.DataTokens[&amp;quot;actions&amp;quot;])[0].ControllerDescriptor.ControllerName;&#xA;                if (controllers.TryGetValue(controllerTypeFullName, out controller))&#xA;                    return controller;&#xA;            }&#xA;        }&#xA;&#xA;        throw new HttpResponseException(HttpStatusCode.NotFound);&#xA;    }&#xA;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;How to register this - before auto-mapping your routes (in your Startup.cs, or RouteConfig.cs, or Global.asax.cs, or similar) you register your new &lt;code&gt;IHttpControllerSelector&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;config.Services.Replace(typeof(IHttpControllerSelector), new NamespaceHttpControllerSelector(config));&#xA;config.MapHttpAttributeRoutes();&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;</description>
      <dc:creator>Rick Drizin</dc:creator>
      <guid isPermaLink="false">90d22899-9411-4b7a-9600-f4afffa22d72</guid>
      <pubDate>Sat, 20 Jun 2020 01:55:52 GMT</pubDate>
    </item>
    <item>
      <title>Install Chrome using Powershell Script</title>
      <link>http://rickdrizin.com/install-chrome-using-powershell-script</link>
      <description>&lt;p&gt;I know everyone hates Internet Explorer, and only use Internet Explorer to download Chrome or Firefox.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To avoid you further pain, this is a Powershell script that you can use to install Chrome without even touching IE. &lt;em&gt;Enjoy!&lt;/em&gt; :-)&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-powershell&#34;&gt;# Install Chrome&#xA;$Path = $env:TEMP; &#xA;$Installer = &amp;quot;chrome_installer.exe&amp;quot;; &#xA;Invoke-WebRequest &amp;quot;http://dl.google.com/chrome/install/375.126/chrome_installer.exe&amp;quot; -OutFile $Path\$Installer; &#xA;Start-Process -FilePath $Path\$Installer -Args &amp;quot;/silent /install&amp;quot; -Verb RunAs -Wait; &#xA;Remove-Item $Path\$Installer&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;</description>
      <dc:creator>Rick Drizin</dc:creator>
      <guid isPermaLink="false">4f1b90cb-98a0-4870-8aad-78b5825d4f66</guid>
      <pubDate>Fri, 06 Mar 2020 02:08:52 GMT</pubDate>
    </item>
    <item>
      <title>Zabbix UI showing UTC timezone on Timeline</title>
      <link>http://rickdrizin.com/zabbix-ui-showing-utc-timezone-on-timeline</link>
      <description>&lt;p&gt;I&amp;rsquo;m using Zabbix 4.4.3 (latest version), installed using RedHat packages, and the timezone was showing UTC and I needed to change it to my local timezone (EST).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In dozens of different sites I found instructions explaining to configure timezone in php.ini (for me it was in /etc/php.ini) like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;[Date]&#xA;; Defines the default timezone used by the date functions&#xA;; http://php.net/date.timezone&#xA;;date.timezone =&#xA;date.timezone = &amp;quot;America/New_York&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I restarted the services and it wasn&amp;rsquo;t still working. Although the &lt;strong&gt;Local Clock&lt;/strong&gt; works, the &lt;strong&gt;Problems Timeline&lt;/strong&gt; was still showing UTC timezone:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2019/12/1575825255_1c87e99aa9a041c08f888d8aa361afb6.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So I decided to put directly this configuration in the PHP application (Zabbix). I found the UI configuration to be in &lt;strong&gt;/etc/zabbix/web/zabbix.conf.php&lt;/strong&gt;, and just had to add this line:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;date_default_timezone_set(&#39;America/New_York&#39;);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;And now it works (no need to restart the services):&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2019/12/1575825269_e0bc8c9ea01d42ea864f5e6e1dd966a8.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;PS: Somewhere I read thatI should configure &lt;strong&gt;/etc/apache2/conf-available/zabbix-frontend-php.conf&lt;/strong&gt;, but I couldn&amp;rsquo;t find this file anywhere in my RedHat installation.&lt;/p&gt;&#xA;</description>
      <dc:creator>Rick Drizin</dc:creator>
      <guid isPermaLink="false">3a895ce2-2121-4f01-9332-5611e1606cb9</guid>
      <pubDate>Sun, 08 Dec 2019 17:16:08 GMT</pubDate>
    </item>
    <item>
      <title>Powershell script to Stamp pictures with Date/Time</title>
      <link>http://rickdrizin.com/powershell-script-stamp-pictures-date-time</link>
      <description>&lt;p&gt;Quick tip:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I &lt;strong&gt;hate&lt;/strong&gt; having my pictures automatically named like &lt;code&gt;IMG_0384.CR2&lt;/code&gt;, because during backups (moving around hard drives, cloud, etc) it happens that I lose the original date of the files. And although I group pictures in folders, it&amp;rsquo;s still sometimes easy to lost the original date.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So I just created (well, I copied from others but made some adjustments) this helpful Powershell script, which will stamp the filenames with the date when the picture was taken.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-powershell&#34;&gt;# Based on https://ss64.com/ps/syntax-stampme.html&#xA;# usage: PS C:\&amp;gt;./stampme.ps1 &amp;quot;F:\somepicture.png&amp;quot;&#xA;# usage: PS C:\&amp;gt; foreach ($file in get-ChildItem *.CR2) { ./stampme.ps1 $file.name }&#xA;&#xA;&#xA;#StampMe.ps1&#xA;param( [string] $fileName)&#xA;&#xA;# Check the file exists&#xA;if (-not(Test-Path $fileName)) {break}&#xA;&#xA;# Display the original name&#xA;&amp;quot;Original filename: $fileName&amp;quot;&#xA;&#xA;$fileObj = get-item $fileName&#xA;&#xA;# https://stackoverflow.com/questions/6834259/how-can-i-get-programmatic-access-to-the-date-taken-field-of-an-image-or-video&#xA;try {&#xA;&#xA;&#xA;  $pic = New-Object System.Drawing.Bitmap($fileName)&#xA;  $bitearr = $pic.GetPropertyItem(36867).Value &#xA;  $string = [System.Text.Encoding]::ASCII.GetString($bitearr) &#xA;  $DateTime = [datetime]::ParseExact($string,&amp;quot;yyyy:MM:dd HH:mm:ss`0&amp;quot;,$Null)&#xA;}&#xA;catch &#xA;{&#xA;  $DateTime =  (Get-Item $fileName).LastWriteTime&#xA;}&#xA;&#xA;# Get the date&#xA;#$DateStamp = get-date -uformat &amp;quot;%Y-%m-%d_%H%M%S&amp;quot;&#xA;$DateStamp = $DateTime.ToString(&amp;quot;yyyy-MM-dd_HHmmss&amp;quot;)&#xA;&#xA;$extOnly = $fileObj.extension&#xA;&#xA;if ($extOnly.length -eq 0) {&#xA;   $nameOnly = $fileObj.Name&#xA;   rename-item &amp;quot;$fileObj&amp;quot; &amp;quot;$DateStamp-$nameOnly&amp;quot;&#xA;   }&#xA;else {&#xA;   $nameOnly = $fileObj.Name.Replace( $fileObj.Extension,&#39;&#39;)&#xA;   rename-item &amp;quot;$fileName&amp;quot; &amp;quot;$DateStamp-$nameOnly$extOnly&amp;quot;&#xA;   }&#xA;&#xA;# Display the new name&#xA;&amp;quot;New filename: $DateStamp-$nameOnly$extOnly&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Look how my pictures were badly organized before:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2019/12/1575429067_a986a671d66e42b09ea70e9a1dbb8930.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;And look how they are much more beautiful now:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Enjoy!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2019/12/1575429201_6aaa2e0c12f14b509be9313dca3c5cb0.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2019/12/1575429218_deb869bc644e4cc88d992e409debf4f2.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Much better, uh? :-)&lt;/p&gt;&#xA;</description>
      <dc:creator>Rick Drizin</dc:creator>
      <guid isPermaLink="false">a7b5eded-c904-48b3-9f7f-121d603c1f31</guid>
      <pubDate>Wed, 04 Dec 2019 03:13:52 GMT</pubDate>
    </item>
    <item>
      <title>Yet Another Code Generator</title>
      <link>http://rickdrizin.com/yet-another-code-generator</link>
      <description>&lt;p&gt;I&amp;rsquo;ve been a fan of code generation (mostly for scaffolding data access objects from databases) for a long-time. I have used &lt;a href=&#34;https://www.codesmithtools.com/product/generator&#34;&gt;CodeSmith generator&lt;/a&gt;,  &lt;a href=&#34;http://mygeneration.sourceforge.net/&#34;&gt;MyGeneration Code Generator&lt;/a&gt;, LINQ to SQL, &lt;a href=&#34;http://lhotka.net/cslanet/&#34;&gt;Rockford Lhotka CSLA&lt;/a&gt;, &lt;a href=&#34;https://github.com/subsonic/SubSonic-3.0-Templates&#34;&gt;Subsonic Active Record Templates&lt;/a&gt;, and more recently &lt;a href=&#34;https://github.com/sjh37/EntityFramework-Reverse-POCO-Code-First-Generator&#34;&gt;Simon Hughes Entity Framework T4 templates&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The main advantage of code generation (which includes &lt;strong&gt;&amp;ldquo;db scaffolding&amp;rdquo;&lt;/strong&gt;, also known as &lt;strong&gt;database first&lt;/strong&gt; in some ORMs) is that it does the work for you, is repeatable, and &lt;strong&gt;less error-prone&lt;/strong&gt; than manually writing everything. So it&amp;rsquo;s mostly about productivity and consistency. &lt;strong&gt;If you&amp;rsquo;re writing repetitive code by hand, you&amp;rsquo;re stealing from your employer or from your client&lt;/strong&gt;. And if you have a data-oriented application, almost certainly you have repetitive code to some degree.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I frequently need to make some customizations over the code generation templates, and it&amp;rsquo;s always a hard task. Most code generators do not have good support for one or more of the following important features:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Indentation and whitespace control&lt;/li&gt;&#xA;&lt;li&gt;Debugging&lt;/li&gt;&#xA;&lt;li&gt;Includes (subtemplates)&lt;/li&gt;&#xA;&lt;li&gt;Intellisense (code completion)&lt;/li&gt;&#xA;&lt;li&gt;Compile-time checking (strong typing)&lt;/li&gt;&#xA;&lt;li&gt;Integration with CSPROJ files&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Among those, I had one important requirement: the included subtemplates should respect parent indentation, and even if they were multi-line templates those lines should be rendered in the correct position.  Or as handlerbars &lt;a href=&#34;http://handlebarsjs.com/reference.html&#34;&gt;describe&lt;/a&gt; , &lt;em&gt;&amp;ldquo;By default, an indented partial-call causes the output of the whole partial being indented by the same amount.&amp;rdquo;&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;While trying to find a good code generator (to replace what I currently do with T4 Templates) I explored the most popular free tools/libraries for code generation and text templating.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;T4 Templates&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;T4 templates are based on ASPX control blocks &lt;code&gt;&amp;lt;% %&amp;gt;&lt;/code&gt;. They tend to get very ugly, have low degree of intellisense/typing (it&amp;rsquo;s easy to write invalid code and you can only find out debugging which is even harder), have terrible support for indentation, and everytime that I upgrade my Visual Studio the T4 templates totally break, since they are very environment dependent.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;And they look as ugly as this:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;/images/2019/09/1569167765_8ca9ebf0d102467cb8f51a093bc60b6f.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Razor Engines&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/Antaris/RazorEngine&#34;&gt;Antaris RazorEngine&lt;/a&gt; is the top-leading razor engine, but there are other razor engines like &lt;a href=&#34;https://github.com/toddams/RazorLight&#34;&gt;RazorLight&lt;/a&gt; and &lt;a href=&#34;https://github.com/RickStrahl/Westwind.RazorHosting&#34;&gt;WestWind.RazorHosting&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Razor is more concise (and less ugly) than ASPX control blocks, but for achieving concise code they have to make some &amp;ldquo;assumptions&amp;rdquo; about what is control logic and what is output code, and therefore &lt;strong&gt;it tries to automagically guess C# code that is intended to control logic&lt;/strong&gt; so if you write &lt;code&gt;Debug.WriteLine&lt;/code&gt; it will assume that this should be interpreted (and not written to output).&lt;br&gt;&#xA;If you type an XML tag inside a code block it will automagically assume that it should be written to output (which makes sense, afterall XML tags are not control logic, but yet this gets very confusing). So to make it work you end up using escape characters like &lt;code&gt;@&lt;/code&gt;, &lt;code&gt;@{}&lt;/code&gt; and &lt;code&gt;@:&lt;/code&gt; everywhere.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Razor templates are nice because they have good Visual Studio support (with &lt;strong&gt;intellisense and object models&lt;/strong&gt;, although those unclear distintions between control logic and output code usually make intellisense fail), and allow partials, but unfortunately for having intellisense in partials you would have to split them into indivual files.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;RazorEngine is very complete, very stable, and somehow easy to extend, but they have some minor annoyances like saving temporary DLLs (which don&amp;rsquo;t get deleted) everywhere.&lt;br&gt;&#xA;But &lt;strong&gt;the major problems with all Razor-based engines is that Razor uses angle-based tags, and therefore is targeted at writing XML/HTML&lt;/strong&gt;, and a little annoying to write other outputs. Additionally, the Partials (includes) do NOT respect parent indentation level - so if you include a multi-line subtemplate, you&amp;rsquo;ll get a messy indentation.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;&lt;a href=&#34;https://github.com/daveaglick/Scripty&#34;&gt;Scripty&lt;/a&gt;&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Scripty describes itself as &lt;strong&gt;&lt;em&gt;Tools to let you use Roslyn-powered C# scripts for code generation. You can think of it as a scripted alternative to T4 templates&lt;/em&gt;&lt;/strong&gt;.&lt;br&gt;&#xA;It can manipulate CSPROJ files, has support for both .NET Framework and .NET core, and has &lt;strong&gt;good indentation support&lt;/strong&gt;: it has its own TextWriter which keeps tracks of current indent level, and restores this indent level when you start a new line).&#xA;It also has &lt;strong&gt;great intellisense&lt;/strong&gt; since it&amp;rsquo;s scripted using pure C#.&lt;br&gt;&#xA;Unfortunately, &lt;strong&gt;it does not have integrated templating engine&lt;/strong&gt;, so writing complex templates can get ugly and cumbersome. Additionally it looks like the author not only does not intend to support any specific templating engine, but also has somehow abandoned the project (and complex open source projects when abandoned usually decline fast unless a new group of supporters fork it into a new project) - so I was a little afraid of putting all my coins into a complex codebase which is not being maintained.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Templating Engines&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Currently the most popular templating engines are based on the &lt;a href=&#34;http://mustache.github.io/&#34;&gt;mustache&lt;/a&gt; standard, which is very nice because it uses &amp;ldquo;double-braces&amp;rdquo; to define control logic with tags &lt;code&gt;{{ this }}&lt;/code&gt;, so you can still use regular single-braces for C# (or Java or any C-Style) code.  Although mustache is the first engine using this, it was quickly followed by better alternatives like &lt;a href=&#34;https://github.com/wycats/handlebars.js/&#34;&gt;handlebars.js&lt;/a&gt; and Shopify &lt;a href=&#34;https://shopify.github.io/liquid/&#34;&gt;liquid&lt;/a&gt;, which are the two most popular engines, and they were both respectively ported to .NET in the libraries &lt;a href=&#34;https://github.com/rexm/Handlebars.Net&#34;&gt;Handlebars.Net&lt;/a&gt; and &lt;a href=&#34;https://github.com/dotliquid/dotliquid&#34;&gt;Dotliquid&lt;/a&gt;. There&amp;rsquo;s also a new kid on the block called &lt;a href=&#34;https://github.com/lunet-io/scriban&#34;&gt;Scriban&lt;/a&gt; which is based on Dotliquid but with some improvements, and growing fast.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Although the escape character in all those engines does not conflict with C# code, &lt;strong&gt;their syntax is very different from regular C# code&lt;/strong&gt; (probably easier to parse), so you have to learn a new syntax. Learning a new syntax is not a problem, afterall we all have learned so many different syntaxes over time and old dogs love to learn new tricks, but the problem is that those engines also &lt;strong&gt;do NOT have any debugging support&lt;/strong&gt;, which is a must, specially when you&amp;rsquo;re not familiar with the syntax, or when you&amp;rsquo;re writing complex templates. &lt;strong&gt;Debugging templates only by the error outputs is like debugging code only with &lt;code&gt;Console.WriteLine&lt;/code&gt; when you could be using a real IDE.&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;&lt;a href=&#34;https://palletsprojects.com/p/jinja/&#34;&gt;Jinja2&lt;/a&gt;&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Since none of the .NET alternatives fully matched what I was looking for, I also checked the most popular templating engine for non-NET languages.&lt;br&gt;&#xA;Jinja2 engine is written in Python, and is similar to Handlebars and Liquid. They have good whitespacing control, good indentation, and a good ecosystem (parsers, editors, etc). However, similarly like Dotliquid and Handlebars.Net, it looks like &lt;strong&gt;all those templating tools are NOT focused on code generation but on used-defined-templates (like configuring automatic emails, configuring pages for your ecommerce, etc)&lt;/strong&gt;, so they have a different set of requirements in mind. For those tools it really makes sense to have a &lt;strong&gt;simple syntax&lt;/strong&gt;, a &lt;strong&gt;sandboxed security model&lt;/strong&gt; (isolated AppDomain), and loading templates from strings stored anywhere (like your database).  &lt;strong&gt;A code generator does not need any of that, but needs good debugging support, good intellisense, and (for those of us who like it) strong typing&lt;/strong&gt;.&lt;br&gt;&#xA;Last, since I&amp;rsquo;m mostly into C#/.NET, it didn&amp;rsquo;t look like a good fit to start using a Python engine - especially if I want my templates to be easily adopted by other C# users. I was looking for something similar to T4 templates but with better readability, better tooling, and better reuse.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Writing code using C&amp;#35;&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;From the tools above, the only one which integrates with msbuild projects (in other words can write into csproj files) is Scripty, so this is where I started my tests. Scripty basically have their own TextWriter (&lt;code&gt;Scripty.Core.Output.OutputFile&lt;/code&gt;) and some helpers like a collection of TextWriters for writing to multiple files, and for choosing how each file should be treated by the csproj, etc.&lt;br&gt;&#xA;This is Scripty syntax:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;w.WriteLine();&#xA;w.WriteLine(&amp;quot;///&amp;lt;summary&amp;gt;&amp;quot;);&#xA;w.WriteLine(&amp;quot;/// {0}&amp;quot;, System.Security.SecurityElement.Escape(c.SummaryComments));&#xA;w.WriteLine(&amp;quot;///&amp;lt;/summary&amp;gt;&amp;quot;);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;For writing indented code in Scripty you could manually indent your strings like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;w.WriteLine(&amp;quot;finally&amp;quot;);&#xA;w.WriteLine(&amp;quot;{&amp;quot;);&#xA;w.WriteLine(&amp;quot;    dbConnection.Close();&amp;quot;);&#xA;w.WriteLine(&amp;quot;}&amp;quot;);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip; or you could use their nice indentation helpers which control indentation level for you:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;w.WriteLine($&amp;quot;public {Settings.DbContextName}(string connectionString) : base(connectionString)&amp;quot;);&#xA;w.WriteLine(&amp;quot;{&amp;quot;);&#xA;using (w.WithIndent())&#xA;{&#xA;    w.WriteLine(&amp;quot;InitializePartial();&amp;quot;);&#xA;}&#xA;w.WriteLine(&amp;quot;}&amp;quot;);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As you can notice, this can get very ugly and cumbersome to write:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;w.WriteLine($&amp;quot;{Settings.MigrationClassModifiers} class {Settings.MigrationConfigurationFileName}: System.Data.Entity.Migrations.DbMigrationsConfiguration&amp;lt;{Settings.DbContextName }&amp;gt; &amp;quot;);&#xA;w.WriteLine(&amp;quot;{&amp;quot;);&#xA;using (w.WithIndent())&#xA;{&#xA;    w.WriteLine($&amp;quot;public {Settings.MigrationConfigurationFileName}()&amp;quot;);&#xA;    w.WriteLine(&amp;quot;{&amp;quot;);&#xA;    using (w.WithIndent())&#xA;    {&#xA;        w.WriteLine($&amp;quot;AutomaticMigrationsEnabled = { Settings.AutomaticMigrationsEnabled.ToString() };&amp;quot;);&#xA;        w.WriteLine($&amp;quot;AutomaticMigrationDataLossAllowed = { Settings.AutomaticMigrationDataLossAllowed.ToString() };&amp;quot;);&#xA;        if (!string.IsNullOrEmpty(Settings.ContextKey))&#xA;            w.WriteLine($@&amp;quot;ContextKey = &amp;quot;&amp;quot;{ Settings.ContextKey }&amp;quot;&amp;quot;;&amp;quot;);&#xA;    }&#xA;    w.WriteLine(&amp;quot;}&amp;quot;);&#xA;}&#xA;w.WriteLine(&amp;quot;}&amp;quot;);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Pretty ugly, right?&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;More concise manual indentation&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;The first helper method that I added to Scripty was something to make manual-indentation less verbose when all I need is to create C-style blocks ( &lt;code&gt;{ }&lt;/code&gt; ).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With my helpers, creating an indented code block became a little easier because a single statement will both write the line before the block starts, will write the brace which starts the block, will increase indent, and when being disposed it will decrease the indent and will also output the brace which closes the block. So it&amp;rsquo;s 3 lines (and increasing/decreasing inner indentation) in a single line.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;using (w.WithCStyleBlock($&amp;quot;namespace {myNamespace}&amp;quot;))&#xA;{&#xA;    using (w.WithCStyleBlock($&amp;quot;public class {myClass}&amp;quot;))&#xA;    {&#xA;         w.WriteLine(&amp;quot;// My Properties start here&amp;quot;);&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;this generates this code:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;namespace codegencs&#xA;{&#xA;    public class Test1&#xA;    {&#xA;        // My Properties start here&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Another example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;w.WriteLine($&amp;quot;{Settings.MigrationClassModifiers} class {Settings.MigrationConfigurationFileName}: System.Data.Entity.Migrations.DbMigrationsConfiguration&amp;lt;{Settings.DbContextName }&amp;gt; &amp;quot;);&#xA;w.WriteLine(&amp;quot;{&amp;quot;);&#xA;using (w.WithIndent())&#xA;{&#xA;    w.WriteLine($&amp;quot;public {Settings.MigrationConfigurationFileName}()&amp;quot;);&#xA;    w.WriteLine(&amp;quot;{&amp;quot;);&#xA;    using (w.WithIndent())&#xA;    {&#xA;        w.WriteLine($&amp;quot;AutomaticMigrationsEnabled = { Settings.AutomaticMigrationsEnabled.ToString() };&amp;quot;);&#xA;        w.WriteLine($&amp;quot;AutomaticMigrationDataLossAllowed = { Settings.AutomaticMigrationDataLossAllowed.ToString() };&amp;quot;);&#xA;        if (!string.IsNullOrEmpty(Settings.ContextKey))&#xA;            w.WriteLine($@&amp;quot;ContextKey = &amp;quot;&amp;quot;{ Settings.ContextKey }&amp;quot;&amp;quot;;&amp;quot;);&#xA;    }&#xA;    w.WriteLine(&amp;quot;}&amp;quot;);&#xA;}&#xA;w.WriteLine(&amp;quot;}&amp;quot;);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Can be simplified into:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;using (w.WithCStyleBlock($&amp;quot;{Settings.MigrationClassModifiers} class {Settings.MigrationConfigurationFileName}: System.Data.Entity.Migrations.DbMigrationsConfiguration&amp;lt;{Settings.DbContextName }&amp;gt; ))&#xA;{&#xA;    using (w.WithCStyleBlock($&amp;quot;public {Settings.MigrationConfigurationFileName}()&amp;quot;))&#xA;    {&#xA;        w.WriteLine($&amp;quot;AutomaticMigrationsEnabled = { Settings.AutomaticMigrationsEnabled.ToString() };&amp;quot;);&#xA;        w.WriteLine($&amp;quot;AutomaticMigrationDataLossAllowed = { Settings.AutomaticMigrationDataLossAllowed.ToString() };&amp;quot;);&#xA;        if (!string.IsNullOrEmpty(Settings.ContextKey))&#xA;            w.WriteLine($@&amp;quot;ContextKey = &amp;quot;&amp;quot;{ Settings.ContextKey }&amp;quot;&amp;quot;;&amp;quot;);&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As you can see, the boilerplate was condensed into a single statement, and yet the control logic braces/indentation clearly match the output code braces which are implicitally rendered.&lt;br&gt;&#xA; (I know that some people will prefer opening braces in the same line - so sorry, you won&amp;rsquo;t see that helper in my code generator, ever!! :-)  just kidding - let&amp;rsquo;s create a WithJavascriptStyleBlock() for opening block in same line ok? :-)   )&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Multiline statements and the Mixed Indentations Problem&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Even with C-block helpers, writing line by line like previous examples can be cumbersome - you&amp;rsquo;ll probably want to write small blocks in a single multiline statement like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;if (writeClass)&#xA;{&#xA;    if (writeDispose) &#xA;    {&#xA;        w.WriteLine(&#xA;        @&amp;quot;protected virtual void Dispose(bool disposing)&#xA;        {&#xA;            base.Dispose()&#xA;        }&amp;quot;);&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The problem is that in the code above I made the string aligned with the control logic, to be visually clear. But the output would be this (assuming that TextWriter is at &lt;code&gt;IndentLevel=0&lt;/code&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;protected virtual void Dispose(bool disposing)&#xA;        {&#xA;            base.Dispose()&#xA;        }&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To make the output code correctly indented, you would have to use &lt;strong&gt;Mixed Indentations&lt;/strong&gt;, where control logic has its own indentation, and output code has another:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;if (writeClass)&#xA;{&#xA;    if (writeDispose) &#xA;    {&#xA;        w.WriteLine(&#xA;@&amp;quot;protected virtual void Dispose(bool disposing)&#xA;{&#xA;    base.Dispose()&#xA;}&amp;quot;);&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Looks ugly, isn&amp;rsquo;t it? This mixed-indentation problem also affects T4 templates, as you can see in the previous T4 template sample screenshot that I posted above. And as you&amp;rsquo;ll notice, T4 templates can get even worse because the syntax highlighting may get totally crazy (or not work at all) and you won&amp;rsquo;t be able to tell apart what is control logic and what is output code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As you can see, &lt;strong&gt;when you write multiline statements if you want to correctly control indentation and whitespace you&amp;rsquo;ll have to use mixed indents of the generating code and the generated code, and that gets very confusing&lt;/strong&gt;. If you indent the strings to the right (to be aligned with the outer control code), you&amp;rsquo;ll get extra indents in your output, which may not be desirable.&lt;br&gt;&#xA; (And, yes, I&amp;rsquo;m aware that there are code formatting tools like Roslyn, but yet, having manual control over code is a good idea, and more than this - you may want to write non-C# code that can&amp;rsquo;t be automatically formatted)&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Solving multi-line strings&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;To make the multi-line blocks a little less confusing (&lt;strong&gt;avoid &amp;ldquo;mixed indent levels&amp;rdquo;&lt;/strong&gt;) I created a helper method which would allow me to write &lt;strong&gt;multiline string with any number of padding spaces&lt;/strong&gt; (to make it aligned with the outer generating code), and yet &lt;strong&gt;those spaces will be ignored&lt;/strong&gt;. Whenever I write a multi-line block, my helper assumes that the block should follow the current indentation level (of Scripty TextWriter), and do not add any further indentation.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;if (something)&#xA;{&#xA;    if (something)&#xA;    {&#xA;        if (something)&#xA;        {&#xA;            w.WriteLine(@&amp;quot;&#xA;                namespace codegencs&#xA;                {&#xA;                    public class Test1&#xA;                    {&#xA;                        // My Properties start here&#xA;                    }&#xA;                }&amp;quot;);&#xA;        }&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In case, my helper method will realign this whole block to the left, docking the outermost line to the left, while respecting &amp;ldquo;internal&amp;rdquo; indentation. So assuming that the current TextWriter was at IndentLevel 0 we get this output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;namespace codegencs&#xA;{&#xA;    public class Test1&#xA;    {&#xA;        // My Properties start here&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;And if the TextWriter was at IndentLevel 1 we get this output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;    namespace codegencs&#xA;    {&#xA;        public class Test1&#xA;        {&#xA;            // My Properties start here&#xA;        }&#xA;    }&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;PS: Not only the block is docked to the left (removing from all lines the maximum number of spaces) but also we ignore the first empty line, which allows us to put the opening&lt;code&gt;@&amp;quot;&lt;/code&gt; in a single line, making the first line correctly-aligned with the following lines.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;// this&#xA;w.WriteLine(@&amp;quot;&#xA;        public class Test1&#xA;        {&#xA;            // My Properties start here&#xA;        }&amp;quot;);&#xA;&#xA;// is a little better than this, right?&#xA;w.WriteLine(&#xA;        @&amp;quot;public class Test1&#xA;        {&#xA;            // My Properties start here&#xA;        }&amp;quot;);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h1&gt;Integrating a real Templating Engine&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Now that indentation and multiline strings were more readable, the next step was to allow templates with more logic, and mostly with reusable code (functions or subtemplates). As I explained above, Scripty does not have ambition to be a Templating Engine, or even to have one integrated, so it was clear that I should integrate into Scripty a real engine like RazorEngine, Scriban or Dotliquid.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;RazorEngine has good extensibility, it looked promising. I wrote my own BaseTemplate and registered it to be injected for all templates. The idea was to get the underlying Scripty TextWriter.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Basically I had this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;public class RazorIndentedTemplate&amp;lt;T&amp;gt; : TemplateBase&amp;lt;T&amp;gt;&#xA;{&#xA;    private readonly TextWriter _tw;&#xA;&#xA;    public RazorIndentedTemplate(TextWriter tw)&#xA;    {&#xA;        _tw = tw;&#xA;    }&#xA;    public override void Write(object value)&#xA;    {&#xA;        _tw.Write(value);&#xA;    }&#xA;&#xA;    public override void WriteLiteral(string literal)&#xA;    {&#xA;        _tw.Write(literal);&#xA;    }&#xA;...&#xA;    public override TemplateWriter Include(string name, object model, Type modelType)&#xA;    {&#xA;        return new TemplateWriter(w =&amp;gt;&#xA;        {&#xA;            var scripty  = ((Scripty.Core.Output.OutputFile)this._tw);&#xA;            scripty.IndentLevel++;&#xA;            Razor.Run(name: name, writer: this.CurrentWriter, modelType: modelType, model: model);&#xA;            scripty.IndentLevel--;&#xA;        });&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;And then in your template:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;var config = new FluentTemplateServiceConfiguration(c =&amp;gt;&#xA;    c&#xA;    //.WithEncoding(RazorEngine.Encoding.Raw)&#xA;    .WithBaseTemplateType(typeof(RazorIndentedTemplate.RazorIndentedTemplate&amp;lt;&amp;gt;))&#xA;    .ActivateUsing(context =&amp;gt; (ITemplate)Activator.CreateInstance(context.TemplateType, writer))&#xA;);&#xA;using (var service = RazorEngineService.Create(config))&#xA;{&#xA;...&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;With the code above, everytime that I included a subtemplate (using &lt;code&gt;@Include(&amp;quot;Subtemplate&amp;quot;)&lt;/code&gt;) I could find the TextWriter, and increase the indent level.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That&amp;rsquo;s not what I wanted.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;I wanted that indent to be increased according to the inline position of the cursor&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;string razorTemplate = @&amp;quot;&#xA;    public class Class1&#xA;    {&#xA;        @Include(&amp;quot;Class1Method1&amp;quot;) // this SHOULD increase indent level.&#xA;    }&#xA;    @Include(&amp;quot;otherclass&amp;quot;) // this should NOT increase indent level.&#xA;&amp;quot;;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In other words, I wanted includes to &lt;strong&gt;respect parent indentation even if the parent indentation was inline defined by some spaces right before the include&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So I needed to get current cursor position (how many characters after the last line break, but not counting indent spaces added by Scripty). Scripty OutputFile does NOT allow me to get that, and also does not allow me to replace it&amp;rsquo;s OutputFile by my own implementation (like RazorEngine does), but it allows to pass an inner text writer.&lt;br&gt;&#xA;I don&amp;rsquo;t remember if I really managed to make it work (I think I just gave up and decided to write my own before it), but it was certainly turning into a Frankestein:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;In my template (outside Scripty) I would had multi-line helper.&lt;/li&gt;&#xA;&lt;li&gt;In my template (outside Scripty) I would had indentation helper.&lt;/li&gt;&#xA;&lt;li&gt;In my template I would have a PositionableTextWriter (to keep track of cursor position in current line), and would pass this as inner writer of Scripty OutputFile.&lt;/li&gt;&#xA;&lt;li&gt;In another assembly I had to create my new RazorBaseTemplate, and register it to RazorEngine. Which in case would depend on my PositionableTextWriter.&lt;/li&gt;&#xA;&lt;li&gt;Razor includes would automatically decide if they should increase indentation.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;And in the end, it would still be hard to debug, bad intellisense (unless I was willing to create an individual cshtml file for each reusable block ever), and totally coupled.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Besides Scripty OuputFile which was limited, I also faced another dozen of weird problems when running Scripty (which uses Roslyn scripting, which have some &lt;strong&gt;serious&lt;/strong&gt; issues like &lt;a href=&#34;https://github.com/scriptcs/scriptcs/issues/1078&#34;&gt;not allowing namespaces&lt;/a&gt;) like assembly conflicts, namespaces problems, etc, all hard to solve.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So after frustration with both Scripty and RazorEngine, I decided to write my own TextWriter not only to keep track of current cursor position, but also to completely replace Scripty indent-control.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;My own TextWriter&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Writing my TextWriter was basically to keep track of current cursor position, so I would have to count number of characters written after each line break. And then I added the indentation-control, similar to Scripty. And then I added my helpers methods: the one that will &amp;ldquo;trim&amp;rdquo; multi-line strings, and the one that is a shorthand for C-blocks.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Ok, all working great - Now that indentation and multiline strings were more readable, it was time to create a robust way of using subtemplates. Probably I could use RazorEngine more easily, but since I was already rewriting from scratch I thought I could just use pure C# strings as my templating engine.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is what I had in mind:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;// This is a reusable method which you can embed anywhere inside your string-interpolated templates&#xA;string RenderProperties(List&amp;lt;Property&amp;gt; props)&#xA;{&#xA;    return () =&amp;gt; $@&amp;quot;&#xA;        {string.Join(Environment.NewLine, props.Select(prop =&amp;gt; $&amp;quot;public {prop.Type} {prop.Name} {{ get; set; }}&amp;quot;))}&amp;quot;;&#xA;}&#xA;public void GenerateMyClass()&#xA;{&#xA;    List&amp;lt;Property&amp;gt; props = new List&amp;lt;Property&amp;gt;() { new Property() { Name = &amp;quot;Name&amp;quot;, Type = &amp;quot;string&amp;quot; }, new Property() { Name = &amp;quot;Age&amp;quot;, Type = &amp;quot;int&amp;quot; } };&#xA;    var w = new TemplateTextWriter();&#xA;    string myNamespace = &amp;quot;codegencs&amp;quot;;&#xA;    string myClass = &amp;quot;Test1&amp;quot;;&#xA;    w.Write(@&amp;quot;&#xA;        namespace {myNamespace}&#xA;        {&#xA;            public class {myClass}&#xA;            {&#xA;                // My Properties start here&#xA;                { RenderProperties(props) }&#xA;            }&#xA;        }&amp;quot;);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The problem with this is that my Write method (yes, that one which can handle multiline strings) will receive as argument a single string. And this is what it would output, since the included method renders a linebreak and has no idea of inline indentation:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;namespace codegencs&#xA;{&#xA;    public class Test1&#xA;    {&#xA;        // My Properties start here&#xA;        public string Name { get; set; }&#xA;public int Age { get; set; }&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;And as you may have noticed, I&amp;rsquo;m a little obsessed with whitespace control, so the whitespeak freak got angry again because this way of using subtemplates wouldn&amp;rsquo;t work. Subtemplates should &amp;ldquo;respect current indent&amp;rdquo; even if the indent was implicitally defined by some spaces before the subtemplate was included.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Why not C&amp;#35; ?&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Since my TextWriter was fully C# (no templating language), and it was doing a good part of what I needed, why not do the whole subtemplating thing in C#? All I had to do is finding a way to &lt;strong&gt;capture current cursor position&lt;/strong&gt; before starting a subtemplate. In other words, I wanted &amp;ldquo;inline templates&amp;rdquo; which should be executed while preserving the current indentation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If it sounds weird to output C# code using C# code (really?), let me give some good reasons:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Compiled, typed, compile-time checking&lt;/li&gt;&#xA;&lt;li&gt;Full IDE support. The IDE which you are already familiar. With debugging support.&lt;/li&gt;&#xA;&lt;li&gt;Runs in .NET Standard and .NET Core&lt;/li&gt;&#xA;&lt;li&gt;Full access to all C# Framework. You can connect to SqlServer, you can use Newtonsoft JSON, etc.&lt;/li&gt;&#xA;&lt;li&gt;Full C# framework - you&amp;rsquo;re not limited to a small subset of string-manipulation functions.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;After all those reasons, all I can think is &amp;ldquo;Why hadn&amp;rsquo;t this been done before&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Interpolated Strings to the Rescue&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;As I explained above my inline templates would have to &lt;strong&gt;&amp;ldquo;capture&amp;rdquo; the current cursor position&lt;/strong&gt;, and therefore I would have to process the inner template only after the outer template (at least the parts which precede the inner template) had been processed/written.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Now comes the interesting part&amp;hellip;&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As soon I started exploring how I could control the rendering of the interpolated strings, I discovered that string interpolation is not only syntactic-sugar offered by the compiler, but it also &lt;a href=&#34;https://weblog.west-wind.com/posts/2016/Dec/27/Back-to-Basics-String-Interpolation-in-C&#34;&gt;translates into a class&lt;/a&gt; &lt;code&gt;FormattableString&lt;/code&gt; which &lt;a href=&#34;https://www.meziantou.net/interpolated-strings-advanced-usages.htm&#34;&gt;offers the format and the arguments individually&lt;/a&gt;, and that would be a perfect use for outer template (format) and inner templates (arguments):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;Func&amp;lt;List&amp;lt;Property&amp;gt;, FormattableString&amp;gt; RenderProperties = (props) =&amp;gt; ...&#xA;string myClass = &amp;quot;Test1&amp;quot;;&#xA;writer.Write($@&amp;quot;&#xA;    public class {myClass}&#xA;    {{&#xA;        // My Properties start here&#xA;        { RenderProperties(props) }&#xA;    }}&amp;quot;);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip; is translated into this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;Func&amp;lt;List&amp;lt;Property&amp;gt;, FormattableString&amp;gt; RenderProperties = (props) =&amp;gt; ...&#xA;string myClass = &amp;quot;Test1&amp;quot;;&#xA;writer.Write(FormattableStringFactory.Create(@&amp;quot;&#xA;    public class {0}&#xA;    {{&#xA;        // My Properties start here&#xA;        {1}&#xA;    }}&amp;quot;, new object[] { myClass, RenderProperties(props) } );&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;PS: since interpolated strings use braces as control character, we have to use double braces for escaping braces.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;FormattableStringFactory.Create&lt;/code&gt; creates an object of type &lt;code&gt;FormattableString&lt;/code&gt;, which has the &lt;code&gt;format&lt;/code&gt; and the &lt;code&gt;arguments&lt;/code&gt;.&lt;br&gt;&#xA;If my &lt;code&gt;Write&lt;/code&gt; method expects a &lt;code&gt;string&lt;/code&gt;, the &lt;code&gt;FormattableString&lt;/code&gt; is implicitally converted into a regular string (and in case double braces will be rendered as single braces).&lt;br&gt;&#xA;On the other hand, if method expects a &lt;code&gt;FormattableString&lt;/code&gt;, we can use the &lt;code&gt;format&lt;/code&gt; and &lt;code&gt;arguments&lt;/code&gt; explicitly - so we can process the format block by block, and when we reach each argument &lt;code&gt;{X}&lt;/code&gt; we can &amp;ldquo;save&amp;rdquo; the current position and therefore &lt;strong&gt;preserve the current indentation&lt;/strong&gt;.&lt;br&gt;&#xA;So all I have to do is &lt;strong&gt;process (writing to output) the string format until I found the embedded argument&lt;/strong&gt;, then &lt;strong&gt;process the inline argument&lt;/strong&gt;, and repeat until the end of the string format. So with string interpolation we can embed complex subtemplates inside the parent template, while respecting the &amp;ldquo;cursor position&amp;rdquo; where the inner template starts.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;// This is a reusable method which you can embed anywhere inside your string-interpolated templates&#xA;Func&amp;lt;FormattableString&amp;gt; RenderProperties(List&amp;lt;Property&amp;gt; props)&#xA;{&#xA;    return () =&amp;gt; $@&amp;quot;&#xA;        {string.Join(Environment.NewLine, props.Select(prop =&amp;gt; $&amp;quot;public {prop.Type} {prop.Name} {{ get; set; }}&amp;quot;))}&amp;quot;&#xA;    ;&#xA;}&#xA;public void GenerateMyClass()&#xA;{&#xA;    List&amp;lt;Property&amp;gt; props = new List&amp;lt;Property&amp;gt;() { new Property() { Name = &amp;quot;Name&amp;quot;, Type = &amp;quot;string&amp;quot; }, new Property() { Name = &amp;quot;Age&amp;quot;, Type = &amp;quot;int&amp;quot; } };&#xA;    var writer = new TemplateTextWriter();&#xA;    string myNamespace = &amp;quot;codegencs&amp;quot;;&#xA;    string myClass = &amp;quot;Test1&amp;quot;;&#xA;    writer.Write($@&amp;quot;&#xA;        namespace {myNamespace}&#xA;        {{&#xA;            public class {myClass}&#xA;            {{&#xA;                // My Properties start here&#xA;                { RenderProperties(props) }&#xA;            }}&#xA;        }}&amp;quot;);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;And the output is:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;namespace codegencs&#xA;{&#xA;    public class Test1&#xA;    {&#xA;        // My Properties start here&#xA;        public string Name { get; set; }&#xA;        public int Age { get; set; }&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As you can see, the inner block has multiple lines, and yet all those lines were written in the same position where the first line started. In other words, the inner block was fully written in the &amp;ldquo;current cursor position&amp;rdquo;. And again, if the text writer had indent level 1, all that output (outer and inner template) would have 4 more spaces before each line. Cool, uh?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For my inner template I used a &lt;code&gt;Func&amp;lt;FormattableString&amp;gt;&lt;/code&gt; but it could be other types like &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;Func&amp;lt;string&amp;gt;&lt;/code&gt;, or &lt;code&gt;FormattableString&lt;/code&gt; itself. They would all be evaluated &amp;ldquo;on demand&amp;rdquo;, only by the moment we need to output those parameters.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;FormattableString is automatically created by the compiler when you write an interpolated string.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The core method of my TextWriter is below, and basically it will get the format string, split by the arguments (&lt;code&gt;{0}&lt;/code&gt;, &lt;code&gt;{1}&lt;/code&gt;, etc, which are automatically generated by the compiler when you write a regular interpolated string), and will write (respecting current indent level, etc) a small part of the string format &amp;ldquo;up to the next argument&amp;rdquo;, then it will process the argument, which might be another interpolated string (entering into recursion), or might be a more reusable callback function, or just a plain string, and repeat until the end of the string.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;#region WriteFormattable(string format, params object[] arguments) - Basically, we split any interpolated string, and write block by block, doing lazy-evaluation of arguments. &#xA;/// &amp;lt;summary&amp;gt;&#xA;/// This is the &amp;quot;heart&amp;quot; of this class. Basically, we split any interpolated string, and write block by block, doing lazy-evaluation of arguments. &#xA;/// The idea of writing Func&amp;lt;FormattableString&amp;gt; is that we do NOT evaluate the {arguments} BEFORE the outer string is being written - they are only evaluated when needed&#xA;/// so we can capture the cursor position in current line, and preserve-it if the arguments render multi-line strings&#xA;/// &amp;lt;/summary&amp;gt;&#xA;public void WriteFormattable(FormattableString formattable)&#xA;{&#xA;    string format = formattable.Format;&#xA;    if (_trimBlockPaddings)&#xA;        format = TrimLeftPadding(format);&#xA;    if (_trimFirstEmptyLine)&#xA;        format = this.TrimFirstEmptyLine(format);&#xA;    object[] arguments = formattable.GetArguments();&#xA;    var matches = Regex.Matches(format, @&amp;quot;{\d}&amp;quot;);&#xA;    int lastPos = 0;&#xA;    for (int i = 0; i &amp;lt; matches.Count; i++)&#xA;    {&#xA;        // unescape escaped curly braces&#xA;        string text = format.Substring(lastPos, matches[i].Index - lastPos).Replace(&amp;quot;{{&amp;quot;, &amp;quot;{&amp;quot;).Replace(&amp;quot;}}&amp;quot;, &amp;quot;}&amp;quot;); &#xA;        base.WriteWithIndents(text);&#xA;        // arguments[i] may not work because same argument can be used multiple times&#xA;        var arg = arguments[int.Parse(matches[i].Value.Substring(1, 1))];&#xA;        if (arg as FormattableString != null)&#xA;        {&#xA;            base.ExecuteInlineAction(() =&amp;gt;&#xA;            {&#xA;                FormattableString subText = (FormattableString)arg;&#xA;                this.Write(subText);&#xA;            });&#xA;        }&#xA;        else if (arg as Func&amp;lt;FormattableString&amp;gt; != null)&#xA;        {&#xA;            base.ExecuteInlineAction(() =&amp;gt;&#xA;            {&#xA;                Func&amp;lt;FormattableString&amp;gt; subText = ((Func&amp;lt;FormattableString&amp;gt;)arg);&#xA;                this.Write(subText);&#xA;            });&#xA;        }&#xA;        else if (arg as Action&amp;lt;TemplateTextWriter&amp;gt; != null)&#xA;        {&#xA;            base.ExecuteInlineAction(() =&amp;gt;&#xA;            {&#xA;                Action&amp;lt;TemplateTextWriter&amp;gt; action = ((Action&amp;lt;TemplateTextWriter&amp;gt;)arg);&#xA;                action(this);&#xA;            });&#xA;        }&#xA;        else if (arg as Action&amp;lt;TextWriter&amp;gt; != null)&#xA;        {&#xA;            base.ExecuteInlineAction(() =&amp;gt;&#xA;            {&#xA;                Action&amp;lt;TextWriter&amp;gt; action = ((Action&amp;lt;TextWriter&amp;gt;)arg);&#xA;                action(this);&#xA;            });&#xA;        }&#xA;        else if (arg as Func&amp;lt;string&amp;gt; != null)&#xA;        {&#xA;            base.ExecuteInlineAction(() =&amp;gt;&#xA;            {&#xA;                string exec = ((Func&amp;lt;string&amp;gt;)arg)();&#xA;                this.Write(exec);&#xA;            });&#xA;        }&#xA;        else if (arg as string != null)&#xA;        {&#xA;            base.ExecuteInlineAction(() =&amp;gt;&#xA;            {&#xA;                string subText = ((string)arg);&#xA;                this.Write(subText);&#xA;            });&#xA;        }&#xA;        else&#xA;        {&#xA;            base.ExecuteInlineAction(() =&amp;gt;&#xA;            {&#xA;                this.Write(arg.ToString());&#xA;            });&#xA;        }&#xA;&#xA;        lastPos = matches[i].Index + matches[i].Length;&#xA;    }&#xA;    string lastPart = format.Substring(lastPos).Replace(&amp;quot;{{&amp;quot;, &amp;quot;{&amp;quot;).Replace(&amp;quot;}}&amp;quot;, &amp;quot;}&amp;quot;);&#xA;    base.WriteWithIndents(lastPart);&#xA;}&#xA;#endregion&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;And the indentation control basically will split all writes line-by-line, and for each new line will add indent before the text:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;#region WriteWithIndents(string value): writes line by line, and writes the indent strings before each new line&#xA;/// &amp;lt;summary&amp;gt;&#xA;/// This is the &amp;quot;heart&amp;quot; of this class. Basically, we split any multi-line string, and write line by line. &#xA;/// Before writing each new line we write the indent block, which could for example be 8 spaces (4 spaces in first indent level and 4 spaces for second indent level),&#xA;/// or 2 tabs (one for each indent level), or any combination.&#xA;/// &amp;lt;/summary&amp;gt;&#xA;/// &amp;lt;param name=&amp;quot;value&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&#xA;protected void WriteWithIndents(string value)&#xA;{&#xA;    if (string.IsNullOrEmpty(value))&#xA;        return;&#xA;&#xA;    var matches = _lineBreaksRegex.Matches(value);&#xA;&#xA;    int lastPos = 0;&#xA;    for (int i = 0; i &amp;lt; matches.Count; i++)&#xA;    {&#xA;        string line = value.Substring(lastPos, matches[i].Index - lastPos);&#xA;        string lineBreak = value.Substring(matches[i].Index, matches[i].Length);&#xA;        lastPos = matches[i].Index + matches[i].Length;&#xA;&#xA;        // if _dontIndentCurrentLine is set, it&#39;s because we&#39;re starting an inner block right &amp;quot;at cursor position&amp;quot;-  no need to indent again - we&#39;re already positioned!&#xA;        if (line.Length &amp;gt; 0 &amp;amp;&amp;amp; _currentLine.Length == 0 &amp;amp;&amp;amp; !_dontIndentCurrentLine)&#xA;            this.WriteIndent();&#xA;&#xA;        this.WriteRaw(line);&#xA;        if (_normalizeLineEndings)&#xA;            this.WriteRaw(_innerWriter.NewLine);&#xA;        else&#xA;            this.WriteRaw(lineBreak);&#xA;        _currentLine.Clear();&#xA;        _dontIndentCurrentLine = false;&#xA;    }&#xA;    string lastLine = value.Substring(lastPos);&#xA;&#xA;    if (lastLine.Length &amp;gt; 0 &amp;amp;&amp;amp; _currentLine.Length == 0 &amp;amp;&amp;amp; !_dontIndentCurrentLine)&#xA;        this.WriteIndent();&#xA;    this.WriteRaw(lastLine);&#xA;    _currentLine.Clear().Append(lastLine);&#xA;    _dontIndentCurrentLine = false;&#xA;}&#xA;#endregion&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Other than this, the last magic part is this function, which will &amp;ldquo;save current cursor position&amp;rdquo;, and will start a new &amp;ldquo;inline write&amp;rdquo;. For example, suppose that the outer template has implicitally written 4 spaces and then we&amp;rsquo;re starting an inline action, the TextWriter will &amp;ldquo;save&amp;rdquo; this 4 spaces, write the first line (no need to indent because it was &amp;ldquo;implicitally indented&amp;rdquo;), and then will explicitly indent the next lines with this same 4 spaces. (Would also work for tabs, or any other indentation string).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cs&#34;&gt;/// &amp;lt;summary&amp;gt;&#xA;/// If the current line has some manually-written whitespace, this method will &amp;quot;save&amp;quot; current cursor position, and in case the inline action writes a multi-line text,&#xA;/// the subsequent lines (after the first) will &amp;quot;preserve&amp;quot; the cursor position by adding this extra indent.&#xA;/// (&amp;quot;manually-written whitespace&amp;quot; does not count the automatic indents written by this class).&#xA;/// &amp;lt;/summary&amp;gt;&#xA;protected void ExecuteInlineAction(Action inlineAction)&#xA;{&#xA;    string indent = _currentLine.ToString();&#xA;    if (indent != null &amp;amp;&amp;amp; indent.Length &amp;gt; 0 &amp;amp;&amp;amp; string.IsNullOrWhiteSpace(indent))&#xA;    {&#xA;        this._levelIndent.Push(indent); // we could convert tabs to spaces or vice-versa&#xA;        _dontIndentCurrentLine = true;&#xA;        _currentLine.Clear();&#xA;        inlineAction();&#xA;        this._levelIndent.Pop();&#xA;    }&#xA;    else&#xA;    {&#xA;        inlineAction();&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Hope you enjoyed as much as I did.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;On next posts I may explore some new ideas, or maybe just develop some nice templates.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Full source code &lt;a href=&#34;https://github.com/Drizin/CodegenCS&#34;&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;</description>
      <dc:creator>Rick Drizin</dc:creator>
      <guid isPermaLink="false">0cbae5bc-8140-4626-b3a2-8fc3a886d254</guid>
      <pubDate>Fri, 20 Sep 2019 04:16:03 GMT</pubDate>
    </item>
    <item>
      <title>Installing Gitea (Git Server developed in GO) in Windows</title>
      <link>http://rickdrizin.com/installing-gitea-git-server-developed-in-go-in-windows</link>
      <description>&lt;p&gt;I&amp;rsquo;ve been a long-time user of &lt;a href=&#34;https://github.com/gogs/gogs&#34;&gt;gogs&lt;/a&gt;, but I decided to update my version recently and found out this fork called &lt;a href=&#34;https://github.com/go-gitea/gitea&#34;&gt;gitea&lt;/a&gt; which seems to have more features.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;How to install it on a Windows server:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://golang.org/dl/&#34;&gt;Download and install&lt;/a&gt; GO language. (It&amp;rsquo;s as easy as next-next-finish)&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;Open a command prompt and type:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;mkdir %GOPATH%&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;cd %GOPATH%&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;go get -d -u code.gitea.io/gitea&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;cd &amp;quot;%GOPATH%/src/code.gitea.io/gitea&amp;quot;&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;go build&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Optional: copy this gitea folder to some other folder (e.g. &lt;code&gt;C:\gitea\&lt;/code&gt;) if you don&amp;rsquo;t want to run this from your &lt;code&gt;%GOPATH%&lt;/code&gt; folder&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;.\gitea web&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;launch &lt;code&gt;http://localhost:3000&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Click &lt;code&gt;&amp;quot;sign in&amp;quot;&lt;/code&gt; to configure initial configuration (I suggest to use PostgreSQL)&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;Instead of running as command prompt, you can configure it as Windows Service:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Close &lt;code&gt;gitea web&lt;/code&gt; (ctrl-c)&lt;/li&gt;&#xA;&lt;li&gt;Edit &lt;code&gt;C:\gitea\custom\conf\app.ini:&lt;/code&gt;  and set Gitea to run using local system user: &lt;code&gt;RUN_USER = COMPUTERNAME$&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Open a command prompt (cmd) as an Administrator, then run the following command to register Gitea as a Windows service:&lt;br&gt;&#xA;&lt;code&gt;sc create gitea start= auto binPath= &amp;quot;&amp;quot;C:\gitea\gitea.exe&amp;quot; web --config &amp;quot;C:\gitea\custom\conf\app.ini&amp;quot;&amp;quot;&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Open “Windows Services”, search for the service named “gitea”, right-click it and click on “Run”. If everything is OK, Gitea will be reachable on &lt;a href=&#34;http://localhost:3000&#34;&gt;http://localhost:3000&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;References:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.gitea.io/en-us/install-from-source/&#34;&gt;Gitea installation&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.gitea.io/en-us/windows-service/&#34;&gt;Gitea run as Windows Service&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <dc:creator>Rick Drizin</dc:creator>
      <guid isPermaLink="false">67b73795-99cc-4b67-81cf-1e5729e9fb73</guid>
      <pubDate>Thu, 30 May 2019 04:16:47 GMT</pubDate>
    </item>
    <item>
      <title>Full Recovery vs Simple Recovery and the Ever-growing LDF file</title>
      <link>http://rickdrizin.com/full-recovery-vs-simple-recovery-and-the-ever-growing-ldf-file</link>
      <description>&lt;p&gt;Many newcomers (and even experienced developers who never had to manage their own SQL Servers) usually don&amp;rsquo;t understand &lt;strong&gt;the difference between Full Recovery mode and Simple Recovery mode&lt;/strong&gt;, and more than that they don&amp;rsquo;t know &lt;strong&gt;how to manage their SQL databases so that their LDF files won&amp;rsquo;t grow indefinitely&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Full Recovery vs Simple Recovery&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Simple Recovery uses transaction log only for uncommited transactions, so this file is very small, and doesn&amp;rsquo;t grow forever (allocated space is reused), so there is no Log backup for Simple Recovery.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Full Recovery tracks all past transactions in the transaction log, so log &lt;a href=&#34;http://stackoverflow.com/questions/56628/how-do-you-clear-the-sql-server-transaction-log&#34;&gt;grows forever unless we do maintenance&lt;/a&gt; .&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The major advantage of Full Recovery is that it allows us to use &lt;a href=&#34;https://www.mssqltips.com/sqlservertip/1229/sql-server-point-in-time-recovery/&#34;&gt;point in time restore&lt;/a&gt;, which allows to restore to an exact time, reverting (or inspecting) pontual database changes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;I strongly recommend Full recovery for any serious production environment.&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Ola Hallengren Maintenance Scripts&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Ola Hallengren is an experienced DBA who has developed these amazing &lt;a href=&#34;https://ola.hallengren.com/&#34;&gt;SQL Server Maintenance scripts&lt;/a&gt;, comprised of scripts for running backups, integrity checks, and index and statistics maintenance on all editions of Microsoft SQL Server.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://ola.hallengren.com/scripts/MaintenanceSolution.sql&#34;&gt;Download the scripts here&lt;/a&gt;, run then on your server, and it will install many useful stored procedures into your master database.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;I strongly recommend those scripts so that you don&amp;rsquo;t need to reinvent the wheel.&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Backup Databases&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;The following script will backup all your user databases&lt;/strong&gt; (applies both to Full Recovery or Simple Recovery)&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;-- Full backup (keeping 7 last days)&#xA;EXECUTE master.dbo.DatabaseBackup&#xA;@Databases = &#39;USER_DATABASES&#39;,&#xA;@Directory = &#39;C:\Backup&#39;,&#xA;@BackupType = &#39;FULL&#39;,&#xA;@Verify = &#39;Y&#39;,&#xA;@Compress = &#39;N&#39;,&#xA;@CheckSum = &#39;Y&#39;,&#xA;@CleanupTime = 168 -- 168hs =  7-day retention&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;OBS: &amp;ldquo;FULL&amp;rdquo; is for &amp;ldquo;FULL backup&amp;rdquo; (as opposed to DIFFERENTIAL backup), and has NOTHING to do with &amp;ldquo;Full Recovery&amp;rdquo;.&lt;br&gt;&#xA;OBS: USER_DATABASES can be replaced by a single database&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Backup Transaction Log&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;The following script will backup transaction log for your user databases&lt;/strong&gt; (applies only to Full Recovery)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;We should periodically backup the transaction log, so that it doesn&amp;rsquo;t grow indefinitely.&lt;/strong&gt;&#xA;Backing up the transaction log does NOT automatic shrink the transaction log, but ALLOWS us to shrink that log because SQL can only consider part of the transaction log as &amp;ldquo;unused space&amp;rdquo; if the respective transactions were backed up before.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;-- Transaction Log Backup&#xA;EXECUTE master.dbo.DatabaseBackup&#xA;@Databases = &#39;USER_DATABASES&#39;,&#xA;@Directory = &#39;C:\Backup&#39;,&#xA;@BackupType = &#39;LOG&#39;,&#xA;@ChangeBackupType = &#39;Y&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;OBS: Simple Recovery uses transaction log only for uncommited transactions, so there is no Log backup for Simple Recovery&lt;br&gt;&#xA;OBS: USER_DATABASES can be replaced by a single database&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Switching from Full to Simple Recovery&lt;/h1&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;ALTER DATABASE yourdb SET RECOVERY SIMPLE WITH NO_WAIT;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;OBS: The transaction log won&amp;rsquo;t shrink automatically! See below.&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;h1&gt;Switching from Simple to Full Recovery:&lt;/h1&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;ALTER DATABASE yourdb SET RECOVERY FULL WITH NO_WAIT;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h1&gt;Shrink the Transaction Log file (LDF)&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;If the database was in Full Recovery and didn&amp;rsquo;t had log maintenance, probably the log file became huge.&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Shrink the Transaction Log for a database in Simple Recovery Mode&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;If the database is running in Simple Recovery, you can shrink easily:&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;-- Shrink the file&#xA;USE yourdb;&#xA;DBCC SHRINKFILE(yourdb_log, 10); -- 10MB should be enough for us&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;OBS: &lt;strong&gt;yourdb_log is the LOGICAL NAME of the log file, and is not necessarily the same name as the physical file in disk, specially if your database was renamed or restored from a backup with different name.&lt;/strong&gt;&lt;br&gt;&#xA;e.g. if we create a database &amp;ldquo;Northwind&amp;rdquo; and later rename or restore into a database &amp;ldquo;Northwind2012&amp;rdquo; , the internal name of your log file will be Northwind_log, even if the physical file is called Northwind2012_log.ldf or whatever.&lt;br&gt;&#xA;&lt;strong&gt;To obtain the logical name of your log file, use this command:&lt;br&gt;&#xA;&lt;code&gt;SELECT name FROM sys.database_files where type_desc=&#39;LOG&#39;&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Shrink the Transaction Log for a database in Full Recovery Mode&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If the database is running in Full Recovery, shrinking may be harder. First of all, note that the transaction log has a pointer that indicates which part of the log file was backed up and which part wasn&amp;rsquo;t backed up. Shrinking can only remove parts which were backup up, so first of all, make a transaction log backup (see above &lt;strong&gt;Backup Transaction Log&lt;/strong&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To shrink the transaction log, you should use the same shrinking command as used for Simple Recovery (above), however, it&amp;rsquo;s common that we get an &lt;a href=&#34;http://stackoverflow.com/questions/7193445/dbcc-shrinkfile-on-log-file-not-reducing-size-even-after-backup-log-to-disk&#34;&gt;annoying error&lt;/a&gt; where the log doesn&amp;rsquo;t shrink and you get an error &lt;code&gt;Cannot shrink log file 2 (My DB_Log) because the logical log file located at the end of the file is in use&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To prevent/avoid this problem, &lt;strong&gt;just backup the transaction log of your database and &lt;a href=&#34;https://stackoverflow.com/a/21820281/3606250&#34;&gt;shrink the log file immediately after&lt;/a&gt;&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;use master;&#xA;EXECUTE master.dbo.DatabaseBackup&#xA;@Databases = &#39;yourdb&#39;,&#xA;@Directory = &#39;C:\Backup&#39;,&#xA;@BackupType = &#39;LOG&#39;,&#xA;@ChangeBackupType = &#39;Y&#39;;&#xA;&#xA;USE yourdb;&#xA;DBCC SHRINKFILE(yourdb_log, 200);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If the transaction log is already too large and you can&amp;rsquo;t even backup, just truncate the log file by temporarily changing to simple recovery mode:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;ALTER DATABASE yourdb SET RECOVERY SIMPLE WITH NO_WAIT;&#xA;&#xA;USE yourdb;&#xA;DBCC SHRINKFILE(yourdb_log, 200);&#xA;&#xA;ALTER DATABASE yourdb SET RECOVERY FULL WITH NO_WAIT;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Finally, after shrinking the file, configure it for auto-growth:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;USE [master];&#xA;GO&#xA;&#xA;ALTER DATABASE yourdb&#xA;  MODIFY FILE&#xA;  (NAME = yourdb_log, SIZE = 300MB, FILEGROWTH = 50MB);&#xA;GO&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h1&gt;Maintenance Jobs&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Based on the &lt;a href=&#34;https://ola.hallengren.com/frequently-asked-questions.html&#34;&gt;script&amp;rsquo;s author suggestion&lt;/a&gt;, this my suggested schedule for your servers:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;User databases:&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;p&gt;Integrity check (weekly)&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;EXECUTE dbo.DatabaseIntegrityCheck&#xA;@Databases = &#39;USER_DATABASES&#39;,&#xA;@CheckCommands = &#39;CHECKDB&#39;,&#xA;@PhysicalOnly = &#39;Y&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;Index &amp;amp; Statistics maintenance (weekly)&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;EXECUTE dbo.IndexOptimize @Databases = &#39;USER_DATABASES&#39;,&#xA;@FragmentationLow = NULL,&#xA;@FragmentationMedium = &#39;INDEX_REORGANIZE,INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE&#39;,&#xA;@FragmentationHigh = &#39;INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE&#39;,&#xA;@FragmentationLevel1 = 5,&#xA;@FragmentationLevel2 = 30,&#xA;@UpdateStatistics = &#39;ALL&#39;,&#xA;@OnlyModifiedStatistics = &#39;Y&#39; &#xA;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;Full backup (daily)&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;EXECUTE dbo.DatabaseBackup&#xA;@Databases = &#39;USER_DATABASES&#39;,&#xA;@Directory = &#39;C:\Backup&#39;,&#xA;@BackupType = &#39;FULL&#39;,&#xA;@Verify = &#39;Y&#39;,&#xA;@Compress = &#39;Y&#39;,&#xA;@CheckSum = &#39;Y&#39;,&#xA;@CleanupTime = 168 -- 168hs =  7-day retention&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;Transaction log (daily or hourly [or even more frequent] if we want to set up database mirroring)&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;EXECUTE dbo.DatabaseBackup&#xA;@Databases = &#39;USER_DATABASES&#39;,&#xA;@Directory = &#39;C:\Backup&#39;,&#xA;@BackupType = &#39;LOG&#39;,&#xA;@ChangeBackupType = &#39;Y&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;System databases:&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Full backup (daily)&lt;/li&gt;&#xA;&lt;li&gt;Integrity check (daily)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Server:&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;sp_delete_backuphistory&lt;/code&gt; (weekly)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;sp_purge_jobhistory&lt;/code&gt; (weekly)&lt;/li&gt;&#xA;&lt;li&gt;CommandLog cleanup (weekly)&lt;/li&gt;&#xA;&lt;li&gt;Output file cleanup (weekly)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;TO DO&lt;/strong&gt;: use &lt;code&gt;xp_cmdshell&lt;/code&gt; to zip backups, because SQL Express can&amp;rsquo;t compress backups&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;TO DO&lt;/strong&gt;: modify DatabaseBackup script to automatically shrink log file immediately after a LOG backup.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;On this post I just wanted to make a cheat sheet and scratch the surface. If you want to gain a deep understanding of Transaction Log backup and shrinking, please refer to &lt;a href=&#34;http://stackoverflow.com/a/18292136/3606250&#34;&gt;this&lt;/a&gt; answer and the references linked there.&lt;/p&gt;&#xA;</description>
      <dc:creator>Rick Drizin</dc:creator>
      <guid isPermaLink="false">86cd879a-03cd-4d71-832d-89285c00c5cd</guid>
      <pubDate>Sat, 11 Mar 2017 02:48:19 GMT</pubDate>
    </item>
  </channel>
</rss>