Database Object and EntityFramework : Asp.net 5

Using the checking account model that we created at the beginning of this chapter, we'll now see how we can write a small amount of code to associate a user account with a checking account, and then automatically generate database tables that reflect that relationship.

See the resister action method.
   // POST: /Account/Register
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task Register(RegisterViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };
                IdentityResult result = await UserManager.CreateAsync(user, model.Password);
                if (result.Succeeded)
                {
                    await SignInAsync(user, isPersistent: false);

                    // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
                    // Send an email with this link
                    // string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
                    // var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
                    // await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking here");

                    return RedirectToAction("Index", "Home");
                }
                else
                {
                    AddErrors(result);
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

We saw that a new account is created in the register method using an instance of application user.
  var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };

ApplicationUser.cs :

namespace AutomatedTellerMachine.Models
{
    public class ApplicationUser : IdentityUser
    {
        public async Task GenerateUserIdentityAsync(UserManager 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 ApplicationDbContext : IdentityDbContext
    {
        public ApplicationDbContext()
            : base("DefaultConnection", throwIfV1Schema: false)
        {
        }

        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }
    }
}


we see that this class is defined in identity models dot CS and it inherits from identity user.
Identity user is the model that's going to be stored in the database and contains properties like username and password hash, and we can add additional properties that we want to store in this inheriting class here.

 In this file, we also have a definition for application DB context, which inherits from identity DB context, which in turn, inherits from DB context.

A DB context will serve as the object layer we'll use to communicate with the database.
By inheriting from identity DB context, this is already going to give us properties, like users and roles, and we can use those to work directly with the user data in our database.
  public class ApplicationDbContext : IdentityDbContext

 The string default connection that's passed to the base class constructor refers to a connection string in web dot config, that will be used to connect to the database or to create the database if it doesn't already exist.
  public ApplicationDbContext()
            : base("DefaultConnection", throwIfV1Schema: false)
        {
        }

When you see into Web.config file, we will find:

   
  < connectionStrings >
    < add name = "DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-AutomatedTellerMachine-20140705054415.mdf;Integrated Security=True" providerName="System.Data.SqlClient" / >
  <  /connectionStrings >

 It refers to an instance of SQL server local DB. The data directory token between the pipes represents the app underscore data folder of our project, where it will create a database file using this file name "AutomatedTellerMachine-20140705054415.mdf". When we eventually do a deployment to a live server it will be easy to change these settings to use the full version of SQL server, and we can even maintain separate settings for development and production.

We'd like to add to our application DB context is a member that exposes our checking account data, and we do that by adding a public property that's a generic DB set of checking account, and I'll call that "checking accounts", and I'll need to bring system dot data dot entity into the picture.

namespace AutomatedTellerMachine.Models
{
    // 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 GenerateUserIdentityAsync(UserManager 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;

            //we can access this.UserName, this.Roles here
        }
    }

    public class ApplicationDbContext : IdentityDbContext
    {
        public ApplicationDbContext()
            : base("DefaultConnection", throwIfV1Schema: false)
        {
        }

        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }

        public DbSet CheckingAccounts { get; set; } //added
        //This is going to allow us to work directly with a checking account table,
//which we'll be creating shortly in the database.
    }
}


Now, In the checking account class, we'll add another property that will be a reference to the user that holds this account.


 public class CheckingAccount
    {
        public int Id { get; set; }

        [Required]
       // [StringLength(10,MinimumLength =6)]
        [RegularExpression(@"\d{6,10}", ErrorMessage ="Account Number must be between 6 to 10")]
        [Display(Name ="Account Number :")]
        public string AccountNumber { get; set; }

        [Required]
        [Display(Name = "First Name :")]
        public string FirstName { get; set; }

        [Required]
        [Display(Name = "Last Name :")]
        public string LastName { get; set; }

        public string Name
        {
            get
            {
                return String.Format("{0) {1}", this.FirstName, this.LastName);
            }
        }


        [DataType(DataType.Currency)]
        public decimal Balance { get; set; }

        public virtual ApplicationUser User { get; set; } //added just now

public string ApplicationUserId { get; set; } //It represeted Id of User property : Smart EntityFramework
    }

This will be automatically implemented with a foreign key that references the user table when our database is generated. Making it a virtual property allows it to be overridden by the framework with a mechanism that supports lazy loading of this related object.


Now, back in the Resister action method.


If the creation of the user succeeds, we can set the user up with a new checking account.
 // POST: /Account/Register
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task Register(RegisterViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };
                IdentityResult result = await UserManager.CreateAsync(user, model.Password);
                if (result.Succeeded)
                {
                    //The creation of the user succeeds
                    var db = new ApplicationDbContext();
                    var checkingAccount = new CheckingAccount() { FirstName = model.FirstName, LastName = model.LastName, AccountNumber="227", Balance=0, ApplicationUserId= user.Id };
                    db.CheckingAccounts.Add(checkingAccount);
                    db.SaveChanges();

                    await SignInAsync(user, isPersistent: false);

                    return RedirectToAction("Index", "Home");
                }
                else
                {
                    AddErrors(result);
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

We'll declare a new instance of application DB context, and a checking account. We'll copy the first name and last name from the register view model, and we'll cheat a little on the account number for now just by hard-coding it. Balance should be zero for a brand new account, and we'll assign user dot ID from the new user that was created to application user ID.

We can see the new database created in AppData folder.




Comments