Disable deletion for records with dependencies

c# dto entity-framework-6 model-view-controller

Question

I want to delete records from my database only which don't have any dependencies.

eg:- Company Table has Company Pk primary key and it is the foreign key for department table and location table. So the system should not allow user to delete a company from company if it has dependencies with department and location.

The records without any dependencies can be deleted. How can I do this?

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
using System.Net;
using System.Web;
using System.Web.Mvc;
using Payroll.Core.Domain;
using Payroll.Infrastructure.Data;
using AutoMapper;
using Payroll.Web.Dto;
using Payroll.Core.Interfaces;
using Payroll.Infrastructure.Validators;

namespace Payroll.Web.Controllers
{
    [RoutePrefix("Company")]
    public class CompanyController : Controller
    {
        private readonly IMapper _mapper = null;
        private readonly IUnitOfWork _work = null;

        public CompanyController(IUnitOfWork work, IMapper mapper)
        {
            _work = work;
            _mapper = mapper;
        }

        // GET: Company
        public async Task<ActionResult> Index()
        {
            var companies = await _work.Companies.GetAllAsync();
            var companyDtos = _mapper.Map<List<CompanyDto>>(companies);

            return View(companyDtos);
        }

        // GET: Company/5
        [Route("{companyPk:int}")]
        public async Task<ActionResult> Details(int? companyPk)
        {
            //Validate parameters
            if (companyPk == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Company identifier is missing.");
            }

            //Get model from db
            Company company = await _work.Companies.GetAsync(companyPk);
            if (company == null)
            {
                return HttpNotFound();
            }

            //Convert model to dto
            CompanyDto companyDto = _mapper.Map<CompanyDto>(company);

            return View(companyDto);
        }

        // GET: Company/New
        [Route("New")]
        public ActionResult New()
        {
            var dto = new CompanyDto();
            return View(dto);
        }

        // POST: Company/New
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see https://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        [Route("New")]
        public async Task<ActionResult> New(CompanyDto companyDto)
        {
            //Validate Dto state
            if (ModelState.IsValid)
            {
                //Convert dto to model
                Company company = _mapper.Map<Company>(companyDto);

                //Assign model properties
                company.CompanyPk = new Random().Next(1, 10);

                Utilities.Instance.SetEntityProperties(company);

                //Validate model
                var validator = new CompanyValidator();
                var validation = await validator.ValidateAsync(company);

                if (validation.IsValid)
                {
                    //Save model to db
                    _work.Companies.Add(company);
                    await _work.CompleteAsync();

                    return RedirectToAction("Index");
                }
                else
                {
                    foreach (var error in validation.Errors)
                    {
                        ModelState.AddModelError(error.PropertyName, error.ErrorMessage);
                    }
                }
            }

            return View(companyDto);
        }

        // GET: Company/5/Edit
        [Route("{companyPk:int}/Edit")]
        public async Task<ActionResult> Edit(int? companyPk)
        {
            //Validate parameters
            if (companyPk == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Company identifier is missing.");
            }

            //Get the model from db
            Company company = await _work.Companies.GetAsync(companyPk);
            if (company == null)
            {
                return HttpNotFound();
            }

            //Convert model to dto
            CompanyDto companyDto = _mapper.Map<CompanyDto>(company);

            return View(companyDto);
        }

        // POST: Company/5/Edit
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see https://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        [Route("{companyPk:int}/Edit")]
        public async Task<ActionResult> Edit(int? companyPk, CompanyDto companyDto)
        {
            //Validate parameters
            if (companyPk == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Company identifier is missing.");
            }

            //Validate Dto state
            if (ModelState.IsValid)
            {
                //Get the model from db
                //Because the record now being edited can be changed by another process
                var company = await _work.Companies.GetAsync(companyPk);

                if (company == null)
                {
                    return HttpNotFound();
                }

                //Map the previous state of the model to log
                var logCompany = _mapper.Map<LogCompany>(company);

                //Convert dto to model
                //This is a specific mapping which modifies the original model from only bound properties of Dto
                _mapper.Map(companyDto, company);

                //Validate model
                var validator = new CompanyValidator();
                var validation = await validator.ValidateAsync(company);

                if (validation.IsValid)
                {
                    //Assign log model properties
                    logCompany.RecordId = 0;
                    Utilities.Instance.SetLogEntityProperties(logCompany, "E");

                    //Save model to db
                    _work.LogCompanies.Add(logCompany);
                    _work.Companies.Update(company);

                    await _work.CompleteAsync();

                    return RedirectToAction("Index");
                }
                else
                {
                    foreach (var error in validation.Errors)
                    {
                        ModelState.AddModelError(error.PropertyName, error.ErrorMessage);
                    }
                }
            }

            return View(companyDto);
        }

        // GET: Company/5/Delete
        [Route("{companyPk:int}/Delete")]
        public async Task<ActionResult> Delete(int? companyPk)
        {
            //Validate parameters
            if (companyPk == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Company identifier is missing.");
            }

            //Get the model from db
            Company company = await _work.Companies.GetAsync(companyPk);
            if (company == null)
            {
                return HttpNotFound();
            }

            //Convert model to dto
            CompanyDto companyDto = _mapper.Map<CompanyDto>(company);

            return View(companyDto);
        }

        // POST: Company/5/Delete
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        [Route("{companyPk:int}/Delete")]
        public async Task<ActionResult> DeleteConfirmed(int companyPk)
        {
            //Get the model from db
            Company company = await _work.Companies.GetAsync(companyPk);

            //Prepare log model
            var logCompany = _mapper.Map<LogCompany>(company);
            logCompany.RecordId = 0;
            Utilities.Instance.SetLogEntityProperties(logCompany, "D");

            //Save model to db
            _work.LogCompanies.Add(logCompany);
            _work.Companies.Remove(company);
            await _work.CompleteAsync();

            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _work.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}
1
0
10/8/2019 10:39:53 AM

Accepted Answer

If you have navigation properties in your entity then you can just check if their keys are not null:

company.LocationId !=null && company.DepartmentId!=null

If you don't have Id properties (EF can create them conventionally) then read this documentation and load entities. Assuming that will not add much overhead.

var company = _work.Companies.Where(b => b.CompanyPk == companyPk)
                       .Include(b => b.Location)
                       .Include(b => b.Department)
                       .FirstOrDefault();
company.Location !=null && company.Department!=null

Hoping this is not a production code:

company.CompanyPk = new Random().Next(1, 10);

And never-ever destroy the injected dependency. This is a red flag as you don't control its lifetime, what if there is a pool? The rule is - you didn't create it, you are not responsible to destroy it. If you want explicitly control lifetime - then inject a Factory, create a service, use and destroy.

_work.Dispose();
1
10/9/2019 3:33:28 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow