Monday 15 June 2020

CRUD operations using Angular9 & CORE WEBAPI(3.1) ,AutoMapper,Repository, Dependency Injection, EF core code first approach & implementing store procedure in EF core.



Dot net core webapi code :

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

namespace Automapper007.Models
{
    public class EMP
    {
        [Key]
        public int EID { get; set; }
        [MaxLength(50)]
        public string NAME { get; set; }
        [MaxLength(50)]
        public string GENDER { get; set; }
    }
}


--
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Automapper007.Models
{
    public class AppDbContext:DbContext
    {
        public AppDbContext(DbContextOptions<AppDbContext> options):base(options)
        {

        }
        public DbSet<EMP> Emps { get; set; }

    }
}

--
Add-migraion 4th;

Write below code :

using Microsoft.EntityFrameworkCore.Migrations;

namespace Automapper007.Migrations
{
    public partial class _4th : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            var sp = @"CREATE procedure dbo.SP_DML2
                        (
                        @EID int=null,
                        @NAME nvarchar(50)=null,
                        @GENDER nvarchar(50)=null,
                        @MARK int,
                        @message nvarchar(Max)='' output
                        )
                        as
                        begin
                         begin Try
                           if @MARK=1
                           begin
                           insert into Emps(NAME,GENDER) values(@NAME,@GENDER)
                           set @message='Data Saved Successfully.'
                           end
                           else if @MARK=2
                           begin
                           update Emps set NAME=@NAME,GENDER=@GENDER where EID=@EID
                           set @message='Data Updated Successfully.'
                           end
                           else if @MARK=3
                           begin
                           delete from  Emps  where EID=@EID
                           set @message='Data Deleted Successfully.'
                           end
                         end Try
                         begin catch
                         SELECT   @message='Error on Procedure :'+ERROR_PROCEDURE()+'Error on line :'+ ERROR_LINE()+'Error message :'+ERROR_MESSAGE() 
                         end catch
                            end";
            migrationBuilder.Sql(sp);
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {

        }
    }
}

update-database
--
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Automapper007.Models;

namespace Automapper007.Services
{
  public interface IRepository
    {
        public Task<IEnumerable<EMP>> Gets();
        public Task<EMP> Get(int EID);
        public Task<string> Save(EMP emp);
        public Task<string> Update(EMP emp);
        public Task<string> Delete(int EID);


    }
}
--
using Automapper007.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Automapper007.Models;
using Automapper007.Services;
using Microsoft.EntityFrameworkCore;


namespace Automapper007.Services
{
    public class Repository : IRepository
    {
        private readonly AppDbContext context;
        string Message = "";
        public Repository(AppDbContext context)
        {
            this.context = context;
        }
        public async Task<string> Delete(int EID)
        {
             await context.Database.ExecuteSqlRawAsync($"EXEC dbo.SP_DML2 @EID={EID},@MARK={3},@message={Message} output");
            return Message;
        }

        public async Task<EMP> Get(int EID)
        {
            return await context.Emps.FromSqlRaw($"select * from Emps where EID={EID}").FirstAsync();
        }

        public async Task<IEnumerable<EMP>> Gets()
        {
            return await context.Emps.FromSqlRaw("select * from Emps").ToListAsync();
        }

        public async Task<string> Save(EMP emp)
        {
           
                await context.Database.ExecuteSqlRawAsync($"EXEC dbo.SP_DML2 @EID={emp.EID},@NAME={emp.NAME},@GENDER={emp.GENDER},@MARK={1},@message={Message} output");
                return Message;
           
            
        }

        public async Task<string> Update(EMP emp)
        {
            await context.Database.ExecuteSqlRawAsync($"EXEC dbo.SP_DML2 @EID={emp.EID},@NAME={emp.NAME},@GENDER={emp.GENDER},@MARK={2},@message={Message} output");
            return Message;
        }
    }
}
--
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Automapper007.Models;
using Automapper007.Services;

namespace Automapper007.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class EmpController : ControllerBase
    {
        private readonly IRepository repository;
      
        public EmpController(IRepository repository)
        {
            this.repository = repository;
        }
        [HttpGet]
        public async Task<ActionResult<IEnumerable<EMP>>> Gets()
        {
            try
            {
                return Ok(await repository.Gets());
            }
            catch (Exception ex)
            {

                return StatusCode(StatusCodes.Status500InternalServerError, ex);
            }
        }
        [HttpGet("{EID:int}")]
        public async Task<ActionResult<EMP>> Get(int EID)
        {
            try
            {
                return Ok(await repository.Get(EID));
            }
            catch (Exception ex)
            {

                return StatusCode(StatusCodes.Status500InternalServerError, ex);
            }
        }
        [HttpPost]
        public async Task<ActionResult> Save(EMP emp)
        {
            try
            {
                return CreatedAtAction(nameof(Get), new { EID = emp.EID }, await repository.Save(emp));
            }
            catch (Exception ex)
            {

                return StatusCode(StatusCodes.Status500InternalServerError, ex);
            }
        }
        [HttpPut]
        public async Task<ActionResult> Update(EMP emp)
        {
            try
            {
                return Ok(await repository.Update(emp));
            }
            catch (Exception ex)
            {

                return StatusCode(StatusCodes.Status500InternalServerError, ex);
            }
        }
        [HttpDelete("{EID:int}")]
        public async Task<ActionResult<EMP>> Delete(int EID)
        {
            try
            {
                return Ok(await repository.Delete(EID));
            }
            catch (Exception ex)
            {

                return StatusCode(StatusCodes.Status500InternalServerError, ex);
            }
        }
    }
}
--
Angular9 Code :

Model :

export class IEMP {
    EID: number;
    NAME: string;
    GENDER: string;
}

Service :
import { Injectable } from '@angular/core';
import { IEMP } from './emp.model';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/observable/throw';

@Injectable()
export class EmpServices {
    baseUrl = 'https://localhost:44393/api/Emp';
    constructor(private http: HttpClient) { }
    Gets() {
        return this.http.get(`${this.baseUrl}`)
            .catch((err) => {
                return Observable.throw(err);
            });
    }
    Get(eid: number) {
        return this.http.get(`${this.baseUrl}/${eid}`)
            .catch((err) => {
                return Observable.throw(err);
            });
    }
    Save(emp: IEMP) {
        return this.http.post(`${this.baseUrl}`
        , JSON.stringify(emp)
        , {headers: new HttpHeaders({'Content-Type' : 'application/json'})} )
        .catch( (err) => {
            return Observable.throw(err);
        });
    }
    Update(emp: IEMP) {
        return this.http.put(`${this.baseUrl}`
        , JSON.stringify(emp)
        , {headers: new HttpHeaders({'Content-Type' : 'application/json'})}
        )
            .catch((err) => {
                return Observable.throw(err);
            });
    }
    Delete(eid: number) {
        return this.http.delete(`${this.baseUrl}/${eid}`
        , {headers: new HttpHeaders({'Content-Type' : 'application/json'})}
        )
            .catch((err) => {
                return Observable.throw(err);
            });
    }
}

Pipe :

import { Pipe, PipeTransform } from '@angular/core';


@Pipe({
    name: 'TestPipe'
})
export class TcustomPipe implements PipeTransform {
    transform(value: string, gender: string): string {
        if (gender.toLowerCase() === 'male') {
               return 'Mr. ' + value;
        } else {
                return 'Miss. ' + value;
        }
    }
}

Create View :

<form class="form-horizontal" [formGroup]="frmEmp">
    <div class="form-group">
        <label class="control-label col-lg-4"></label>
        <div class="col-lg-4 alert-danger" *ngIf='errorMessage !== undefined'>
          {{errorMessage}}
        </div>
</div>
  <div class="form-group" [ngClass]="{'has-error':frmEmp.get('EID').errors && (frmEmp.get('EID').touched || frmEmp.get('EID').dirty)}">
      <label class="control-label col-lg-4">EID</label>
      <div class="col-lg-4">
          <input type="text" class="form-control" formControlName="EID" />
      </div>
      <span class="help-block has-error" *ngIf="frmEmp.get('EID').errors && (frmEmp.get('EID').touched || frmEmp.get('EID').dirty)">Eid should not be blank.</span>
  </div>
  <div class="form-group" [ngClass]="{'has-error':frmEmp.get('NAME').errors && (frmEmp.get('NAME').touched || frmEmp.get('NAME').dirty)}">
      <label class="control-label col-lg-4">NAME</label>
      <div class="col-lg-4">
          <input type="text" class="form-control" formControlName="NAME" />
      </div>
      <span class="help-block has-error" *ngIf="frmEmp.get('NAME').errors && (frmEmp.get('NAME').touched || frmEmp.get('NAME').dirty)">Name should not be blank.</span>
  </div>
  <div class="form-group" [ngClass]="{'has-error':frmEmp.get('GENDER').errors && (frmEmp.get('GENDER').touched || frmEmp.get('GENDER').dirty)}">
      <label class="control-label col-lg-4">GENDER</label>
      <div class="col-lg-4">
          <input type="radio" value="Male" formControlName="GENDER" />Male
          <input type="radio" value="Female" formControlName="GENDER" />Female
      </div>
      <span class="help-block has-error" *ngIf="frmEmp.get('GENDER').errors && (frmEmp.get('GENDER').touched || frmEmp.get('GENDER').dirty)">Please select a gender.</span>
  </div>
  <div class="form-group" >
      <label class="control-label col-lg-4"></label>
      <div class="col-lg-4">
          <input type="button" value="Submit" (click)="save(frmEmp.invalid)" class="btn btn-primary" style="width:80px" />
          <input type="button" value="Reset" (click)="reset(frmEmp)" class="btn btn-primary" style="width:80px" />
          <a [routerLink]="['/list']">Back To List</a>
      </div>
  </div>
</form>

Create Component :

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Router, ActivatedRoute } from '@angular/router';
import { EmpServices } from '../emp/emp.service';
import { IEMP } from './test.model';
import { NgForm } from '@angular/forms';


@Component({
  selector: 'app-createtest',
  templateUrl: './createtest.component.html',
  styleUrls: ['./createtest.component.css']
})
export class CreatetestComponent implements OnInit {
  EMP: IEMP;
  frmEmp: FormGroup;
  errorMessage: string;
  eid: number;
  constructor(private ro: Router, private ar: ActivatedRoute, private es: EmpServices, private fb: FormBuilder) { }

  ngOnInit() {
    this.CLR();
    this.frmEmp = this.fb.group({
      EID: [null, Validators.required],
      NAME: [null, Validators.required],
      GENDER: [null, Validators.required]
    });
    this.eid = this.ar.snapshot.params['id'];
    if (this.eid !== undefined) {
      this.es.Get(this.eid).subscribe((data) => {
        this.frmEmp.setValue({
          EID: data.EID,
          NAME: data.NAME,
          GENDER: data.GENDER
        });
      }, (err) => {
        this.errorMessage = err.message;
      });
    }
  }
  CLR(): void {
    this.EMP = {
      EID: null,
      NAME: null,
      GENDER: null
    };
  }
  reset(nf: NgForm): void {
    nf.reset();
  }
  save(isValid: boolean): void {
    if (!isValid) {
      this.EMP.EID = Number(this.frmEmp.value.EID);
      this.EMP.NAME = this.frmEmp.value.NAME;
      this.EMP.GENDER = this.frmEmp.value.GENDER;
      if (this.eid !== undefined) {
        this.es.Update(this.EMP).subscribe((data) => {
          this.ro.navigate(['/list']);
        }, (err) => {
          this.errorMessage = err.message;
        });
      } else {
        this.es.Save(this.EMP).subscribe((data) => {
          this.ro.navigate(['/list']);
        }, (err) => {
          this.errorMessage = err.message;
        });
      }
    }
  }
}

List View :

<div class="row">
  <input type="button" value="Add New" [routerLink]="['/create']"  class="btn btn-primary" style="width:80px" />
</div><br>
<div class="row alert-danger" *ngIf='errorMessage !== undefined'>
          {{errorMessage}}
</div>
<div class="row">
  <table class="table table-bordered table-condensed table-hover table-responsive table-striped">
      <thead class="bg bg-primary">
          <tr>
              <th>Sl No.</th>
              <th>NAME</th>
              <th>GENDER</th>
              <th>ACTION</th>
          </tr>
      </thead>
      <tbody>
          <tr *ngFor="let c of list;let i=index">
              <td>{{i+1}}</td>
              <td>{{c.NAME|TestPipe:c.GENDER}}</td>
              <td>{{c.GENDER}}</td>
              <td>
                  <a [routerLink]="['/create',c.EID]">Edit</a> | <a (click)="del(c.EID)">Delete</a>
              </td>
          </tr>
      </tbody>
  </table>
</div>

List Component :

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { EmpServices } from '../emp/emp.service';
import { IEMP } from './test.model';

@Component({
  selector: 'app-listtest',
  templateUrl: './listtest.component.html',
  styleUrls: ['./listtest.component.css']
})
export class ListtestComponent implements OnInit {
  errorMessage: string;
  list: IEMP[];
  constructor(private es: EmpServices) { }

  ngOnInit() {
    this.fill();
  }
  fill(): void {
    this.es.Gets().subscribe((data) => {
      this.list = data;
    }, (err) => {
      this.errorMessage = err.message;
    });
  }
  del(eid: number): void {
    if (confirm('Do you want to delete it ?')) {
      this.es.Delete(eid).subscribe((data) => {
        this.fill();
      }, (err) => {
        this.errorMessage = err.message;
      });
    }
  }
}

App View :

<div style="padding:5px" class="container">
    <ul class="nav nav-tabs">
     <li routerLinkActive="Active">
       <a routerLink="list">Empioyee</a>
     </li>
     <li routerLinkActive="Active">
        <a routerLink="create">Department</a>
      </li>
    </ul>
  <br>
  <router-outlet></router-outlet>
  </div>
App Model :

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
import { RouterModule, Routes } from '@angular/router';
import {EmpServices} from './emp/emp.service';
import { HttpClientModule } from '@angular/common/http';
import { CreatetestComponent } from './test/createtest.component';
import { ListtestComponent } from './test/listtest.component';
import { TcustomPipe } from './test/test.pipe';

const appRoutes: Routes = [
  { path: 'list', component: ListtestComponent },
  { path: 'create/:id', component: CreatetestComponent  },
  { path: 'delete/:id', component: CreatetestComponent  },
  { path: 'create', component: CreatetestComponent  },
  { path: '', redirectTo: '/list', pathMatch: 'full' },
  { path: '**', component: ListtestComponent  }
];

@NgModule({
  declarations: [
    AppComponent,
    ListEmployeesComponent,
    CreateEmployeeComponent,
    CreateDepartmentComponent,
    CreateStapComponent,
    CreateFacultyComponent,
    CreateDoctorComponent,
    CreatePatientComponent,
    EmplistComponent,
    EmpcreateComponent,
    CreatetestComponent,
    ListtestComponent,
    TcustomPipe
  ],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule,
    HttpModule,
    HttpClientModule,
    BsDatepickerModule.forRoot(),
    RouterModule.forRoot(appRoutes),
    ToastrModule.forRoot(),
    
  ],
  providers: [EmployeeService, DepartmentServices, StapServices, FacultyServices, DoctorServie, PatienServices, EmpServices],
  bootstrap: [AppComponent]
})
export class AppModule { }