When it comes to both performance and security it’s important that the database isn’t running on the same server as the CMS.
Important note! If you already got a database model up and running and apply this changes you would need to do a migration to new database model. Here is some reference on how to fix that if you run into this problem:
Prerequisite
The example in this post are based on the code from here: http://sveinaandahl.blogspot.no/2015/08/how-to-integrate-aspnet-identity-with.htmlDatabase model
It was several elements I found during the analyze that could improve the performance, but here are a few easy fixes.
- It’s important that Datatypes in the database isn’t using MAX, e.g. NVARCHAR<MAX>. It’s actually better to set a large number. SQL will not index datatype the contains the datatype MAX.
- When this is fixed. You can add index on selected tables. By doing this the request dropped from 200 milliseconds to 30.
- Another effect by adding indexs is that the SQL server will be steady, even if the CMS frontend server gets a lot of request.
Most of this changes can be done through Entity framework. All the changes you want to apply to the data model can implemented in the OnModelCreating function. Here you can change the datatype and add index types that will be used a lot.
Update Models/Account/ApplicationUser.cs with this code
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Data.Entity.Infrastructure.Annotations;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
namespace TestSite.Models.Account
{
// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
public class MyClaims : IdentityUserClaim
{
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("EcfSqlConnection", throwIfV1Schema: false)
{
Database.SetInitializer<ApplicationDbContext>(new DropCreateDatabaseIfModelChanges<ApplicationDbContext>());
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//Shorten length on existing datatypes => improve performance
modelBuilder.Entity<ApplicationUser>().Property(u => u.PhoneNumber).HasMaxLength(20);
modelBuilder.Entity<ApplicationUser>().Property(u => u.PasswordHash).HasMaxLength(1024);
modelBuilder.Entity<ApplicationUser>().Property(u => u.SecurityStamp).HasMaxLength(1024);
modelBuilder.Entity<MyClaims>().Property(u => u.ClaimType).HasMaxLength(512);
modelBuilder.Entity<MyClaims>().Property(u => u.ClaimValue).HasMaxLength(512);
//Indexing important datatypes. => improve performance
modelBuilder.Entity<ApplicationUser>().Property(u => u.Email).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute()));
}
}
}
Happy coding!
Very practical advise indeed. Thanks for sharing
ReplyDelete/K