Wednesday, 3 October 2012

Tips and Hints: Entity Framework bits and pieces

This is a mix of all sorts of tiny bits I find while using Entity Framework. 

* Singularise tables' names.

Tables generated by EF will be named as plural automatically, in order to switch it to use singleton, the plural convention needs removing from model builder.
public class MyEntity : DbContext, IDisposable
{
public DbSet<Product> Product {get;set;}
public DbSet<Category> Category {get;set;}

public MyEntity(string nameOrConnectionString)
: base(nameOrConnectionString)
{ }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingEntitySetNameConvention>();
}
}

* Create a One-To-Many relationship table using Code First, and access it via LINQ.

The following setups are used to configure a one-to-many relationship:
public class Product
{
 public int ProductID { get; set; }

 public int CategoryID { get; set; }
 public Category Category { get; set; }
}

public class Category
{
 public int CategoryID { get; set; }
}

public class MyEntity : DbContext, IDisposable
{
 public DbSet<Product> Product { get; set; }
 public DbSet<Category> Category { get; set; }

 public MyEntity(string nameOrConnectionString)
 : base(nameOrConnectionString)
 { }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
 modelBuilder.Entity<Product>().HasOptional(p => p.Category).WithMany().HasForeignKey(m => m.CategoryID);
        }
}

* Create a Many-To-Many relationship table using Code First, and access it via LINQ.

The following setups are required to configure two tables with many to many relationship: 
public class Product
{
public int ProductID {get;set;}
public ICollection<Category> Category {get;set;}
}

public class Category
{
public int CategoryID {get;set;}
public ICollection<Product> Product {get;set;}
}

public class MyEntity : DbContext, IDisposable
{
public DbSet<Product> Product {get;set;}
public DbSet<Category> Category {get;set;}

public MyEntity(string nameOrConnectionString)
: base(nameOrConnectionString)
{ }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.HasMany(p => p.Category)
  .WithMany(p => p.Product)
.Map(
m =>
{
m.MapLeftKey("ProductID");
m.MapRightKey("CategoryID");
m.ToTable("ProductCategory");
});
}
}
Three tables, namely "Product", "Category" and "ProductCategory", are created as the result of previous code. Among which, "ProductCategory" is the relationship table containing primary key from "Product" and "Category" tables as its union unique key.

Use the following code to query for the joined result.
var productCategory = this.myEntity.Product
                .Include("Category")
                .Where(p => p.ProductID == productID)
                .ToString();

Sunday, 30 September 2012

Error: Handler “PageHandlerFactory-Integrated” has a bad module “ManagedPipelineHandler” in its module list in IIS 7.5

The shocking screen of death appeared on Friday when I created a new web project on my new PC, which says 'Handler “PageHandlerFactory-Integrated” has a bad module “ManagedPipelineHandler” in its module list'. 
IIS 7.5 Detailed Error - 500.21 - Internal Server Error
Server Error in Application "DEFAULT WEB SITE"
Internet Information Services 7.5

[Error Summary]
HTTP Error 500.21 - Internal Server Error
Handler "PageHandlerFactory-Integrated" has a bad module "ManagedPipelineHandler" in its module list

[Detailed Error Information]
Module IIS Web Core
Notification ExecuteRequestHandler
Handler PageHandlerFactory-Integrated
Error Code 0x8007000d
Requested URL http://localhost:80/default.aspx
Physical Path C:\inetpub\wwwroot\default.aspx
Logon Method Anonymous
Logon User Anonymous

[Most likely causes:]
•Managed handler is used; however, ASP.NET is not installed or is not installed completely.
•There is a typographical error in the configuration for the handler module list.

[Things you can try:]
•Install ASP.NET if you are using managed handler.
•Ensure that the handler module's name is specified correctly. Module names are case-sensitive and use the format modules="StaticFileModule, DefaultDocumentModule, DirectoryListingModule".

[Links and More Information]
IIS core does not recognize the module.
View more information »
By looking into the "Things you can try" and a bit of quick search, I realised it was my dodgy IIS that is causing the problem, which is essentially .NET is not registered with IIS. So I carry out the solution provided in "WIshMesh", and problem's solved!
Running the following commands solved this issue:

%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -i
%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -i

Monday, 24 September 2012

How to: Set Up a Source Control?

In an multi-developer environment, version control turns out to be a very important thing to do before crack on coding. There are certain options while setting up svn repository: 1. use public hosting service, e.g. google code, 2. set up locally repository, 3. set up network share. By comparing the usability and impact of the solutions, the last way of accessing repository seems to be more of a feasible action.

Even though dealing with day-to-day check in check out is an easy task using TortoiseSVN, to set up a network share svn repository requires a little bit more than that. That's why VisualSVN Server came to the rescue.


The step-by-step guide of setting up network share repository is as follow:


Server-side


1. Download and install VisualSVN Server

2. Open Visual SVN Server, right click on 'Repository', select 'Create New Repository'
3. Type in a name for the repository, also tick the check box 'Create default structure', which will give a nicely trunk-branch infra-structure
4. Job done on setting up network sharing svn
5. Right click on the name of the repository created, select 'Copy URL to Clipboard'

Client-side


1. Install TortoiseSVN

2. Right click on any project folder which is ready to be checked in as a trunk
3. Select 'TortoiseSVN', 'Import...'
4. Paste the https repository URL into the dialog box, and type in some comment for the check-in
5. After clicking 'OK', the project will get created in the repository in the URL
6. Right click in the folder where you would like to place the check out, select 'SVN checkout..'
7. Type in the same repository URL and set up check out directory
8. After clicking 'OK', you should get a copy of project which you can do any damage to, but be careful when checking them back in.

References: 
1. Why should set up network sharing repository: 
http://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-serversetup.html
2. A step-by-step guide video of server SVN setup:
http://www.youtube.com/watch?v=yGIo9_x-YSo
3. A step-by-step guide of server SVN setup: 
http://rajibmahmud.wordpress.com/2009/01/09/work-with-visual-svn-server-tortoise-svn/

Sunday, 9 September 2012

How to: Implement Dependency Injection in MVC 4 with Ninject

After creating mvc 4, the first thing I realised was there were slightly framework changes. Most significantly is inside the 'Global.asax.cs', which moves all the configuration setting registers into separate class files in the folder 'App_Start'. 

This actually prevents me from doing DI using 'Ninject.MVC3' in the way I used to implement in mvc 3. While Ninject package for mvc 4 is not out yet, I have to come up with an alternative solution. The following is the step by step guide.


1. Add 'Ninject.MVC3' package

You will see 'NinjectWebCommon.cs' file is generated inside 'App_Start' folder, which was meant to be part of package adding process.

2. Modify 'Global.asax.cs'


* Inherit 'MvcApplication' from 'NinjectHttpApplication' instead of 'HttpApplication'

* Implement 'OnApplicationStarted' method inherited from 'NinjectHttpApplication', and move all registers in 'Application_Start' this method to support the normal usage of those functions.
* Implement 'CreateKernel' method and register your own services.

namespace Ninject.MVC4
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();
        }
    }


    public class MvcApplication : NinjectHttpApplication
    {
        protected override void OnApplicationStarted()
        {
            base.OnApplicationStarted();

            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();
        }

        /// <summary>
        /// Creates the kernel that will manage your application.
        /// </summary>
        /// <returns>The created kernel.</returns>
        protected override IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            RegisterServices(kernel);
            return kernel;
        }

        /// <summary>
        /// Load your modules or register your services here!
        /// </summary>
        /// <param name="kernel">The kernel.</param>
        private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<IFlorentinesService>().ToDefaultChannel();
        }
    }
}

3. Modify controller

Introduce service into controller constructor before consumption.


namespace MVC4.Controllers
{  
public class HomeController : Controller  
{      
private ITestService service;
        public HomeController(ITestService service)      
{          
this. service = service;      
}  
}
}

4. Delete 'NinjectWebCommon.cs'

By specifying client endpoint, the service injection is done.