Monday, September 29, 2014

Modular code organization in ASP.NET MVC

Hated the way ASP.NET MVC imposes the sock drawer approach to your code organization?


Instead of sock drawer approach, we could organize our code into modules


Here's how we wanted our code organization be like:




With modular approach, the controller and its views are grouped together. Though you will lose the IDE navigation aspect of controller<->view, you won't miss it much as your contoller and its views are near each other



Notice that we didn't include {controller} in the url, the controller and module are the same thing

And notice too that we hardcoded the controller to "_"

"_Controller" won't work, ASP.NET MVC always append Controller to the controller parameter. Hence "_" is enough

using System.Web.Mvc;

namespace JustAspNetMvcThing.Areas.Hey
{
    public class HeyAreaRegistration : AreaRegistration
    {
        public override string AreaName { get{ return "Hey"; } }

        public override void RegisterArea(AreaRegistrationContext context)
        {

            // Add this:
            context.MapRoute(
                name: "Hey_Jude_Dont_Make_SandwichModule_default",
                url: "Hey/Jude/Dont/Make/SandwichModule/{action}/{id}",
                defaults: new { action = "Index", id = UrlParameter.Optional, controller = "_" },                
                // instead of this string-based code: "JustAspNetMvcThing.App.Hey.Jude.Dont.Make.SandwichModule" parameter, we could use typeof:
                namespaces: new[] { typeof(JustAspNetMvcThing.App.Hey.Jude.Dont.Make.SandwichModule._Controller).Namespace }
            );

            context.MapRoute(
                "Hey_default",
                "Hey/{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional }
            );
        }
    }
}

using System.Web.Mvc;

namespace JustAspNetMvcThing.Areas.Let
{
    public class LetAreaRegistration : AreaRegistration
    {
        public override string AreaName
        {
            get
            {
                return "Let";
            }
        }

        public override void RegisterArea(AreaRegistrationContext context)
        {

            // Add this:
            context.MapRoute(
                name: "Let_It_BeModule_default",
                url: "Let/It/BeModule/{action}/{id}",
                defaults: new { action = "Index", id = UrlParameter.Optional, controller = "_" },
                namespaces: new[] { typeof(JustAspNetMvcThing.App.Let.It.BeModule._Controller).Namespace }
            );
  

            context.MapRoute(
                "Let_default",
                "Let/{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional }
            );
        }
    }
}



Here's the base controller for our modules:
using System.Collections.Generic;
using System.Linq;

using System.Web.Mvc;

namespace JustAspNetMvcThing.App
{
    
    public class AppBaseController : Controller
    {

        public ViewResult View(object model, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "") 
        { 
                return TheView(model, /*viewName*/ null, memberName); 
        }


        public ViewResult View(string viewName = null, string masterName = null, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "")
        {
            return TheView((object)null, viewName, memberName);
        }


        ViewResult TheView(object model, string viewName, string memberName)
        {                        
            // Skip(1) skips JustAspNetMVcThing
            // SkipLastN excludes the controller

            // Sample output: App/Hey/Jude/Dont/Make/SandwichModule
            string modulePath = string.Join("/", this.GetType().FullName.Split('.').Skip(1).SkipLastN(1));

            // Sample output: /App/Hey/Jude/Dont/Make/SandwichModule/Bad.cshtml
            string viewFullPath =  "/" + modulePath + "/" + memberName + ".cshtml";
            
            return View(viewFullPath, model);
        }                
    }// class AppBaseController

    static class Helper
    {
        // Because .Reverse() is bad: http://stackoverflow.com/questions/4166493/drop-the-last-item-with-linq#comment4498849_4166546
        public static IEnumerable<T> SkipLastN<T>(this IEnumerable<T> source, int n)
        {
            var it = source.GetEnumerator();
            bool hasRemainingItems = false;
            var cache = new Queue<T>(n + 1);

            do
            {
                if (hasRemainingItems = it.MoveNext())
                {
                    cache.Enqueue(it.Current);
                    if (cache.Count > n)
                        yield return cache.Dequeue();
                }
            } while (hasRemainingItems);
        }
    }//class Helper
 
}//namespace


The Sandwich module, notice the _Controller name? We do that, so the controller will always sort first in the folder
using JustAspNetMvcThing.Models;

using System.Web.Mvc;

namespace JustAspNetMvcThing.App.Hey.Jude.Dont.Make.SandwichModule
{
    public class _Controller : AppBaseController
    {        
        // GET: /Hey/Jude/Dont/Make/SandwichModule/Bad/1
        public ViewResult Bad(int id = 0)
        {
            var p = new Person { FirstName = "Paul " + id };

            return View(p);
        }

    }
}

Here's one of the SandwichModule's views. Noticed that we can't use @model anymore. @model ModelHere is just a shorthand for @inherits System.Web.Mvc.WebViewPage<ModelHere>
@inherits System.Web.Mvc.WebViewPage<JustAspNetMvcThing.Models.Person>

Hello @Model.FirstName


The Be module:
using System.Web.Mvc;

namespace JustAspNetMvcThing.App.Let.It.BeModule
{
    public class _Controller : AppBaseController
    {        
        // GET: /Let/It/BeModule/ThePersonYouWantToBe
        public ActionResult ThePersonYouWantToBe()
        {
            return View();
        }

    }
}


Here's one of the BeModule's views:
@inherits System.Web.Mvc.WebViewPage

I am me!




Happy Coding!

Nested routing and folder in ASP.NET MVC Redux

Here's a way to make nested routing and folder in ASP.NET MVC: http://www.ienablemuch.com/2014/09/nested-routing-and-folder-in-aspnet-mvc.html


However, I find the code organization of that approach is not symmetrical enough, I wanted the code organization of controller and views be mirror image of each other, like this:





Here's the supporting code:

using System.Collections.Generic;
using System.Linq;

using System.Web.Mvc;

namespace JustAspNetMvcThing.App
{
    
    public class AreaBaseController : Controller
    {
        public ViewResult View(object model, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "") 
        { 
            return TheView(model, /*viewName*/ null, memberName); 
        }

        
        public ViewResult View(string viewName = null, string masterName = null, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "") 
        {             
            return TheView(/*model*/ (object)null, viewName, memberName); 
        }

        ViewResult TheView(object model, string viewName, string memberName)
        {
            if (viewName != null && model == null)
                return View(viewName, model: null);

            
            string origName = this.GetType().Name;
            // "Controller" string is stripped from "ItController"
            // "Controller" is stringly-typed, there's a better way, just wanted to make a short code
            // Sample output: It
            string controllerName = origName.Substring(0, origName.Length - "Controller".Length);

            // Skip(3) skips JustAspNetMVcThing.App.Controllers
            // SkipLastN excludes the controller, example: Hey/Jude/Dont/Make
            // Sample output: Hey/Jude/Dont/Make/It
            string controllerPath = string.Join("/", this.GetType().FullName.Split('.').Skip(3).SkipLastN(1)) + "/" + controllerName;

            // Sample output: /App/Views/Hey/Jude/Dont/Make/It/Bad.cshtml
            string viewFullPath =  "/App/Views/" + controllerPath + "/" + memberName + ".cshtml";
            
            return View(viewFullPath, model);
        }                
    }

    static class Helper
    {
        // Because .Reverse() is bad: http://stackoverflow.com/questions/4166493/drop-the-last-item-with-linq#comment4498849_4166546
        public static IEnumerable<T> SkipLastN<T>(this IEnumerable<T> source, int n)
        {
            var it = source.GetEnumerator();
            bool hasRemainingItems = false;
            var cache = new Queue<T>(n + 1);

            do
            {
                if (hasRemainingItems = it.MoveNext())
                {
                    cache.Enqueue(it.Current);
                    if (cache.Count > n)
                        yield return cache.Dequeue();
                }
            } while (hasRemainingItems);
        }
    }

}


Then do this on the Area registration:
using System.Web.Mvc;

namespace JustAspNetMvcThing.Areas.Hey
{
    public class HeyAreaRegistration : AreaRegistration
    {
        public override string AreaName { get{ return "Hey"; } }

        public override void RegisterArea(AreaRegistrationContext context)
        {

            // Add this:
            context.MapRoute(
                name: "Hey_Jude_Dont_Make_default",
                url: "Hey/Jude/Dont/Make/{controller}/{action}/{id}",
                defaults: new { action = "Index", id = UrlParameter.Optional },
                namespaces: new[] { "JustAspNetMvcThing.App.Controllers.Hey.Jude.Dont.Make" }
            );

            context.MapRoute(
                "Hey_default",
                "Hey/{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional }
            );
        }
    }
}


Voila! Your controller can continue its normal business. The View(object) resolves to View(object,memberName="") hence we are able to hook the normal View signature from the controller that inherits from AreaBaseController
using JustAspNetMvcThing.Models;

using System.Web.Mvc;

namespace JustAspNetMvcThing.App.Controllers.Hey.Jude.Dont.Make
{
    public class ItController : AreaBaseController
    {        
        // GET: /Hey/Jude/Dont/Make/It/Bad/1
        public ViewResult Bad(int id = 0)
        {
            var p = new Person { FirstName = "Paul " + id };

            return View(p);
        }

    }
}


Lastly, we must use @inherits instead of @model on our views. @model is a shorthand for @inherits
@inherits System.Web.Mvc.WebViewPage<JustAspNetMvcThing.Models.Person>  

Hello @Model.FirstName




Happy Coding!

50% Sure

The amusing thing with running ASP.NET MVC in an environment other than Windows






Happy Deploying!

Deploy ASP.NET MVC to Linux

If you received this error when deploying Visual Studio ASP.NET MVC project to Linux/Unix Mono environment:

System.InvalidOperationException
The view 'Index' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Home/Index.aspx
~/Views/Home/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
~/Views/Home/Index.cshtml
~/Views/Home/Index.vbhtml
~/Views/Shared/Index.cshtml
~/Views/Shared/Index.vbhtml


Chances are the Precompile during publishing option is checked when you published your project, just uncheck it then the error will go away:





Tested ASP.NET MVC 4


Note that if you are deploying ASP.NET MVC project instead of ASP.NET one, the fastcgi_index in configuration file "/etc/nginx/sites-available/default" have to be removed, otherwise you'll receive this error:





Update Oct 4, 2014


Upon further investigation. We can also leave the Precompile during publishing checked, but we must click Configure link, then uncheck the Allow precompiled site to be updatable




Happy Deploying!


Sunday, September 28, 2014

Nested routing and folder in ASP.NET MVC

Nested routing and folder is doable in Laravel

Ever wanted to have a nested url and folder in ASP.NET MVC too? e.g., http://example.com/Hey/Jude/Dont/Make/It/Bad/1

It's doable in ASP.NET MVC by straying outside of convention-over-configuration. First, configure the routing, and then be explicit in your controller when specifying your view's path. Voila! you can now place your view anywhere you wanted it to, but most likely you'll want the folder hierarchy be symmetrical with your url

To cut to the chase, here it is in picture:



Note that we can't use @model directive on our view anymore with the approach above. So we have to explicitly use @inherits. @model ModelHere is shorthand for @inherits System.Web.Mvc.WebViewPage<ModelHere>, achieves the same thing. For details, see this: http://stackoverflow.com/questions/8127462/the-view-must-derive-from-webviewpage-or-webviewpagetmodel


Visual Studio cannot navigate anymore to your view with the approach above, however with ReSharper it's still able to navigate the view from your controller



Alternatively, if you don't like the sock drawer approach, you can use modular approach, here's one: http://www.ienablemuch.com/2014/09/modular-code-organization-in-aspnet-mvc.html

Friday, September 26, 2014

SignalR without generated proxy

Without generated proxy, you can just use plain html on your project, typical of SPA applications. So you won't need this anymore in your SPA application: <script src='<%: ResolveClientUrl("~/signalr/hubs") %>'></script>


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="/Scripts/jquery-1.6.4.min.js"></script>
    <script src="/Scripts/jquery.signalR-2.1.2.js"></script>
</head>
<body>

    <input type="text" id="theMessage" />

    <button>Loading...</button>

    <div id="messages"></div>

</body>

<script>
    $(function () {
        var tmntConnection = $.hubConnection();

        var tmntHub = tmntConnection.createHubProxy('tmntHub');

        
        tmntHub.connection.start(function () {




            var uuid = generateUUID();
            $('button').text('Ready').click(function () {
                var text = $('#theMessage').val();
                tmntHub.invoke('tellAprilONeil', uuid, text);
            });


            // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
            function generateUUID() {
                var d = new Date().getTime();
                var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
                    var r = (d + Math.random() * 16) % 16 | 0;
                    d = Math.floor(d / 16);
                    return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16);
                });
                return uuid;
            };

        })


        tmntHub.on('cowabungaToTurtles', function (name, message) {

            $('#messages').append("<p>" + name + ": " + message + "</p>");
        });

        
    });
</script>

</html>



Contrast the above to SignalR with generated proxy: http://www.ienablemuch.com/2014/09/signalr-in-three-easy-steps.html


Happy Coding!


Thursday, September 25, 2014

SignalR in three easy steps

Step 0: Create an empty ASP.NET Web Application, get SignalR from Nuget


Step 1, create the start-up class. SignalR look for the name Startup when your app starts

using Owin;

// If you need to use other class name http://www.asp.net/aspnet/overview/owin-and-katana/owin-startup-class-detection
// [assembly: Microsoft.Owin.OwinStartup(typeof(PlaySignalR.StartMeUp))]

namespace PlaySignalR
{

    // By convention, SignalR look for Startup class name. Renaming this would cause runtime error if you don't specify OwinStartup attribute
    public class Startup
    {
        // SignalR also look for this method signature. The name Configuration could also be renamed, it's specified in attribute/web.config
        public void Configuration(Owin.IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}


Step 2, create a communication hub:

namespace PlaySignalR
{
    // Teenage Mutant Ninja Turtles Hub
    public class TmntHub : Microsoft.AspNet.SignalR.Hub
    {
        public void TellAprilONeil(string name, string message)
        {
            Clients.All.cowabungaToTurtles(name, message);
        }
    }
}


Last step, add Default.aspx, then use this:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="PlaySignalR.Default" %>

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="/Scripts/jquery-1.6.4.min.js"></script>
    <script src="/Scripts/jquery.signalR-2.1.2.js"></script>
    <script src='<%: ResolveClientUrl("~/signalr/hubs") %>'></script>
</head>
<body>
    
    <input type="text" id="theMessage" />

    <button>Send message</button>

    <div id="messages"></div>

</body>

<script>
    $(function () {
        var tmntHub = $.connection.tmntHub;

        tmntHub.connection.start();

        tmntHub.client.cowabungaToTurtles = function (name, message) {
            
            $('#messages').append("<p>" + name + ": " + message + "</p>");
        };

        $('button').click(function () {
            var text = $('#theMessage').val();            
            tmntHub.server.tellAprilONeil('<%: Guid.NewGuid()%>', text);            
        });
        

    });
</script>

</html>



Complete code: https://github.com/MichaelBuen/PlaySignalR


Happy Coding!

Wednesday, September 24, 2014

DryIoc ASP.NET Web API error

Error
Check your custom 'IHttpControllerActivator' and make sure that it will not manufacture the same instance.


Use Reuse.InResolutionScope instead:
using System;
using System.Linq;
using System.Web.Http;

using DryIoc;
using System.Reflection;

namespace Craft
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        DryIoc.Container _container;

        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);


            _container = new DryIoc.Container();                        

            Assembly assembly = typeof(WebApiApplication).Assembly;

            foreach (var controller in assembly.GetTypes().Where(t => typeof(ApiController).IsAssignableFrom(t)))
            {
                _container.Register(controller, DryIoc.Reuse.InResolutionScope);                
            }

            _container.Register<ISampleService, SampleService>(DryIoc.Reuse.Singleton);
            
            GlobalConfiguration.Configuration.Services.Replace(typeof(System.Web.Http.Dispatcher.IHttpControllerActivator), new ControllerActivator(_container));
        }

        public override void Dispose()
        {
            _container.Dispose();
            base.Dispose();
        }
    }



    // http://blog.ploeh.dk/2012/09/28/DependencyInjectionandLifetimeManagementwithASP.NETWebAPI/
    // http://blog.ploeh.dk/2012/10/03/DependencyInjectioninASP.NETWebAPIwithCastleWindsor/
    public class ControllerActivator : System.Web.Http.Dispatcher.IHttpControllerActivator
    {
        DryIoc.Container _container;

        public ControllerActivator(DryIoc.Container container)
        {
            _container = container;
        }

        public System.Web.Http.Controllers.IHttpController Create(
            System.Net.Http.HttpRequestMessage request,
            System.Web.Http.Controllers.HttpControllerDescriptor controllerDescriptor,
            Type controllerType)
        {

            var controller = (System.Web.Http.Controllers.IHttpController)_container.Resolve(controllerType);

            _container.ResolvePropertiesAndFields(controller);

            return controller;
        }       
    }

    public interface ISampleService
    {
        string GetMessage();
    }


    public class SampleService : ISampleService
    {

        string ISampleService.GetMessage()
        {
            return "Hello Kel " + Guid.NewGuid();
        }
    }

} // namespace



This code: _container.ResolvePropertiesAndFields(controller), is not needed when we pass the interfaces to constructor instead


P.S.

A good read on why ASP.NET Web API's IDependencyResolver is a Service Locator pattern:

"Jeff, thank you for writing. You are indeed correct that one of the many problems with the Service Locator anti-pattern(and therefore also IDependencyResolver) is that the overall context is hidden. Glenn Block originally pointed that particular problem out to me.
This is also the case with IDependencyResolver, because when GetService(Type) or GetServices(Type) is invoked, the only information the composition engine knows, is the requested type. Thus, resolving something that requires access to the HttpRequestMessage or one of its properties, is impossible with IDependencyResolver, but perfectly possible with IHttpControllerActivator.
So, yes, I would definitely say that any DI Container that provides 'ASP.NET Web API integration' by implementing IDependencyResolver is missing out. In any case, these days I rarely use a DI Container, so I don't consider it a big deal - and if I need to use a DI Container, I just need to add those few lines of code listed above in this blog post." -- Mark Seemann

And why Service Locator is an anti-pattern: http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/



Happy Coding!

Musings on DI / IoC containers

I stepped on the holy war of all holy wars, choice of DI :D


I believe we don't need too much documentation on DI, it's the most well-defined component in our field of industry. The list of feature a DI provides is very narrow/well-defined and straightforward, the amount of documentation we need on a DI doesn't need to be book/encyclopedia-like. A cheat sheet would do


So I would hazard a guess, given that DI's functionality is straightforward, any amount of documentation on specific brand of DI would be good enough


On the flip side of the coin, I'm even wary of something if it has many google results/documentation, if most of those documentations/blogs are just troubleshooting or work-around on shortcoming of an specific brand of component


Documentations on DIs are overrated, DI is like the notepad/mspaint of frameworks :-) They just have few functionality, they need little to no documentation, I can live by with a cheat sheet; if there is none, we will create one, even the IDE's autocomplete could be enough. The DI itself is overrated


I'll explore DryIoc from its documentation and see if I'll hit a wall using it on ASP.NET Web API


DryIoc is the simplest of the bunch of other DIs. The author even let the DryIoc be downloaded in source code form from Nuget (of course we can also download the DLL one from Nuget). That's a testament how the author is confident of how simple DryIoc is


Otherwise, there's a second or third fastest and has a good documentation:

DryIoc, LightInject and SimpleInjector offer a very performance combined with support for advanced scenarios like interception and generic decorators.
Simple Injector and LightInject also provide extensive documentation and support all important platforms. -- Daniel Palme


If the documentation is not good enough, we will go with Funq or even Unity, I'm very familiar with Funq :P Rest assured, it's easy to familiarize ourselves on *ALL* DIs, they almost look the same, tried Castle, Ninject, Funq, Unity. DI is the most uncomplicated framework among all frameworks. When you already know one, it's easy to get a headstart on another one



Heheh if there's only a DI for a DI, we can easily plug other faster/well-documented DI if the existing DI is not up to par with our needs, documentation-wise, functionality-wise and performance-wise. Oh.. I think I'm having a dependency Inception on this one O_o



Happy Coding!

Sunday, September 14, 2014

LEFT JOIN GROUP BY HAVING COUNT on Entity Framework

Objective, create a Linq query that shows all persons with pay history count of zero or three on entities


This is how our Linq's query should be like in SQL:

select p.BusinessEntityID, p.FirstName, TheCount = count(ph.BusinessEntityId)
from Person.Person p
left join HumanResources.EmployeePayHistory ph on p.BusinessEntityID = ph.BusinessEntityID
group by p.BusinessEntityID, p.FirstName
having count(ph.BusinessEntityId) = 0 or count(ph.BusinessEntityId) = 3
order by TheCount



The two domain entities however doesn't belong in same aggregate..

namespace Domain
{
    public static class ThePerson
    {
        public class Person
        {
            public int    BusinessEntityId { get; set; }

            public string Title            { get; set; }
            public string FirstName        { get; set; }
            public string MiddleName       { get; set; }
            public string LastName         { get; set; }

            // public virtual ICollection<TheHumanResources.EmployeePayHistory> PayHistories { get; set; }
        }
    }
}


namespace Domain
{
    public static class TheHumanResources
    {
        public class EmployeePayHistory
        {
            public int                       BusinessEntityId { get; set; }
            public DateTime                  RateChangeDate   { get; set; }

            public virtual ThePerson.Person  Person           { get; set; }
            public decimal                   Rate             { get; set; } 
        }
    }
}


namespace DomainMapping
{
    public class TheDbContext : DbContext
    {
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<ThePerson.Person>().ToTable("Person.Person")
                .HasKey(x => x.BusinessEntityId);
                // .HasMany(x => x.PayHistories).WithRequired().HasForeignKey(x => x.BusinessEntityId);

                
               


            modelBuilder.Entity<TheHumanResources.EmployeePayHistory>()
                .ToTable("HumanResources.EmployeePayHistory")
                .HasKey(x => new { x.BusinessEntityId, x.RateChangeDate } )
                .HasRequired(x => x.Person)
                .WithRequiredDependent()
                .Map(m => m.MapKey("BusinessEntityID"));

        }
    }
}


..hence we can't make a simpler query like this:
var query =
    from person in ctx.Set<ThePerson.Person>().SelectMany(x => x.PayHistories.DefaultIfEmpty(), (person, payHistory) => new { person, payHistory })
    
    group person by new { person.person.BusinessEntityId, person.person.FirstName } into persons
    
    let TheCount = persons.Sum(x => x.payHistory != null ? 1 : 0)
    
    where TheCount == 0 || TheCount == 3
    
    orderby TheCount
    
    select new { persons.Key.BusinessEntityId, persons.Key.FirstName, TheCount };


Output:
SELECT
    [GroupBy1].[K1] AS [BusinessEntityId],
    [GroupBy1].[K2] AS [FirstName],
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT
        [Join1].[K1] AS [K1],
        [Join1].[K2] AS [K2],
        SUM([Join1].[A1]) AS [A1]
        FROM ( SELECT
            [Extent1].[BusinessEntityId] AS [K1],
            [Extent1].[FirstName] AS [K2],
            CASE WHEN ( NOT (([Extent2].[BusinessEntityId] IS NULL) AND ([Extent2].[RateChangeDate] IS NULL))) THEN 1 ELSE 0 END AS [A1]
            FROM  [Person].[Person] AS [Extent1]
            LEFT OUTER JOIN [HumanResources].[EmployeePayHistory] AS [Extent2] ON [Extent1].[BusinessEntityId] = [Extent2].[Person_BusinessEntityId1]
        )  AS [Join1]
        GROUP BY [K1], [K2]
    )  AS [GroupBy1]
    WHERE [GroupBy1].[A1] IN (0,3)
    ORDER BY [GroupBy1].[A1] ASC




Following is easy to read Linq with left join group by and having, but it's not efficient, this creates a subquery in SELECT:

var query = from person in ctx.Set<ThePerson.Person>()

            join payHistory in ctx.Set<TheHumanResources.EmployeePayHistory>() on person.BusinessEntityId equals payHistory.BusinessEntityId into payHistories
            from payHistoryNullable in payHistories.DefaultIfEmpty()

            let TheCount = payHistories.Count()

            where TheCount == 0 || TheCount == 3

            orderby TheCount ascending

            select new { person.BusinessEntityId, person.FirstName, TheCount };


Output:
SELECT
    [Project1].[BusinessEntityId] AS [BusinessEntityId],
    [Project1].[FirstName] AS [FirstName],
    [Project1].[C1] AS [C1]
    FROM ( SELECT
        [Extent1].[BusinessEntityId] AS [BusinessEntityId],
        [Extent1].[FirstName] AS [FirstName],
        -- subquery        
        (SELECT
            COUNT(1) AS [A1]
            FROM [HumanResources].[EmployeePayHistory] AS [Extent3]
            WHERE [Extent1].[BusinessEntityId] = [Extent3].[BusinessEntityId]) AS [C1]
        FROM  [Person].[Person] AS [Extent1]
        LEFT OUTER JOIN [HumanResources].[EmployeePayHistory] AS [Extent2] ON [Extent1].[BusinessEntityId] = [Extent2].[BusinessEntityId]
    )  AS [Project1]
    WHERE [Project1].[C1] IN (0,3)
    ORDER BY [Project1].[C1] ASC



Not as readable as the Linq query above, but this is better as this uses GROUP BY:

var query = from person in ctx.Set<ThePerson.Person>()

            join payHistory in ctx.Set<TheHumanResources.EmployeePayHistory>() on person.BusinessEntityId equals payHistory.BusinessEntityId into payHistories
            from payHistoryNullable in payHistories.DefaultIfEmpty()

            group payHistoryNullable by new { person.BusinessEntityId, person.FirstName } into payHistoriesNullable

            let TheCount = payHistoriesNullable.Sum(eachPayHistoryNullable => eachPayHistoryNullable != null ? 1 : 0)

            where TheCount == 0 || TheCount == 3

            orderby TheCount ascending
            select new { payHistoriesNullable.Key.BusinessEntityId, payHistoriesNullable.Key.FirstName, TheCount };


Output:

SELECT
    [GroupBy1].[K1] AS [BusinessEntityId],
    [GroupBy1].[K2] AS [FirstName],
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT
        [Join1].[K1] AS [K1],
        [Join1].[K2] AS [K2],
        SUM([Join1].[A1]) AS [A1]
        FROM ( SELECT
            [Extent1].[BusinessEntityId] AS [K1],
            [Extent1].[FirstName] AS [K2],
            CASE WHEN ( NOT (([Extent2].[BusinessEntityId] IS NULL) AND ([Extent2].[RateChangeDate] IS NULL))) THEN 1 ELSE 0 END AS [A1]
            FROM  [Person].[Person] AS [Extent1]
            LEFT OUTER JOIN [HumanResources].[EmployeePayHistory] AS [Extent2] ON [Extent1].[BusinessEntityId] = [Extent2].[BusinessEntityId]
        )  AS [Join1]
        -- efficient, uses GROUP BY 
        GROUP BY [K1], [K2] 
    )  AS [GroupBy1]
    WHERE [GroupBy1].[A1] IN (0,3)
    ORDER BY [GroupBy1].[A1] ASC            



Happy Coding!

Saturday, September 13, 2014

Interface Magic (at least to me)

Didn't know that interface could intercept the method of the base class even that base class is not implementing the interface

using System;
                    
public class Program
{
    public static void Main()
    {
        IRobot r = new Robot();

        r.SaySomething();
    }
}


public class Machine
{
    public void SaySomething()
    {
        Console.WriteLine("Hello");
    }
}

public interface IRobot
{
    void SaySomething();
}


public class Robot : Machine, IRobot
{
// and we don't have to implement IRobot here    
}




Live Code: https://dotnetfiddle.net/cqdt8z


Output:
Hello

I still have to find a use for that code found somewhere



Happy Coding!

Friday, September 12, 2014

WPF Command

Got lost on the new Command here:

public ICommand ShowEmailAddress
{
    get
    {
        return new Command(() => true, () => DialogService.Show(this.EmailAddress));
    }
}


Command is not available on base class library of .NET, we have to implement ICommand ourselves.

Found a sample implementation of ICommand here: http://www.markwithall.com/programming/2013/03/01/worlds-simplest-csharp-wpf-mvvm-example.html


Modified according to the need of code above:
public class Command : ICommand
{
    readonly Action _action;

    readonly Func<bool> _canExecute;

    
    public Command(Func<bool> canExecute, Action action)
    {
        _canExecute = canExecute;
        _action = action;
    }

    void ICommand.Execute(object parameter)
    {
        _action();
    }

    bool ICommand.CanExecute(object parameter)
    {
        // return true; // It's advisable to make this always true: http://www.markwithall.com/programming/2013/03/01/worlds-simplest-csharp-wpf-mvvm-example.html

        return _canExecute();
    }

#pragma warning disable 67
    public event EventHandler CanExecuteChanged;
#pragma warning restore 67
}


Happy Coding!

Thursday, September 11, 2014

Property changed event handler

If you want the implementation of the INotifyPropertyChanged interface..
public event PropertyChangedEventHandler PropertyChanged;

void OnPropertyChanged(string property)
{
 PropertyChangedEventHandler handler = this.PropertyChanged;
 if (handler != null)
  handler(this, new PropertyChangedEventArgs(property));
}



..more explicit, you can't just change the PropertyChanged implementation to this:
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged;

void OnPropertyChanged(string property)
{
 PropertyChangedEventHandler handler = this.PropertyChanged;
 if (handler != null)
  handler(this, new PropertyChangedEventArgs(property));
}


It will have this error:
An explicit interface implementation of an event must use event accessor syntax


Must do this:
PropertyChangedEventHandler _propertyChanged;
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
{
 add { _propertyChanged += value; }
 remove { _propertyChanged -= value; }
}

void OnPropertyChanged(string property)
{
 PropertyChangedEventHandler handler = this._propertyChanged;
 if (handler != null)
  handler(this, new PropertyChangedEventArgs(property));
}  


Happy Coding!

Trusted connection string is not allowed on IIS?

Trusted connection string format doesn't work when in IIS..


cfg.DataBaseIntegration(c =>
    {
        c.Driver<NHibernate.Driver.SqlClientDriver>();
        c.Dialect<NHibernate.Dialect.MsSql2008Dialect>();
        c.ConnectionString = "Server=.;Database=RideOfYourLife;Trusted_Connection=True";

        c.LogSqlInConsole = true;
        c.LogFormattedSql = true;                    
    });


.., the error cascades to ServiceStack as:
response Status
error CodeExceptionmessageError trying to resolve Service 'Marshaller.TheServices.ReservationResourceService' or one of its autowired dependencies (see inner exception for details)



The error is not helpful at all, so I tried to wire a simple IoC-injected object, that is an object with no database connection, and voila, the error gone!


Tracked the error in connection string, must change it to standard format:

cfg.DataBaseIntegration(c =>
    {
        c.Driver<NHibernate.Driver.SqlClientDriver>();
        c.Dialect<NHibernate.Dialect.MsSql2008Dialect>();
        c.ConnectionString = "Server=.;Database=RideOfYourLife;User Id=sa; Password=opensesame;";

        c.LogSqlInConsole = true;
        c.LogFormattedSql = true;                    
    });


I have yet to find out how to make trusted connection string work on IIS


Happy Coding!

Sunday, September 7, 2014

Intercepting SQL in NHibernate for Test Uses

Found an implementation for interceptor:

public class NHSQLInterceptor : EmptyInterceptor, IInterceptor
{
    NHibernate.SqlCommand.SqlString IInterceptor.OnPrepareStatement(NHibernate.SqlCommand.SqlString sql)
    {
        // SQL.NHibernateSQL is static property
        SQL.NHibernateSQL = sql.ToString();
        return sql;
    }
}



On configuration:

var config = new Configuration();
...
...
config.SetInterceptor(new SQLInterceptor());
...
...
ISessionFactory factory = config.BuildSessionFactory();
...
...
factory.OpenSession(config.Interceptor); // turns out passing the interceptor to session is not needed, interceptors still gets called despite removing this



Then I found something simpler on stackoverflow:
public class SqlStatementInterceptor : EmptyInterceptor
{
    public override NHibernate.SqlCommand.SqlString OnPrepareStatement(NHibernate.SqlCommand.SqlString sql)
    {
        SQL.NHibernateSQL = sql.ToString();
        return sql;
    }
}



Happy Coding!

Unit Testing NHibernate Caching

I read somewher that says HashtableCacheProvider is more ok on unit testing, somehow true, have to use it for unit testing for now

cfg.Cache(x =>
            {

                // This is more stable on unit test
                x.Provider<NHibernate.Cache.HashtableCacheProvider>();       

                // I don't know why SysCacheProvider has problem on simultaneous unit testing, 
                // might be SysCacheProvider is just giving one session factory, so simultaneous test see each other caches
                // This solution doesn't work: http://stackoverflow.com/questions/700043/mstest-executing-all-my-tests-simultaneously-breaks-tests-what-to-do

                // x.Provider<NHibernate.Caches.SysCache.SysCacheProvider>();                    
                

Use entity cache when fetching an entity

The following code contrast the difference on cache re-use between getting an entity via cached query, and via cached entity


Here's the common code:

namespace TestTheSecondLevelCache
{
    public class Common
    {
        public static ISessionFactory BuildSessionFactory()
        {
            var sf = DomainMapping.Mapper.BuildSessionFactory();

            using (var session = sf.OpenStatelessSession())
            using (var tx = session.BeginTransaction())
            {
                Console.WriteLine("Stateless update");
                var p = session.Get<Person>(1);
                p.FirstName = "John";
                session.Update(p);
                tx.Commit();
            }


            return sf;
        }
    }
}

Query caching:
[TestMethod]
public void Test_Query_Caching_Compare_This_To_Entity_Caching()
{

    var sf = Common.BuildSessionFactory();
    
    Action query = delegate
    {

        using (var session = sf.OpenSession())
        using (var tx = session.BeginTransaction())
        {
            Console.WriteLine("Query 1");
            var person = session.Query<Person>().Where(x => x.PersonId == 1).Cacheable().Single();
        }

        using (var session = sf.OpenSession())
        using (var tx = session.BeginTransaction())
        {

            Console.WriteLine("Query 2");
            var person = session.Query<Person>().Where(x => x.PersonId == 2).Cacheable().Single();
        }


        using (var session = sf.OpenSession())
        using (var tx = session.BeginTransaction())
        {
            Console.WriteLine("Query 3");
            var person = session.Query<Person>().Where(x => x.PersonId == 1).Cacheable().Single();
        }

        using (var session = sf.OpenSession())
        using (var tx = session.BeginTransaction())
        {
            Console.WriteLine("Query 4");
            var person = session.Query<Person>().Where(x => x.PersonId == 2).Cacheable().Single();
        }

    };


    query();

    using (var session = sf.OpenSession())
    using (var tx = session.BeginTransaction())
    {
        Console.WriteLine("Update");
        var p = session.Get<Person>(1);
        p.FirstName = "ZX-" + p.FirstName;
        session.Save(p);
        tx.Commit();
    }


    query();


    using (var session = sf.OpenSession())
    using (var tx = session.BeginTransaction())
    {
        Console.WriteLine("Assert");
        var p = session.Get<Person>(1);
        Assert.AreEqual("ZX-John", p.FirstName);
    }


}


Output:
Test Name:    Test_Query_Caching_Compare_This_To_Entity_Caching
Test Outcome:    Passed
Result StandardOutput:    
Stateless update
NHibernate: 
    SELECT
        person0_.PersonId as PersonId4_0_,
        person0_.FirstName as FirstName4_0_,
        person0_.LastName as LastName4_0_ 
    FROM
        Person person0_ 
    WHERE
        person0_.PersonId=@p0;
    @p0 = 1 [Type: Int32 (0)]
Query 1
NHibernate: 
    select
        person0_.PersonId as PersonId4_,
        person0_.FirstName as FirstName4_,
        person0_.LastName as LastName4_ 
    from
        Person person0_ 
    where
        person0_.PersonId=@p0;
    @p0 = 1 [Type: Int32 (0)]
Query 2
NHibernate: 
    select
        person0_.PersonId as PersonId4_,
        person0_.FirstName as FirstName4_,
        person0_.LastName as LastName4_ 
    from
        Person person0_ 
    where
        person0_.PersonId=@p0;
    @p0 = 2 [Type: Int32 (0)]
Query 3
Query 4
Update
Query 1
NHibernate: 
    select
        person0_.PersonId as PersonId4_,
        person0_.FirstName as FirstName4_,
        person0_.LastName as LastName4_ 
    from
        Person person0_ 
    where
        person0_.PersonId=@p0;
    @p0 = 1 [Type: Int32 (0)]
Query 2
NHibernate: 
    select
        person0_.PersonId as PersonId4_,
        person0_.FirstName as FirstName4_,
        person0_.LastName as LastName4_ 
    from
        Person person0_ 
    where
        person0_.PersonId=@p0;
    @p0 = 2 [Type: Int32 (0)]
Query 3
Query 4
Assert

As you can see, the query cache always gets evicted when there's a change on any of the row. Hence, even we didn't update person #2, all cached query on person gets evicted, resulting to re-fetching them from database. Not efficient


Contrast that query caching with entity caching, notice the use of Get:
[TestMethod]
public void Test_Entity_Caching_Compare_This_To_Query_Caching()
{

    var sf = Common.BuildSessionFactory();

    Action query = delegate
    {

        using (var session = sf.OpenSession())
        using (var tx = session.BeginTransaction())
        {
            Console.WriteLine("Query 1");
            var person = session.Get<Person>(1);
        }

        using (var session = sf.OpenSession())
        using (var tx = session.BeginTransaction())
        {

            Console.WriteLine("Query 2");
            var person = session.Get<Person>(2);
        }


        using (var session = sf.OpenSession())
        using (var tx = session.BeginTransaction())
        {
            Console.WriteLine("Query 3");
            var person = session.Get<Person>(1);
        }

        using (var session = sf.OpenSession())
        using (var tx = session.BeginTransaction())
        {
            Console.WriteLine("Query 4");
            var person = session.Get<Person>(2);
        }

    };


    query();

    using (var session = sf.OpenSession())
    using (var tx = session.BeginTransaction())
    {
        Console.WriteLine("Update");
        var p = session.Get<Person>(1);
        p.FirstName = "ZX-" + p.FirstName;
        session.Save(p);
        tx.Commit();
    }


    query();


    using (var session = sf.OpenSession())
    using (var tx = session.BeginTransaction())
    {
        Console.WriteLine("Assert");
        var p = session.Get<Person>(1);
        Assert.AreEqual("ZX-John", p.FirstName);
    }





}

Output:
Test Name:    Test_Entity_Caching_Compare_This_To_Query_Caching
Test Outcome:    Passed
Result StandardOutput:    
Stateless update
NHibernate: 
    SELECT
        person0_.PersonId as PersonId4_0_,
        person0_.FirstName as FirstName4_0_,
        person0_.LastName as LastName4_0_ 
    FROM
        Person person0_ 
    WHERE
        person0_.PersonId=@p0;
    @p0 = 1 [Type: Int32 (0)]
Query 1
NHibernate: 
    SELECT
        person0_.PersonId as PersonId4_0_,
        person0_.FirstName as FirstName4_0_,
        person0_.LastName as LastName4_0_ 
    FROM
        Person person0_ 
    WHERE
        person0_.PersonId=@p0;
    @p0 = 1 [Type: Int32 (0)]
Query 2
NHibernate: 
    SELECT
        person0_.PersonId as PersonId4_0_,
        person0_.FirstName as FirstName4_0_,
        person0_.LastName as LastName4_0_ 
    FROM
        Person person0_ 
    WHERE
        person0_.PersonId=@p0;
    @p0 = 2 [Type: Int32 (0)]
Query 3
Query 4
Update
Query 1
Query 2
Query 3
Query 4
Assert

It's more efficient, both entity 1 and 2 are not re-fetched from DB even there's a change on entity



Happy Coding!

Saturday, September 6, 2014

Unlimited undo even you close your Visual Studio

Install this autogit then automark


How it works, autogit automatically makes a git of your changes everytime you save your code. To view your changes, use automark, you can view your changes in browser, or you can view it in markdown format

NHibernate Second-Level Cache XOR Fetch

TL;DR

Don't use Fetch on entities that are already in the second level cache


Simulation:


If an entity(e.g., Country) needed from the main query (e.g., Order) are all already in second level cache(e.g., caused by displaying them in dropdowns, or pre-loaded at startup) and it infrequently changes, don't use Fetch on that entity:

var list = session.Query<Order>() 
           .Fetch(x => x.Country) // Remove this 
           .OrderBy(x => x.Country.CountryName); 

foreach (var item in list) 
{                      
    Console.WriteLine("Order Id: {0}\nOrder Date: {1}\nCountry: {2}", item.OrderId, item.OrderDate, item.Country.CountryName);                  
}

This is the query when there's a Fetch, inefficient:

SELECT  
     o.OrderId,  
     o.OrderDate,      
     c.CountryId, 
     o.Comment, 
     c.Country, 
     c.CountryName, 
     c.Population 
FROM  
    [Order] o 
LEFT JOIN 
    Country c 
        ON o.CountryId = p 
ORDER BY 
    c.CountryName 


Whereas if you remove Fetch..
var list = session.Query<Order>() 
           .OrderBy(x => x.Country.CountryName); 

foreach (var item in list) 
{                      
    Console.WriteLine("Order Id: {0}\nOrder Date: {1}\nCountry: {2}", item.OrderId, item.OrderDate, item.Country.CountryName);                  
} 
..it's less taxing for the database. Don't worry, you can still display the CountryName above, that's how awesome NHibernate second level caching is. Here's the resulting query:

SELECT  
     o.OrderId,  
     o.OrderDate,      
     c.CountryId, 
     o.Comment 
FROM  
     [Order] o 
LEFT JOIN 
     Country c 
         ON o.CountryId = c.CountryId
ORDER BY 
     c.CountryName 



Now, if you want to minimize the database load further, say you don't want to include the Order's comment, you can just select all the fields you need:

var list = session.Query<Order>().OrderBy(x => x.Country.CountryName).Select(x => new { x.OrderId, x.OrderDate, x.Country.CountryName });  


Though the above looks correct, the Order's comment is removed, the query bypassed the use of second level cache, and the resulting query is less efficient, int(CountryId) is more efficient than nvarchar(CountryName):


SELECT  
    o.OrderId,  
    o.OrderDate,          
    c.CountryName 
FROM  
    [Order] o 
LEFT JOIN 
    Country c 
        ON o.CountryId = c.CountryId
ORDER BY 
    c.CountryName 

And if you need the population, you need to add another column in Linq's Select, resulting to less efficient query:

SELECT  
     o.OrderId,  
     o.OrderDate,      
     c.CountryName, 
     c.Population 
FROM  
    [Order] o 
LEFT JOIN 
    Country c 
        ON o.CountryId = c.CountryId
ORDER BY 
    c.CountryName 


Here's the proper way to prevent over-selecting and at the same time maximizing the use of second-level cache:
var list = session.Query<Order>() 
           .OrderBy(x => x.Country.CountryName) 
           .Select(x => new { x.OrderId, x.OrderDate, Country = session.Get<Country>(x.Country.CountryId) });  
 
foreach (var item in list) 
{                      
    Console.WriteLine("Order Id: {0}\nOrder Date: {1}\nCountry: {2}\nPopulation: {3}", item.OrderId, item.OrderDate, item.Country.CountryName, item.Country.Population);                  
} 


The resulting query is very efficient, no over-select(e.g., Comment is not included) on main entity(Order), and the referenced entity's key is the only column included in the SELECT:

SELECT  
    o.OrderId,  
    o.OrderDate,      
    c.CountryId 
FROM  
    [Order] o 
LEFT JOIN 
    Country c 
        ON o.CountryId = c.CountryId
ORDER BY 
    c.CountryName 


Sample code: https://github.com/MichaelBuen/LocalizationWithFallbacksAndCaching

Happy Coding!

Thursday, September 4, 2014

There's one specific culture whose parent culture is not neutral

using System;
using System.Globalization;
using System.Linq;

public class SamplesCultureInfo
{

   public static void Main()
   {

      // Prints the header.
    Console.WriteLine("  {0} {1, 80}","SPECIFIC CULTURE", "PARENT CULTURE");
    
    
    Action<CultureTypes, Func<CultureInfo, bool>> display = (c, exp) => 
    {
        foreach (CultureInfo ci in CultureInfo.GetCultures(c).Where(exp).OrderBy(x => x.TwoLetterISOLanguageName))
        {
            Console.Write("0x{0} {1} {2, -70}", ci.LCID.ToString("X4"), ci.Name, ci.EnglishName);
            Console.WriteLine("0x{0} {1} {2} : {3}", ci.Parent.LCID.ToString("X4"), ci.Parent.Name, ci.Parent.EnglishName, ci.Parent.IsNeutralCulture);     
        }
    };
    
    Action<CultureTypes> displayAll = c => display(c, x => true);
    
    // displayAll(CultureTypes.SpecificCultures);
    // displayAll(CultureTypes.NeutralCultures);
    
    //// Only one specific culture which parent culture is not neutral:
    // CultureInfo.GetCultures(CultureTypes.SpecificCultures).All(x => x.Parent.IsNeutralCulture).Dump();        
    // CultureInfo.GetCultures(CultureTypes.SpecificCultures).Count(x => !x.Parent.IsNeutralCulture).Dump();
    //// This is that culture:        
    display(CultureTypes.SpecificCultures, x => !x.Parent.IsNeutralCulture);
    
    
        
    
    // CultureInfo.GetCultures(CultureTypes.NeutralCultures).Count().Dump();

   }

}

Live codes:
https://dotnetfiddle.net/PCq4vR
https://dotnetfiddle.net/17Bkny

Output:
SPECIFIC CULTURE                                                                    PARENT CULTURE
0x0803 ca-ES-valencia Valencian (Spain)                                             0x0403 ca-ES Catalan (Catalan) : False


Interesting: http://stackoverflow.com/questions/8354352/how-can-i-get-the-region-and-culture-info-for-bahamas