Easy Solution On How to Stop Growing Log File Too Big

In various organizations, huge SQL databases are equipped, which perform more than millions of transactions per hour. A SQL server database has data files and transaction log files. Data files store the user data and transaction log files store all the changes user made in the database and all the details of the transactions performed while making changes.

Now, the issue is that this feature of logging the details, every time changes are made in SQL server can not be controlled or stopped. This causes a grave issue when the size of SQL server overgrows. However, the way in which these log files grow and configure can be controlled. So, to avoid SQL server log file growing unexpectedly, consider any of the following methods given below. Also, to manage the large area size, it is good to shrink log file size, we will discuss the ways to resolve the same issue in this content.

SQL Server- Solutions to Stop Growing Log File Too Big

There are numerous ways for truncating sql ldf too big file. Some of the chief solutions have been provided in the following segment of this content.

  • Monitor default Size Limit: In case SQL ldf file is growing too big then, put a large default size limit on the SQL server, so that it does not expands automatically and overloads the SQL server database.
  • Using the Memory Units: Remember to configure the expansion of log files by making use of the memory units instead of percentage if the SQL transaction log file grows quickly.
  • Changing the recovery model: Simple Recovery model definitely helps in controlling and shrinking the log file size. Based on how crucial the data is, user can choose any of the following recovery models namely,
    1. Simple Recovery Model
    2. Bulk-logged Recovery Model
    3. Full Recovery Model

In the simple model, the most recent backup of the database of SQL server is recovered while in the bulk-logged or full recovery model, database can be recovered up to the point of failure. This recovery is done by restoring transaction log file.

By default, Full recovery model is set. Then, user has to regularly back up the transaction log files to prevent them from becoming too large and to remove inactive transactions from transaction log. Also, consider this when taking back up of .ldf files.

NOTE: If user is defragmenting indexes, make use of DBCC INDEXDEFRAG and not DBCC DBREINDEX. If DBCC DBREINDEX is used then, transaction log file might expand drastically.

Using manual solution:

If maintenance is not carried on regularly, log file size grows too big. Therefore, it is recommended to take these manual steps before it takes up all available disk space. Now, let us look at the method to shrink a SQL Database’s transaction log file:

  1. Firstly, Open the SQL Server Management Studio and then log in to the proper SQL instance.
  2. In Object Explorer tree, expand the Database folder >> select database with large .ldf file.
  3. After this, Create a full backup of database by right-clicking on it >> Select Tasks >> Back Up.
    • User should make sure that Backup type is set to Full then, Delete any existing destinations >> add a new Disk destination.
    • Browse a location with a lot of free disk space >> rename the backup file with the .BAK extension.
    • Choose the bullet option for Overwrite all existing backup sets on the ‘Options’ page.
    • Finally, user can click on the ‘OK’ button to start the process of taking backup of log files.
  4. Similarly, create a transaction log backup of the database in the same manner as done above.
    • Right-click on database >> Select Tasks >> Backup and assure that backup type is set to Transaction log.
    • Choose the bullet option for Overwrite all existing backup sets on the ‘Options’ page.
    • Finally, user can click on the ‘OK’ button to start the process of taking backup of log files.
  5. The closing step is the shrinking of transaction log files by right-clicking database >> Tasks >> Shrink >> Files

NOTE: User may repeat steps 3,4 and 5 until the .ldf file size becomes physically smaller.

Conclusion

In this content, we have discussed various solutions on how to truncate .ldf files if transaction file size becomes too large. This is necessary in order to manage data with ease. Manual method and some general solutions have been written in this content to enlighten users when they come across such issues while dealing with SQL Server.

Judging Microsoft Imagine Cup – 2017

Judging Microsoft Imagine Cup (1st Round) – 2017 in Bangladesh
Venue: Microsoft Office, Dhaka, Bangladesh
Date: 19 March, 2017

Image cropping using Jcrop in ASP.NET MVC Application

What is Image cropping?

  • Image cropping refer to removal of some part of image
  • Uses to improve framing and size
  • Applied in photograph to resize image

Application overview
In this project, I will show image cropping of an employee phot when employee information saved and modified. Full crud operation applied in the application with image cropping.
Let’s have a look on the implementation of the project.

Tools and Technology used

I used following tools and technology to develop the project –

  1. Visual Studio 2015
  2. Visual C#
  3. ASP.NET MVC
  4. Entity Framework 5
  5. Razor view engine
  6. JCrop

Step 1: Create a ASP.net MVC Project
File -> New project and select the project template Visual C# -> ASP.NET Web Application (.NET Framework) -> Console application (.NET Core).

0108_01

Select MVC as a Template as ASP.NET Template and click OK

0108_02

Step 2: Change or Add Connection String
Change or Add connection string in Web.config as follows

  
    
  
  

Step 3: Install JCrop Nuget Package
Go to Tools -> NuGet Package Manager -> Manages NuGet Package Manager for the solution -> Search Jcrop and install jquery.jcrop.js

0108_02_B

Step 4: Create model class

Create model class “Employee” as follows.

Employee Class

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace JCropMVC.Models
{
    public class Employee
    {
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        [Display(Name = "Full Name")]
        [Required(ErrorMessage = "Name cannot be empty")]
        public string Name { get; set; }

        [Display(Name = "Father Name")]
        public string FatherName { get; set; }

        [Display(Name = "Designation")]
        public string Designation { get; set; }

        [Display(Name = "Mobile No")]
        public string Mobile { get; set; }

        [DataType(DataType.EmailAddress)]
        [Display(Name = "Email")]
        public string Email { get; set; }

        [Display(Name = "Image URL")]
        public string PhotoURL { get; set; }
    }
}

Step 5: Modify Context class
Modify ApplicationDbContext in IdentityModel Class

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

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

        public DbSet Employees { get; set; }
    }

Step 6: Create Controller and Views
Create Employees Controller and Views
Click Right button on Controller Folder->Add Controller. Now choose scaffolding template as MVC Controllers with views using Entity Framework and then Click Add.

0108_03

Now select Model class as Employee and Data Context Class as ApplicationDbContext as follows. Then click OK.

0108_04

Step 7: Modify the controller
Modify EmployeesController as follows. Here method ProcessImage(string croppedImage) is used to process and save image. An extra parameter added for Create and Edit action.

using System;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using JCropMVC.Models;
using System.IO;

namespace JCropMVC.Controllers
{
    public class EmployeesController : Controller
    {
        private ApplicationDbContext db = new ApplicationDbContext();

        // GET: Employees
        public ActionResult Index()
        {
            return View(db.Employees.ToList());
        }

        // GET: Employees/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Employee employee = db.Employees.Find(id);
            if (employee == null)
            {
                return HttpNotFound();
            }
            return View(employee);
        }

        // GET: Employees/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: Employees/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "Id,Name,FatherName,Designation,Mobile,Email,PhotoURL")] Employee employee, string avatarCropped)
        {
            string filePath = ProcessImage(avatarCropped);
            employee.PhotoURL = filePath;

            if (ModelState.IsValid)
            {
                db.Employees.Add(employee);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(employee);
        }

        /// 
        /// Process image and save in predefined path
        /// 
        /// 
        /// 
        private string ProcessImage(string croppedImage)
        {
            string filePath = String.Empty;
            try
            {
                string base64 = croppedImage;
                byte[] bytes = Convert.FromBase64String(base64.Split(',')[1]);
                filePath = "/Images/Photo/Emp-" + Guid.NewGuid() + ".png";
                using (FileStream stream = new FileStream(Server.MapPath(filePath), FileMode.Create))
                {
                    stream.Write(bytes, 0, bytes.Length);
                    stream.Flush();
                }
            }
            catch (Exception ex)
            {
                string st = ex.Message;
            }

            return filePath;
        }

        // GET: Employees/Edit/5
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Employee employee = db.Employees.Find(id);
            if (employee == null)
            {
                return HttpNotFound();
            }
            return View(employee);
        }

        // POST: Employees/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "Id,Name,FatherName,Designation,Mobile,Email,PhotoURL")] Employee employee, string avatarCropped)
        {
            string filePath = ProcessImage(avatarCropped);
            employee.PhotoURL = filePath;

            if (ModelState.IsValid)
            {
                db.Entry(employee).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(employee);
        }

        //[Authorize(Users ="sumon")]
        // GET: Employees/Delete/5
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Employee employee = db.Employees.Find(id);
            if (employee == null)
            {
                return HttpNotFound();
            }
            return View(employee);
        }

        // POST: Employees/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            Employee employee = db.Employees.Find(id);
            db.Employees.Remove(employee);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}

Step 8: Modify the views for Employee

Create.cshtml

@model JCropMVC.Models.Employee

@{
    ViewBag.Title = "Create";
}



@using (Html.BeginForm("Create", "Employees", null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.AntiForgeryToken()

    
@Html.ValidationSummary(true)
@Html.LabelFor(model => model.Name, new { @class = "" }) @Html.TextBoxFor(model => model.Name, new { @class = "form-control", placeholder = "Enter employee full name...", type = "text" }) @Html.ValidationMessageFor(model => model.Name)
@Html.LabelFor(model => model.FatherName, new { @class = "" }) @Html.TextBoxFor(model => model.FatherName, new { @class = "form-control", placeholder = "Enter father name...", type = "text" }) @Html.ValidationMessageFor(model => model.FatherName)
@Html.LabelFor(model => model.Designation, new { @class = "" }) @Html.TextBoxFor(model => model.Designation, new { @class = "form-control", placeholder = "Enter designation name...", type = "text" }) @Html.ValidationMessageFor(model => model.Designation)
@Html.LabelFor(model => model.Mobile, new { @class = "" }) @Html.TextBoxFor(model => model.Mobile, new { @class = "form-control", placeholder = "Enter mobile number...", type = "text" }) @Html.ValidationMessageFor(model => model.Mobile)
@Html.LabelFor(model => model.Email, new { @class = "" }) @Html.TextBoxFor(model => model.Email, new { @class = "form-control", placeholder = "Enter email address...", type = "text" }) @Html.ValidationMessageFor(model => model.Email)
@Html.LabelFor(model => model.PhotoURL, new { @class = "" })
Width:   Height: Crop Image
Employee Image

}
@Html.ActionLink("Back to List", "Index")
@section Scripts { @Scripts.Render("~/bundles/jqueryval") }

Edit.cshtml

@model JCropMVC.Models.Employee

@{
    ViewBag.Title = "Edit";
}

Edit

@using (Html.BeginForm()) { @Html.AntiForgeryToken() @*
*@

Employee


@Html.ValidationSummary(true, "", new { @class = "text-danger" }) @Html.HiddenFor(model => model.Id)
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "" }) @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.FatherName, htmlAttributes: new { @class = "" }) @Html.EditorFor(model => model.FatherName, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.FatherName, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.Designation, htmlAttributes: new { @class = "" }) @Html.EditorFor(model => model.Designation, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Designation, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.Mobile, htmlAttributes: new { @class = "" }) @Html.EditorFor(model => model.Mobile, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Mobile, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "" }) @Html.EditorFor(model => model.Email, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" })
@*
@Html.LabelFor(model => model.PhotoURL, htmlAttributes: new { @class = "" })
@Html.EditorFor(model => model.PhotoURL, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.PhotoURL, "", new { @class = "text-danger" })
*@
@Html.LabelFor(model => model.PhotoURL, new { @class = "" })
Width:   Height: Crop Image
Employee Image

@*
*@ }
@Html.ActionLink("Back to List", "Index")
@section Scripts { @Scripts.Render("~/bundles/jqueryval") }

Index.cshtml

@model IEnumerable

@{
    ViewBag.Title = "Index";
}

Index

@Html.ActionLink("Create New", "Create")

@foreach (var item in Model) { }
@Html.DisplayNameFor(model => model.Name) @Html.DisplayNameFor(model => model.FatherName) @Html.DisplayNameFor(model => model.Designation) @Html.DisplayNameFor(model => model.Mobile) @Html.DisplayNameFor(model => model.Email) @Html.DisplayNameFor(model => model.PhotoURL)
@Html.DisplayFor(modelItem => item.Name) @Html.DisplayFor(modelItem => item.FatherName) @Html.DisplayFor(modelItem => item.Designation) @Html.DisplayFor(modelItem => item.Mobile) @Html.DisplayFor(modelItem => item.Email) @**@ @*@Html.DisplayFor(modelItem => item.PhotoURL)*@ @Html.ActionLink("Edit", "Edit", new { id=item.Id }) | @Html.ActionLink("Details", "Details", new { id=item.Id }) | @Html.ActionLink("Delete", "Delete", new { id=item.Id })

Delete.cshtml

@model JCropMVC.Models.Employee

@{
    ViewBag.Title = "Delete";
}

Delete

Are you sure you want to delete this?

Employee


@Html.DisplayNameFor(model => model.Name)
@Html.DisplayFor(model => model.Name)
@Html.DisplayNameFor(model => model.FatherName)
@Html.DisplayFor(model => model.FatherName)
@Html.DisplayNameFor(model => model.Designation)
@Html.DisplayFor(model => model.Designation)
@Html.DisplayNameFor(model => model.Mobile)
@Html.DisplayFor(model => model.Mobile)
@Html.DisplayNameFor(model => model.Email)
@Html.DisplayFor(model => model.Email)
@Html.DisplayNameFor(model => model.PhotoURL)
@Html.DisplayFor(model => model.PhotoURL)
@using (Html.BeginForm()) { @Html.AntiForgeryToken()
| @Html.ActionLink("Back to List", "Index")
}

Step 9: Add image folders
Add Image folders and sub folders (Deafult and Photo) as follows. Add blank photo in the Default folder to show blank photo for the employee.

0108_05

Step 10: Add Employee link
Add Employee link in the nav bar of _Layout page as follows.

                

Step 11: Run the application
Now run the application. Click Employee link in the nav bar. You can View, add, modify and delete employee information. If you go to the create or edit page, you have an option to upload photo and have option to crop the image and then save the image with employee information. Yes! You are done. Let’s cheers!

0108_06

Learn How and When to Shrink Transaction Log File

Transaction logs consist of the records regarding activities taking place on the server database to which they are associated. At one point of time, these files run out of memory to record any more logs. Therefore, it is necessary to backup logs so that they can be cleared off whenever required. Shrinking is of the many procedures used for managing the transaction log files. The following segment acts as a guide on when to shrink transaction log files and what are the best practices to adopt when you do so.

Whys and Wherefores of Shrinking Transaction Log

When transactions are concerned, there are going to be instances where there is lack of storage space. If a transaction file consists of unused space it can be regained for future use. Doing this reduces the unnecessarily growing size of a transaction log file. What is being done here is a procedure known as shrinking of the log file.

NOTE: It is only possible to shrink a transaction log file in a scenario where the database is in an online state and a virtual log is free. However, in certain cases until the next truncation a log cannot be shrunk.

Generally, the truncation process occurs on its own as part of the simple recovery model when a database it is associated to is backed up. In addition, it also occurs as part of the full recovery model where the transaction is backed up. Nevertheless, a number of factors can affect the truncation procedure and delay it.

How Does Shrinking Take Place?

The procedure of shrinking a transaction log file is nothing but the removal of one or more than one virtual logs that exist. The unit of the reduction in size is equal to a virtual log file.

This can better be understood with an example:

There is a log file of 600 MB that is divided into multiple portions, i.e. 100 MB of virtual log file each, which makes 6 of them. This is done because the size of a log can only be decreased with an increment of up to 100 MB each. The variation in sizes can be 500 or 600 MB and not 533 or 625 MB.

Any virtual log that consists of active log records, i.e. active virtual log – is a part of the logical log file. Therefore, such virtual logs cannot be removed.

Things to Remember

In order to performing the shrinking of log files, it is necessary to first monitor the log space then a sequence of two stages follow up, i.e. shrinking of log file and then monitoring the shrinking events that have taken place.

To monitor available log space:

  1. DBCC SQLPERF (Transact-SQL)
  2. Sys.database files (Transact-SQL) – Lets you see the – size, growth, and max_size columns in association to the log

To shrink a transaction log:

  1. DBCC SHRINKFILE (Transact-SQL)
  2. Shrink transaction log file via SSMS

To monitor shrinking events:

  • Event Class – Log File Auto Shrink must be used

When a transaction log is shrunk removal of virtual logs (inactive) takes place. Therefore, in order to remain on the safer side and ensure database integrity during the procedure, it is highly recommended that backups be maintained.

Tips for SQL Server Transaction Log Backup

  1. In order to truncate SQL Server transaction log files, you must have them backed up. Not having regular backups of the transaction log may result in filling up the disk space.
  2. A full backup is not recommended, as it does not include the transaction logs.
  3. Use of ‘BACKUP LOG’ must be made in order to backup transaction logs.
  4. If transaction logs are not to be backed up according to the Database Administrator, Simple Recovery is suggested.

Necessity Of Backing Up Tail Log When Restoring The Database

One of the features that have been incorporated with MS SQL Server 2005 and its newer versions is Tail-Log Backups, which is mainly associated with backup and restore of SQL Server databases using full or bulk-logged recovery models. In the article, we will be learning about the necessity of backing up Tail log when restoring the database of SQL Server.

What is Tail-Log Backup?

The Tail-Log Backups can be defined as the process to capture all the log records that have not been backed up (as the name suggests, the tail of the log). It is a feature that was introduced in SQL Server 2005 and its later versions. This form of log backup is mainly done to avoid loss of work and to make sure that the log chain is kept intact. It is necessary to have a backup of transaction log tail in order to start restore database operation to the point of failure. The tail-log backup will be the last backup of which one can use for the recovery purpose of database.

Though Tail-Log Backup proves to be quite beneficial in the cases stated above, there are situations that does not require Tail-log backup. They are:

  • There is no need of Tail-log backup if recovery point is already present in an earlier log backup
  • When the user needs to replace the database, that may include operations such as overwriting or moving database to different location
  • When User does not need to restore the database to a point of time after the latest backup of the database

Scenarios that Requires Tail-Log Backup During Restore

Here are some of the common scenarios where a tail-log backup is needed:

  1. When the database is Online
    • If the user wishes to perform restore operation of the online database, the first step is to back up the tail of the log. It is recommended to use ‘WITH RECOVERY’ option of the BACKUP T-SQL statement in order to avoid risk of having errors for the online database.
    • NORECOVERY can be used to back up the tail of the log and to keep the database in RESTORING state. It is useful when saving the tail log of the log before RESTORE operation or failing over to a secondary database.
    • User can use both NO_TRUNCATE and NORECOVERY options together to create a log backup, which will skip the log truncation and keep the database into RESTORING state in an atomic state
  2. When the database is Offline
  3. If the database is in offline state and fails to start, user needs to restore the database by creating backup of the tail of log. It is optional whether to use WITH NORECOVERY or not, as no transactions can occur during this time.

  4. When the database is damaged
  5. In case of database that is damaged, user can take tail-log backup with the help of WITHCONTINUE_AFTER_ERROR option of the BACKUP statement. Another option is to use CHECKSUM

Note: Backing up the tail-log on a damaged database will only succeed if the log files are in healthy state, the database is in the state that supports tail-log backups and no bulk-logged changes is present in the database. If the tail-log backup cannot be created, any transactions committed after the recent log backup will be lost. In such scenario you can take the help of third party SQL database repair to recover lost SQL database.

Tail-Log Backups with missing Backup Metadata

As discussed in the above section, the tail-log backups have the capability to capture the tail of the transaction log in case of the offline database, missing data or damaged files. It might lead to incomplete metadata from the restore information commands and msdb. Even though the metadata may be incomplete, the log that has been captured is complete and usable.

  • If the tail-log backup has incomplete metadata, the values of the columns of has_incomplete_metadata and HasIncompleteMetadata are set to 1.
  • If metadata in tail-log backup is incomplete, the backupfilegroup table will be missing most of the information related to filegroups during the tail-log backup. The table backupfilegroup will contain several columns that are having null values.

Conclusion

It can be concluded that there is a high necessity of backup up tail log when restoring the database in SQL Server. If the user does not backup the tail of the log, any transactions may be lost that has occurred since the last backup of the database. The article has discussed about tail log backup and the scenarios where backup of the tail log is needed for restoring the database.

Building a simple application using ASP.NET Core 1.0

What is .NET Core?

  • .NET Core is a general-purpose development platform
  • Maintained by Microsoft and the .NET community on GitHub
  • Its work in cross-platform, supporting Windows, macOS and Linux
  • Can be used in device, cloud, and embedded/IoT scenarios.
  • First release on 27 June, 2016

Application overview
HRM Core an application which I will develop here. User can view, add, edit and delete Employee information with his department and designation. This application will be developed by asp.net core.
Let’s come to the implementation of the project.

Tools and Technology used
I used following tools and technology to develop the project –

  1. Visual Studio 2015 Update 3
  2. Visual C#
  3. ASP.NET MVC
  4. Entity Framework core 1.0
  5. Razor view engine
  6. JQuery

Step 1: Create a ASP.net MVC Project
File -> New project and select the project template C# -> .NET Core -> Console application (.NET Core).

0107_01

Select Web Application as a Template, change authentication to individual user account and click OK
0107_02

Step 2: Change or Add Connection String
Change or Add connection string in appsettings.json as follows


{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=HRMCoreDB;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}

Step 3: Create model classes

Create three model classes Dept, Designation and Employee as follows.

Dept Class

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;

namespace HRMCore.Models
{
    public class Dept
    {
        public Dept()
        {
            ActionDate = DateTime.Now;
        }

        //[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int DeptId { get; set; }

        [Display(Name = "Dept")]
        public string Name { get; set; }

        public string Location { get; set; }

        public virtual List Employees { get; set; }
        public DateTime ActionDate { get; set; }
    }
}

Designation Class


using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;

namespace HRMCore.Models
{
    public class Designation
    {
        public Designation()
        {
            ActionDate = DateTime.Now;
        }
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        [Display(Name = "Designation")]
        public string Name { get; set; }
        public virtual List Employees { get; set; }
        public DateTime ActionDate { get; set; }
    }
}

Employee Class

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;

namespace HRMCore.Models
{
    public class Employee
    {
        public Employee()
        {
            ActionDate = DateTime.Now;
        }

        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        [Display(Name = "Employee Code")]
        public string EmpCode { get; set; }

        [Display(Name = "Full Name")]
        public string FullName { get; set; }

        [Display(Name = "Nick Name")]
        public string NickName { get; set; }

        [Display(Name = "Designation")]
        public int DesignationId { get; set; }

        [ForeignKey("DesignationId")]
        public virtual Designation Designation { get; set; }

        [Display(Name = "Department")]
        public int DeptId { get; set; }

        [ForeignKey("DeptId")]
        public virtual Dept Dept { get; set; }

        public string Phone { get; set; }
        public string Email { get; set; }
        public string Address { get; set; }
        public DateTime ActionDate { get; set; }
    }
}

Step 4: Modify Context class
Modify ApplicationDbContext in Data folder. Add DbSet for Dept, Designation and Employee model

using Microsoft.AspNet.Identity.EntityFramework;
using System.Data.Entity;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using HRMCore.Models;

namespace HRMCore.Data
{
    public class ApplicationDbContext : IdentityDbContext
    {
        public ApplicationDbContext(DbContextOptions options)
            : base(options)
        {
        }

        public DbSet Depts { get; set; }
        public DbSet Designations { get; set; }
        public DbSet Employees { get; set; }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
            // Customize the ASP.NET Identity model and override the defaults if needed.
            // For example, you can rename the ASP.NET Identity table names and more.
            // Add your customizations after calling base.OnModelCreating(builder);
        }
    }
}


Step 5: Create Controller and Views

Create Depts Controller and Views
Click Right button on Controller Folder->Add Controller. Now choose scaffolding template as MVC Controllers with views using Entity Framework and then Click Add.

0107_02_b

Now select Model class as Dept and Data Context Class as ApplicationDbContext as follows. Then click OK.

0107_03

Create Employees Controller and Views
Click Right button on Controller Folder->Add Controller. Now choose scaffolding template as MVC Controllers with views using Entity Framework and then Click Add as before.

Then select Model class as Employee and Data Context Class as ApplicationDbContext as follows. Then click OK.

0107_04


Step 6: Modify the controller

Modify EmployeeController as follows.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using HRMCore.Data;
using HRMCore.Models;

namespace HRMCore.Controllers
{
    public class EmployeesController : Controller
    {
        private readonly ApplicationDbContext _context;

        public EmployeesController(ApplicationDbContext context)
        {
            _context = context;    
        }

        // GET: Employees
        public async Task Index()
        {
            var applicationDbContext = _context.Employees.Include(e => e.Dept).Include(e => e.Designation);
            return View(await applicationDbContext.ToListAsync());
        }

        // GET: Employees/Details/5
        public async Task Details(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var employee = await _context.Employees.SingleOrDefaultAsync(m => m.Id == id);
            if (employee == null)
            {
                return NotFound();
            }

            return View(employee);
        }

        // GET: Employees/Create
        public IActionResult Create()
        {
            ViewData["DeptId"] = new SelectList(_context.Depts, "DeptId", "Name");
            ViewData["DesignationId"] = new SelectList(_context.Designations, "Id", "Name");
            return View();
        }

        // POST: Employees/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task Create([Bind("Id,ActionDate,Address,DeptId,DesignationId,Email,EmpCode,FullName,NickName,Phone")] Employee employee)
        {
            if (ModelState.IsValid)
            {
                _context.Add(employee);
                await _context.SaveChangesAsync();
                return RedirectToAction("Index");
            }
            ViewData["DeptId"] = new SelectList(_context.Depts, "DeptId", "Name", employee.DeptId);
            ViewData["DesignationId"] = new SelectList(_context.Designations, "Id", "Name", employee.DesignationId);
            return View(employee);
        }

        // GET: Employees/Edit/5
        public async Task Edit(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var employee = await _context.Employees.SingleOrDefaultAsync(m => m.Id == id);
            if (employee == null)
            {
                return NotFound();
            }
            ViewData["DeptId"] = new SelectList(_context.Depts, "DeptId", "Name", employee.DeptId);
            ViewData["DesignationId"] = new SelectList(_context.Designations, "Id", "Name", employee.DesignationId);
            return View(employee);
        }

        // POST: Employees/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task Edit(int id, [Bind("Id,ActionDate,Address,DeptId,DesignationId,Email,EmpCode,FullName,NickName,Phone")] Employee employee)
        {
            if (id != employee.Id)
            {
                return NotFound();
            }

            if (ModelState.IsValid)
            {
                try
                {
                    _context.Update(employee);
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!EmployeeExists(employee.Id))
                    {
                        return NotFound();
                    }
                    else
                    {
                        throw;
                    }
                }
                return RedirectToAction("Index");
            }
            ViewData["DeptId"] = new SelectList(_context.Depts, "DeptId", "Name", employee.DeptId);
            ViewData["DesignationId"] = new SelectList(_context.Designations, "Id", "Name", employee.DesignationId);
            return View(employee);
        }

        // GET: Employees/Delete/5
        public async Task Delete(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var employee = await _context.Employees.SingleOrDefaultAsync(m => m.Id == id);
            if (employee == null)
            {
                return NotFound();
            }

            return View(employee);
        }

        // POST: Employees/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public async Task DeleteConfirmed(int id)
        {
            var employee = await _context.Employees.SingleOrDefaultAsync(m => m.Id == id);
            _context.Employees.Remove(employee);
            await _context.SaveChangesAsync();
            return RedirectToAction("Index");
        }

        private bool EmployeeExists(int id)
        {
            return _context.Employees.Any(e => e.Id == id);
        }
    }
}

Step 7: Modify the view
Modify the views if required.

Step 8: Add Seed method
Add a seed class name DataSeeder in model class as follows.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
//using Microsoft.AspNet.Builder;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using HRMCore.Data;
//using System.Data

namespace HRMCore.Models
{

    public static class DataSeeder
    {
        // TODO: Move this code when seed data is implemented in EF 7

        /// 
        /// This is a workaround for missing seed data functionality in EF 7.0-rc1
        /// More info: https://github.com/aspnet/EntityFramework/issues/629
        /// 
        /// 
        /// An instance that provides the mechanisms to get instance of the database context.
        /// 
        public static void SeedData(this IApplicationBuilder app)
        {
            var db = app.ApplicationServices.GetService();

            // TODO: Add seed logic here


            var objSE = new Designation { Name = "Software Engineer" };
            var objSSE = new Designation { Name = "Senior Engineer" };
            var objSA = new Designation { Name = "Software Archiect" };
            var objBA = new Designation { Name = "Business Analyst" };
            var objOfficer = new Designation { Name = "Officer" };
            var objSrOfficer = new Designation { Name = "Sr. Officer" };
            var objAssMgr = new Designation { Name = "Asst. Manager" };

            var objSSD = new Dept { Name = "Software Development" };
            var objIMP = new Dept { Name = "Software Implementation" };
            var objFin = new Dept { Name = "Finance & Administration" };
            var objMkt = new Dept { Name = "Sells & Marketing" };



            var lstEmployees = new List()
            {
                new Employee(){EmpCode = "L0001", FullName = "Tariqul Islam", NickName = "Shakil",
                    Designation = objSE, Dept = objSSD, Phone = "01715333333", Email ="demo@gmail.com"  },

                new Employee(){EmpCode = "L0002", FullName = "Enamul Haque", NickName = "Rony",
                    Designation = objSSE, Dept = objIMP, Phone = "01715333332", Email ="deom@gmail.com"  },

                new Employee(){EmpCode = "L0003", FullName = "Mallik Arif Ahsan", NickName = "Arif",
                    Designation = objAssMgr, Dept = objFin, Phone = "01715333332", Email ="deom@gmail.com"  },

                new Employee(){EmpCode = "L0004", FullName = "Jafrin Islam", NickName = "Sinthi",
                    Designation = objSSE, Dept = objSSD, Phone = "01715333334", Email ="demo@gmail.com"  },

                new Employee(){EmpCode = "L0005", FullName = "Md. Mahedee Hasan", NickName = "Mahedee",
                    Designation = objSSE, Dept = objSSD, Phone = "01715333334", Email ="demo@gmail.com"  },

            };


            List lstDept = new List {
                     new Dept { Name = "Supply Chain" },
                     new Dept { Name = "Software Innovation" }
                };

            List lstDesignation = new List
            {
                    new Designation { Name = "Executive" },
                    new Designation { Name = "Senior Executive" },
                    new Designation { Name = "Manager" },
                    new Designation { Name = "Deputy Manager" },
                    new Designation { Name = "Project Manager" }
            };

            if (db.Depts.ToList().Count <= 0)
                db.AddRange(lstDept);

            if (db.Designations.ToList().Count <= 0)
                db.AddRange(lstDesignation);

            if (db.Employees.ToList().Count <= 0)
                db.Employees.AddRange(lstEmployees);

            db.SaveChanges();
        }
    }
}
[/csharp]

Step 9: Add SeedData Method 
Add SeedData method in Startup class as follows.

[csharp]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using HRMCore.Data;
using HRMCore.Models;
using HRMCore.Services;

namespace HRMCore
{
    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

            if (env.IsDevelopment())
            {
                // For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709
                builder.AddUserSecrets();
            }

            builder.AddEnvironmentVariables();
            Configuration = builder.Build();
        }

        public IConfigurationRoot Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddDbContext(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            services.AddIdentity()
                .AddEntityFrameworkStores()
                .AddDefaultTokenProviders();

            services.AddMvc();

            // Add application services.
            services.AddTransient();
            services.AddTransient();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
                app.UseBrowserLink();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseIdentity();
            app.SeedData();

            // Add external authentication middleware below. To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

Step 9: Add Migration
Go to Tools -> NuGet Package Manager -> Package Manager Console
Run the following command in the package manager console.
PM> Add-Migration addmodel
Then run the following command in the package manager console.
PM> Update-Database -Verbose

Step 10: Add Links in Layout Page
Add Dep and Employee link as follows.

  • Home
  • About
  • Contact
  • Dept
  • Employee
  • Now run the application. Click Dept or Employee link in the nav bar. You can View, add, modify and delete employee information as well as department information. Thanks for your patience.

    0107_05

    Microsoft Student Partner (MSP) Capacity Build up Training (Session 05)


    Microsoft Student Partner (MSP) Capacity Build up Training (Session 05)
    Course Title: Object Oriented Programming with C#
    Venue: East West University, Dhaka, Bangladesh
    Date: 30 July, 2016
    Speaker / Trainer: Md. Mahedee Hasan,
    Microsoft MVP, Visual Studio and Development Technologies
    Software Architect, Leadsoft Bangladesh Limited
    Trainer, Leads Technology Limited

    Microsoft Student Partner (MSP) Capacity Build up Training (Session 04)

    Microsoft Student Partner (MSP) Capacity Build up Training (Session 04)
    Course Title: Object Oriented Programming with C#
    Venue: East West University, Dhaka, Bangladesh
    Date: 23 July, 2016
    Speaker / Trainer: Md. Mahedee Hasan,
    Microsoft MVP, Visual Studio and Development Technologies
    Software Architect, Leadsoft Bangladesh Limited
    Trainer, Leads Technology Limited