Tuesday, August 6, 2019

Using EntityFramework in a .Net Core Project

Introduction

While I work with EntityFramework every day, I do not add an EntityFramework (EF) to an existing project every day. Time and again, I have to create a new project or add EntityFramework to the existing project and I have to re-do many steps that are hard to remember. I decided to document the steps in the form of this article.

In this article, I am going to show how to get started with EntityFramework. I will start a project without support to EntityFramework and add the EF support to the project and use a migration to update the database. The code related to this article is available at GitHub. The sample project uses in Visual Studio 2017 IDE using C#, MS SQL Server with SQL Server Management Studio (SSMS) and EntityFrameworkCore with .Net Core SDK 2.2.


Create Solution and Project

I started with the creation of an empty solution and added a WebAPI project targetting .NetCore 2.2.





As I am using MS SQL Server, I added a reference to

Microsoft.EntityFrameworkCore.SqlServer and Microsoft.EntityFrameworkCore.Design using Nuget Package Manager.


I updated the appsetting.json file for the connectionstring by adding the following property:

 "ConnectionStrings": { 
     "DefaultConnection":
        "Server=(localdb)\\mssqllocaldb;Database=ApplicationDb;Trusted_Connection=True;" }



Configure Database and Models

I have created models for Customer, Contact, and CustomerContact. The code example has these models in DBContext folder. In addition, there are classes for IAuidtable and Audit and some enums which can be ignored for now. Customer and Contact entity have many to many relationships and thus I added CustomerContact entity to store the relationship.


public class Customer : IAuditable
    {
        public Guid Id { get; set; }
        public String AccountNumber { get; set; }
        public String Name { get; set; }
        public DateTime? CreatedDate { get; set; }
        public DateTime? ModifiedDate { get; set; }
        public String LastModifiedBy { get; set; }
        public bool IsInactive { get; set; }
        public ICollection<CustomerContact> CustomerContacts { get; set; }
    }

    public class Contact : IAuditable
    {
        public Guid Id { get; set; }
        public String Name { get; set; }
        public String Title { get; set; }
        public String Phone { get; set; }
        public String Email { get; set; }
        public ContactTypeEnum ContactType { get; set; }
        public String Note { get; set; }
        public DateTime? CreatedDate { get; set; }
        public DateTime? ModifiedDate { get; set; }
        public String LastModifiedBy { get; set; }
        public bool IsInactive { get; set; }
        public ICollection<CustomerContact> CustomerContacts { get; set; }

    }

    public class CustomerContact:IAuditable
    {
        public Guid Id { get; set; }
        public DateTime? CreatedDate { get; set; }
        public DateTime? ModifiedDate { get; set; }
        public string LastModifiedBy { get; set; }
        public bool IsInactive { get; set; }
        public Guid CustomerId { get; set; }
        public Customer Customer { get; set; }
        public Guid ContactId { get; set; }
        public Contact Contact { get; set; }
    }

    public class Audit
    {
        public Guid Id { get; set; }
        public Guid? EntityId { get; set; }
        public string User { get; set; }
        public String Entity { get; set; }
        public DateTime DateTime { get; set; }
        public string ColumnName { get; set; }
        public String OldValue { get; set; }
        public String NewValue { get; set; }
        public EntityStateChangeTypeEnum ChangeType { get; set; }

    }
    /// <summary>
    /// This interface determines what will be automatically tracked.
    /// </summary>
    interface IAuditable
    {
        Guid Id { get; set; }
        DateTime? CreatedDate { get; set; }
        DateTime? ModifiedDate { get; set; }
        String LastModifiedBy { get; set; }
        bool IsInactive { get; set; }
    }

    public enum EntityStateChangeTypeEnum
    {
        Added,
        Deleted,
        Modified,
    }

    public enum ContactTypeEnum
    {
        Primary,
        Secondary,
        Emergency,
    }


With these changes, I am ready to set up code-first logic for creating database tables. I am going to create a class ApplicationDbContext that derives from DbContext of EntityFrameworkCore. In this class, I create DbSet objects of the type of Customer, Contact, CustomerContact, and Audit. This is what makes EF aware of the tables I need to create.


using Microsoft.EntityFrameworkCore;

namespace AutotrackEntityChange.DBContext
{
    public class ApplicationDbContext: DbContext
    {
        //Define DbSets
        public DbSet<Customer> Customers { get; set; }
        public DbSet<Contact> Contacts { get; set; }

        public DbSet<CustomerContact> CustomerContacts { get; set; }
        public DbSet<Audit> Audits { get; set; }

        public ApplicationDbContext(
          DbContextOptions<ApplicationDbContext> options)
            : base(options) {}
    }
}


Now I need to add service in the Startup.cs class to use ApplicationDbContext within the application. The service can be added inside the ConfigureService method using the following code:


 services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration
            .GetConnectionString("DefaultConnection")));


Note that the service addition above uses the same DefaultConnection that was defined in the appsetting.json earlier.


Migration and Database Update

I can run the 'Add-Migration 'InitialCreate'' command in the Package Manager Console within the Visual Studio to generate necessary migration scripts.


This will create necessary Migration files in the solution under Migration folder.


Now I can run 'Update-Database' command in the Package Manager Console to apply the migration. 

Note that at this time, the migration code will generate the database and the tables inside 'ApplicationDb' database. I can now open SSMS and navigate to the database and see the tables.



Summary

In this article, I showed steps to add EntityFramework support to a .Net Core project using Code-First approach and migrations. I provided an example using a WebAPI project with SQL Server, but the steps mentioned here can be used for other database and other project types. The migration I used was really for creating the database and entities, but a similar approach can be used to update the entities. am hoping this will help someone and I welcome comments and suggestions.

References

Sunday, August 4, 2019

Remove commit history in git

Have you ever had a need to clean up all the history in the git repository? I have. I dealt with this old fashioned way until I started interacting with the command line.  The old fashioned way is to create a new repository and update files and replace the old with a new one. In this article, I am going to show how to clean the commit history in git using tools and technique using command lines.  

Method 1: Re-init the repository

In this method, I remove and recreate the git and modify the origin and then I can push the code to remote. The following set of commands can be used:
$ rm -rf .git
$ git init
$ git add .
$ git commit -m "Starting Commit"
$ git remote add origin [......]
$ git push -u --force origin master

Method 2: Alter the branch


In this method, I initially create a temp branch, add all the files to that branch, delete the old branch and then rename the current branch to master and then push the changes to remote. Following sets of commands can do the job. 
$ git checkout --orphan temp
$ git add -A
$ git commit -am "Starting Commit"
$ git branch -D master
$ git branch -m master
$ git push -f origin master

Method 3:  Squashing the commits 

In this method, I combine all the commits into one which is known as squashing. For example, if I have 25 commits since the beginning, then I can combine all commits into one by using the following steps for squashing commits into one and amending the commit message:
$ git rebase -i Head~25
$ #edit the commits mannually
$ git commit –amend