locked
Disconnected scenario during tests with Microsoft.EntityFrameworkCore.InMemory RRS feed

  • Question

  • User-906047806 posted

    Hi,

    I want to test the EditPost method of controllers. To simulate database access, I use Microsoft.EntityFrameworkCore.InMemory.

    But if I use Microsoft.EntityFrameworkCore.InMemory, I have to do something like this (for a given test):


    [Fact]
    public void Can_Edit_Customer_Email()
    {
    // Generate the needed data from Microsoft.EntityFrameworkCore.InMemory
    DataGenerator();

    // Arrange var customer = _context.Customers.Find(1); // Act customer.EmailContact = "john.doe@contoso.com"; HomeController target = new HomeController(_context); target.EditPost(1, customer); // Assert Assert.Equal("john.doe@contoso.com", _context.Customers.Find(1).EmailContact);
    }

    Otherwise, if I feed the target.EditPost method like this:

        // Act 
    HomeController target = new HomeController(_context);
    target.EditPost(1, new Customer {Id = 1, FirstName = "John", LastName = "Doe", Email = "john.doe@contoso.com"});

    I get this "expected" exception:

    System.InvalidOperationException : The instance of entity type 'Customer' cannot be tracked because another instance with the key value 'Id:1' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. 

    With a real database, my controllers work as expected (as detached). I mean, the entities start to be tracked when I retrieve them in the EditPost() method, and stopped to be tracked when _context.SaveChanges() is called.

    But in the Microsoft.EntityFrameworkCore.InMemory context, entities are tracked as soon as they are added (here with my DataGenerator() method), and nothing seems to be reset, when _context.SaveChanges() is called. So I get the above System.InvalidOperationException;

    While the "Find() method etc…" way works fine, it does not reproduce the "actual context" of data submission (with all that implies, like test accuracy, etc).

    So my question is:

    • How can I reproduce disconnected scenario during my tests with Microsoft.EntityFrameworkCore.InMemory? I mean, how can I reset change tracking when _context.SaveChanges() is called?
    Sunday, April 8, 2018 11:32 AM

Answers

  • User1120430333 posted

    The controller shouldn't be doing database activity to even be trying to unit test. Your misusage stems from not fully understand how to use the MVC pattern effectively that is  going to allow you to unit test it. The database activity should be done in the Model. To take it a little further, the Model object shouldn't be doing database activity directly, which should be done with a Data Access Layer or using a Repository Layer.

    You need to understand how to implement Speration of Concerns in your overall architecture of the solution that would allow you to  unit test it effectively. 

    https://en.wikipedia.org/wiki/Separation_of_concerns

    https://www.c-sharpcorner.com/UploadFile/56fb14/understanding-separation-of-concern-and-Asp-Net-mvc/

    https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/overview/understanding-models-views-and-controllers-cs

    <copied>

    An MVC model contains all of your application logic that is not contained in a view or a controller. The model should contain all of your application business logic, validation logic, and database access logic. For example, if you are using the Microsoft Entity Framework to access your database, then you would create your Entity Framework classes (your .edmx file) in the Models folder.

    A view should contain only logic related to generating the user interface. A controller should only contain the bare minimum of logic required to return the right view or redirect the user to another action (flow control). Everything else should be contained in the model.+

    In general, you should strive for fat models and skinny controllers. Your controller methods should contain only a few lines of code. If a controller action gets too fat, then you should consider moving the logic out to a new class in the Models folder.

    <end>

    N-tier or Layered.......

    https://msdn.microsoft.com/en-us/library/ee658117.aspx

    https://msdn.microsoft.com/en-us/library/bb384398.aspx

    If the controller was calling a model object and the model class/object is using an Interface, one could mock out the model object in the controller by using a mocking framework and unit test the controller effectively. If the DAL classes/objects were using and Interface or the Repository objects were using an Interface that the model object was calling the objects in the DAL or Repository, then they could be mocked out at the model object with the Model being unit tested effectively. 

    Unit testing is about unit testing a class's behavior by one knowing how to arrange, act and assert a unit test to test a class's functionality that is to be unit tested in a simulated manner for expected results and mocking allows the simulation of  external dependencies at the 'arrange' and verified at the 'assert'.

    https://www.telerik.com/products/mocking/unit-testing.aspx

    <copied>

    Mocking is a process used in unit testing when the unit being tested has external dependencies. The purpose of mocking is to focus on the code being tested and not on the behavior or state of external dependencies. In mocking, the dependencies are replaced by closely controlled replacements objects that simulate the behavior of the real ones. There are three main types of replacement objects - stubs, fakes and mocks.

    <end>

    The external dependencies would be the call to the model object from the controller and giving the model object the expected input and expected output a particular method within the object in simulation. And that's where mocking comes into play to mock the data so that the test doesn't blow up, because you really never made the call to the database, but  other code within the object having the expected data or objects there, because you simulated it on the 'arrange' and passed into the class on the mock. 

    This is just example code of what the controller should look like if you wanted to unit test it effectively and the model that can be unit tested effectively, because the model object and the DAL objects can be mocked out when the controller and the model are unit tested.

    using System;
    using System.Linq;
    using System.Web.Mvc;
    using MVC.Models;
    using Microsoft.AspNet.Identity;
    
    namespace MVC.Controllers
    {
        public class ProjectController : BaseController
        {
            // GET: Project
            [Authorize]
            public ActionResult Index()
            {
                return View(new ProjectModels().GetProjectsByUserId(User.Identity.GetUserId()));
            }
    
            [Authorize]
            public ActionResult Details(int id = 0)
            {
                return id == 0 ? null : View(new ProjectModels().Edit(id));
            }
    
            [Authorize]
            public ActionResult Create()
            {
                return View(new ProjectModels().Create());
            }
    
            [Authorize]
            [HttpPost]
            public ActionResult Create(ProjectViewModels.Project project, string submit)
            {
                if (submit == "Cancel") return RedirectToAction("Index");
    
                ValidateddlProjectTypes();
    
                project.ProjectType = (Request.Form["ddlProjectTypes"]);
    
                if (new ModelsHelper().IsEndDateLessThanStartDate(project, "Project"))
                    ModelState.AddModelError(string.Empty, "End Date cannot be less than Start Date.");
    
                if (!ModelState.IsValid) return View(new ProjectModels().PopulateSelectedList(project));
    
                new ProjectModels().Create(project, User.Identity.GetUserId());
                return RedirectToAction("Index");
            }
    
            [Authorize]
            public ActionResult Edit(int id = 0)
            {
                return id == 0 ? null : View(new ProjectModels().Edit(id));
            }
    
            [Authorize]
            [HttpPost]
            public ActionResult Edit(ProjectViewModels.Project project, string submit)
            {
                if (submit == "Cancel") return RedirectToAction("Index");
    
                if (new ModelsHelper().IsEndDateLessThanStartDate(project, "Project"))
                    ModelState.AddModelError(String.Empty, "End Date cannot be less than Start Date.");
    
                if (!ModelState.IsValid) return View(new ProjectModels().PopulateSelectedList(project));
    
                var theproject = new ProjectViewModels.Project();
    
                theproject = project;
    
                theproject.ProjectType = Request.Form["ProjectType"];
    
                new ProjectModels().Edit(theproject, User.Identity.GetUserId());
                return RedirectToAction("Index");
            }
    
            public ActionResult Delete(int id = 0)
            {
                if (id > 0) new ProjectModels().Delete(id);
    
                return RedirectToAction("Index");
            }
       
            public ActionResult Cancel()
            {
                return RedirectToAction("Index", "Home");
            }
    
            public ActionResult UploadFile(int id)
            {
                return RedirectToAction("UploadFile", "Upload", new { id = id, type = "PM" });
            }
    
            private void ValidateddlProjectTypes()
            {
                if (Request.Form["ddlProjectTypes"] == string.Empty)
                {
                    ModelState.AddModelError("ProjectType", "Project Type is required");
                }
                else
                {
                    foreach (var key in ModelState.Keys.ToList().Where(key => ModelState.ContainsKey(key)))
                    {
                        if (key == "ProjectType")
                            ModelState[key].Errors.Clear();
                    }
                }
            }
        }
    }
    
    --------------------------------------------------------
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.Mvc;
    using DAL;
    using Entities;
    
    
    namespace MVC.Models
    {
        public class ProjectModels : IProjectModels
        {
            public ProjectViewModels GetProjectsByUserId(string userid)
            {
                var vm = new ProjectViewModels {Projects = new List<ProjectViewModels.Project>()};
                
                var dtos = new DaoProject().GetProjectsByUserId(userid);
    
                vm.Projects.AddRange(dtos.Select(dto => new ProjectViewModels.Project()
                {
                    ProjectId = dto.ProjectId,
                    ClientName = dto.ClientName,
                    ProjectName = dto.ProjectName,
                    Technology = dto.Technology,
                    ProjectType = dto.ProjectType,
                    StartDate = dto.StartDate,
                    EndDate = dto.EndDate,
                    Cost = dto.Cost
                }).ToList());
    
                return vm;
            }
    
            public ProjectViewModels.Project GetProjectById(int id)
            {
                var dto = new DaoProject().GetProjectById(id);
    
                var project = new ProjectViewModels.Project
                { 
                    ProjectId = dto.ProjectId,
                    ClientName = dto.ClientName,
                    ProjectName = dto.ProjectName,
                    Technology = dto.Technology,
                    ProjectType = dto.ProjectType,
                    StartDate = dto.StartDate,
                    EndDate = dto.EndDate,
                    Cost = dto.Cost
                };
       
                return project;
            }
    
            public ProjectViewModels.Project Create()
            {
                var project = new ProjectViewModels.Project();
                return PopulateSelectedList(project);
            }
    
            public void Create(ProjectViewModels.Project project, string userid)
            {
                var dto = new DtoProject
                {
                    ProjectId = project.ProjectId,
                    ClientName = project.ClientName,
                    ProjectName = project.ProjectName,
                    ProjectType = project.ProjectType,  
                    Technology = project.Technology,
                    UserId = userid,
                    StartDate = (DateTime) project.StartDate,
                    EndDate = (DateTime) project.EndDate,
                    Cost = (decimal) project.Cost
                };
    
                new DaoProject().CreateProject(dto);
            }
    
            public ProjectViewModels.Project Edit(int id)
            {
                var dto = new DaoProject().GetProjectById(id);
    
                var project = new ProjectViewModels.Project
                { 
                    ProjectId = dto.ProjectId,
                    ClientName = dto.ClientName,
                    ProjectName = dto.ProjectName,
                    Technology = dto.Technology,
                    ProjectType = dto.ProjectType,
                    StartDate = dto.StartDate,
                    EndDate = dto.EndDate,
                    Cost = dto.Cost
                };
    
                project = PopulateSelectedList(project);
    
                return project;
            }
    
            public void Edit(ProjectViewModels.Project project, string userid)
            {
                var dto = new DtoProject
                {
                    ProjectId = project.ProjectId,
                    ClientName = project.ClientName,
                    ProjectName = project.ProjectName,
                    ProjectType = project.ProjectType,
                    Technology = project.Technology,
                    UserId = userid,
                    StartDate = (DateTime) project.StartDate,
                    EndDate = (DateTime) project.EndDate,
                    Cost = (decimal) project.Cost
                };
    
                new DaoProject().UpdateProject(dto);
            }
    
            public void Delete(int id)
            {
                new DaoProject().DeleteProject(id);
            }
    
            public ProjectViewModels.Project PopulateSelectedList(ProjectViewModels.Project project)
            {
                project.ProjectTypes = new List<SelectListItem>
                {
                    new SelectListItem {Value = "1", Text = "Fixed Price"},
                    new SelectListItem {Value = "2", Text = "Time & Material"}
                };
    
                var selected = (from a in project.ProjectTypes.Where(a => a.Value == project.ProjectType) select a)
                    .SingleOrDefault();
    
                if (selected != null)
                    selected.Selected = true;
    
                return project;
            }
        }
    }
    ---------------------------------------
    
    using System.Collections.Generic;
    using System.Data.Entity;
    using System.Linq;
    using System.Transactions;
    using Entities;
    using DAL.Model;
    
    namespace DAL
    {
        public class DaoProject : IDaoProject
        {
            public DtoProject GetProjectById(int id)
            {
                var dto = new DtoProject();
    
                using (var context = new ProjectMgmntEntities())
                {
                    var project = (context.Projects.Where(a => a.ProjectId == id)).SingleOrDefault();
    
                    if (project == null) return dto;
                    dto.ProjectId = project.ProjectId;
                    dto.ClientName = project.ClientName;
                    dto.ProjectName = project.ProjectName;
                    dto.Technology = project.Technology;
                    dto.ProjectType = project.ProjectType;
                    dto.UserId = project.UserID;
                    dto.StartDate = project.StartDate;
                    dto.EndDate = project.EndDate;
                    dto.Cost = project.Cost;
                }
    
                return dto;
            }
    
            public List<DtoProject> GetProjectsByUserId(string userid)
            {
                var dtos = new List<DtoProject>();
    
                using (var context = new ProjectMgmntEntities())
                {
    
                    dtos = (from a in context.Projects.Where(a => a.UserID.Contains(userid))
                        select new DtoProject
                        {
                            ProjectId = a.ProjectId,
                            ClientName = a.ClientName,
                            ProjectName = a.ProjectName,
                            Technology = a.Technology,
                            ProjectType = a.ProjectType,
                            UserId = a.UserID,
                            StartDate = a.StartDate,
                            EndDate = a.EndDate,
                            Cost = a.Cost
                        }).ToList();
                }
    
                return dtos;
            }
    
            public void CreateProject(DtoProject dto)
            {
                using (var context = new ProjectMgmntEntities())
                {
                    var project = new Project
                    {
                        ClientName = dto.ClientName,
                        ProjectName = dto.ProjectName,
                        Technology = dto.Technology,
                        ProjectType = dto.ProjectType,
                        UserID = dto.UserId,
                        StartDate = dto.StartDate,
                        EndDate = dto.EndDate,
                        Cost = dto.Cost
                    };
    
                    context.Projects.Add(project);
                    context.SaveChanges();
                }
            }
    
            public void UpdateProject(DtoProject dto)
            {
                var project = new Project();
    
                using (var context = new ProjectMgmntEntities())
                {
                    project = (context.Projects.Where(a => a.ProjectId == dto.ProjectId)).SingleOrDefault();
                }
    
                if (project != null)
                {
                    project.ClientName = dto.ClientName;
                    project.ProjectName = dto.ProjectName;
                    project.Technology = dto.Technology;
                    project.ProjectType = dto.ProjectType;
                    project.UserID = dto.UserId;
                    project.StartDate = dto.StartDate;
                    project.EndDate = dto.EndDate;
                    project.Cost = dto.Cost;
                }
    
                using (var dbcontext = new ProjectMgmntEntities())
                {
                    if (project == null) return;
                    dbcontext.Entry(project).State = EntityState.Modified;
                    dbcontext.SaveChanges();
                }
            }
    
            public void DeleteProject(int id)
            {
                Project project;
    
                using (var context = new ProjectMgmntEntities())
                {
                    project = (context.Projects.Where(a => a.ProjectId == id)).SingleOrDefault();
                }
    
                if (project == null) return;
    
                using (var newContext = new ProjectMgmntEntities())
                {
                    var tasks = new DaoTask().GetTasksByProjectId(project.ProjectId);
                    using (TransactionScope scope = new TransactionScope())
                    {
                        foreach (var task in tasks)
                        {
                            new DaoTask().DeleteTask(task.TaskId);
                        }
    
                        newContext.Entry(project).State = EntityState.Deleted;
                        newContext.SaveChanges();
    
                        scope.Complete();
                    }
                }
            }
        }
    }
    
    

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Sunday, April 8, 2018 9:34 PM

All replies

  • User1120430333 posted

    The controller shouldn't be doing database activity to even be trying to unit test. Your misusage stems from not fully understand how to use the MVC pattern effectively that is  going to allow you to unit test it. The database activity should be done in the Model. To take it a little further, the Model object shouldn't be doing database activity directly, which should be done with a Data Access Layer or using a Repository Layer.

    You need to understand how to implement Speration of Concerns in your overall architecture of the solution that would allow you to  unit test it effectively. 

    https://en.wikipedia.org/wiki/Separation_of_concerns

    https://www.c-sharpcorner.com/UploadFile/56fb14/understanding-separation-of-concern-and-Asp-Net-mvc/

    https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/overview/understanding-models-views-and-controllers-cs

    <copied>

    An MVC model contains all of your application logic that is not contained in a view or a controller. The model should contain all of your application business logic, validation logic, and database access logic. For example, if you are using the Microsoft Entity Framework to access your database, then you would create your Entity Framework classes (your .edmx file) in the Models folder.

    A view should contain only logic related to generating the user interface. A controller should only contain the bare minimum of logic required to return the right view or redirect the user to another action (flow control). Everything else should be contained in the model.+

    In general, you should strive for fat models and skinny controllers. Your controller methods should contain only a few lines of code. If a controller action gets too fat, then you should consider moving the logic out to a new class in the Models folder.

    <end>

    N-tier or Layered.......

    https://msdn.microsoft.com/en-us/library/ee658117.aspx

    https://msdn.microsoft.com/en-us/library/bb384398.aspx

    If the controller was calling a model object and the model class/object is using an Interface, one could mock out the model object in the controller by using a mocking framework and unit test the controller effectively. If the DAL classes/objects were using and Interface or the Repository objects were using an Interface that the model object was calling the objects in the DAL or Repository, then they could be mocked out at the model object with the Model being unit tested effectively. 

    Unit testing is about unit testing a class's behavior by one knowing how to arrange, act and assert a unit test to test a class's functionality that is to be unit tested in a simulated manner for expected results and mocking allows the simulation of  external dependencies at the 'arrange' and verified at the 'assert'.

    https://www.telerik.com/products/mocking/unit-testing.aspx

    <copied>

    Mocking is a process used in unit testing when the unit being tested has external dependencies. The purpose of mocking is to focus on the code being tested and not on the behavior or state of external dependencies. In mocking, the dependencies are replaced by closely controlled replacements objects that simulate the behavior of the real ones. There are three main types of replacement objects - stubs, fakes and mocks.

    <end>

    The external dependencies would be the call to the model object from the controller and giving the model object the expected input and expected output a particular method within the object in simulation. And that's where mocking comes into play to mock the data so that the test doesn't blow up, because you really never made the call to the database, but  other code within the object having the expected data or objects there, because you simulated it on the 'arrange' and passed into the class on the mock. 

    This is just example code of what the controller should look like if you wanted to unit test it effectively and the model that can be unit tested effectively, because the model object and the DAL objects can be mocked out when the controller and the model are unit tested.

    using System;
    using System.Linq;
    using System.Web.Mvc;
    using MVC.Models;
    using Microsoft.AspNet.Identity;
    
    namespace MVC.Controllers
    {
        public class ProjectController : BaseController
        {
            // GET: Project
            [Authorize]
            public ActionResult Index()
            {
                return View(new ProjectModels().GetProjectsByUserId(User.Identity.GetUserId()));
            }
    
            [Authorize]
            public ActionResult Details(int id = 0)
            {
                return id == 0 ? null : View(new ProjectModels().Edit(id));
            }
    
            [Authorize]
            public ActionResult Create()
            {
                return View(new ProjectModels().Create());
            }
    
            [Authorize]
            [HttpPost]
            public ActionResult Create(ProjectViewModels.Project project, string submit)
            {
                if (submit == "Cancel") return RedirectToAction("Index");
    
                ValidateddlProjectTypes();
    
                project.ProjectType = (Request.Form["ddlProjectTypes"]);
    
                if (new ModelsHelper().IsEndDateLessThanStartDate(project, "Project"))
                    ModelState.AddModelError(string.Empty, "End Date cannot be less than Start Date.");
    
                if (!ModelState.IsValid) return View(new ProjectModels().PopulateSelectedList(project));
    
                new ProjectModels().Create(project, User.Identity.GetUserId());
                return RedirectToAction("Index");
            }
    
            [Authorize]
            public ActionResult Edit(int id = 0)
            {
                return id == 0 ? null : View(new ProjectModels().Edit(id));
            }
    
            [Authorize]
            [HttpPost]
            public ActionResult Edit(ProjectViewModels.Project project, string submit)
            {
                if (submit == "Cancel") return RedirectToAction("Index");
    
                if (new ModelsHelper().IsEndDateLessThanStartDate(project, "Project"))
                    ModelState.AddModelError(String.Empty, "End Date cannot be less than Start Date.");
    
                if (!ModelState.IsValid) return View(new ProjectModels().PopulateSelectedList(project));
    
                var theproject = new ProjectViewModels.Project();
    
                theproject = project;
    
                theproject.ProjectType = Request.Form["ProjectType"];
    
                new ProjectModels().Edit(theproject, User.Identity.GetUserId());
                return RedirectToAction("Index");
            }
    
            public ActionResult Delete(int id = 0)
            {
                if (id > 0) new ProjectModels().Delete(id);
    
                return RedirectToAction("Index");
            }
       
            public ActionResult Cancel()
            {
                return RedirectToAction("Index", "Home");
            }
    
            public ActionResult UploadFile(int id)
            {
                return RedirectToAction("UploadFile", "Upload", new { id = id, type = "PM" });
            }
    
            private void ValidateddlProjectTypes()
            {
                if (Request.Form["ddlProjectTypes"] == string.Empty)
                {
                    ModelState.AddModelError("ProjectType", "Project Type is required");
                }
                else
                {
                    foreach (var key in ModelState.Keys.ToList().Where(key => ModelState.ContainsKey(key)))
                    {
                        if (key == "ProjectType")
                            ModelState[key].Errors.Clear();
                    }
                }
            }
        }
    }
    
    --------------------------------------------------------
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.Mvc;
    using DAL;
    using Entities;
    
    
    namespace MVC.Models
    {
        public class ProjectModels : IProjectModels
        {
            public ProjectViewModels GetProjectsByUserId(string userid)
            {
                var vm = new ProjectViewModels {Projects = new List<ProjectViewModels.Project>()};
                
                var dtos = new DaoProject().GetProjectsByUserId(userid);
    
                vm.Projects.AddRange(dtos.Select(dto => new ProjectViewModels.Project()
                {
                    ProjectId = dto.ProjectId,
                    ClientName = dto.ClientName,
                    ProjectName = dto.ProjectName,
                    Technology = dto.Technology,
                    ProjectType = dto.ProjectType,
                    StartDate = dto.StartDate,
                    EndDate = dto.EndDate,
                    Cost = dto.Cost
                }).ToList());
    
                return vm;
            }
    
            public ProjectViewModels.Project GetProjectById(int id)
            {
                var dto = new DaoProject().GetProjectById(id);
    
                var project = new ProjectViewModels.Project
                { 
                    ProjectId = dto.ProjectId,
                    ClientName = dto.ClientName,
                    ProjectName = dto.ProjectName,
                    Technology = dto.Technology,
                    ProjectType = dto.ProjectType,
                    StartDate = dto.StartDate,
                    EndDate = dto.EndDate,
                    Cost = dto.Cost
                };
       
                return project;
            }
    
            public ProjectViewModels.Project Create()
            {
                var project = new ProjectViewModels.Project();
                return PopulateSelectedList(project);
            }
    
            public void Create(ProjectViewModels.Project project, string userid)
            {
                var dto = new DtoProject
                {
                    ProjectId = project.ProjectId,
                    ClientName = project.ClientName,
                    ProjectName = project.ProjectName,
                    ProjectType = project.ProjectType,  
                    Technology = project.Technology,
                    UserId = userid,
                    StartDate = (DateTime) project.StartDate,
                    EndDate = (DateTime) project.EndDate,
                    Cost = (decimal) project.Cost
                };
    
                new DaoProject().CreateProject(dto);
            }
    
            public ProjectViewModels.Project Edit(int id)
            {
                var dto = new DaoProject().GetProjectById(id);
    
                var project = new ProjectViewModels.Project
                { 
                    ProjectId = dto.ProjectId,
                    ClientName = dto.ClientName,
                    ProjectName = dto.ProjectName,
                    Technology = dto.Technology,
                    ProjectType = dto.ProjectType,
                    StartDate = dto.StartDate,
                    EndDate = dto.EndDate,
                    Cost = dto.Cost
                };
    
                project = PopulateSelectedList(project);
    
                return project;
            }
    
            public void Edit(ProjectViewModels.Project project, string userid)
            {
                var dto = new DtoProject
                {
                    ProjectId = project.ProjectId,
                    ClientName = project.ClientName,
                    ProjectName = project.ProjectName,
                    ProjectType = project.ProjectType,
                    Technology = project.Technology,
                    UserId = userid,
                    StartDate = (DateTime) project.StartDate,
                    EndDate = (DateTime) project.EndDate,
                    Cost = (decimal) project.Cost
                };
    
                new DaoProject().UpdateProject(dto);
            }
    
            public void Delete(int id)
            {
                new DaoProject().DeleteProject(id);
            }
    
            public ProjectViewModels.Project PopulateSelectedList(ProjectViewModels.Project project)
            {
                project.ProjectTypes = new List<SelectListItem>
                {
                    new SelectListItem {Value = "1", Text = "Fixed Price"},
                    new SelectListItem {Value = "2", Text = "Time & Material"}
                };
    
                var selected = (from a in project.ProjectTypes.Where(a => a.Value == project.ProjectType) select a)
                    .SingleOrDefault();
    
                if (selected != null)
                    selected.Selected = true;
    
                return project;
            }
        }
    }
    ---------------------------------------
    
    using System.Collections.Generic;
    using System.Data.Entity;
    using System.Linq;
    using System.Transactions;
    using Entities;
    using DAL.Model;
    
    namespace DAL
    {
        public class DaoProject : IDaoProject
        {
            public DtoProject GetProjectById(int id)
            {
                var dto = new DtoProject();
    
                using (var context = new ProjectMgmntEntities())
                {
                    var project = (context.Projects.Where(a => a.ProjectId == id)).SingleOrDefault();
    
                    if (project == null) return dto;
                    dto.ProjectId = project.ProjectId;
                    dto.ClientName = project.ClientName;
                    dto.ProjectName = project.ProjectName;
                    dto.Technology = project.Technology;
                    dto.ProjectType = project.ProjectType;
                    dto.UserId = project.UserID;
                    dto.StartDate = project.StartDate;
                    dto.EndDate = project.EndDate;
                    dto.Cost = project.Cost;
                }
    
                return dto;
            }
    
            public List<DtoProject> GetProjectsByUserId(string userid)
            {
                var dtos = new List<DtoProject>();
    
                using (var context = new ProjectMgmntEntities())
                {
    
                    dtos = (from a in context.Projects.Where(a => a.UserID.Contains(userid))
                        select new DtoProject
                        {
                            ProjectId = a.ProjectId,
                            ClientName = a.ClientName,
                            ProjectName = a.ProjectName,
                            Technology = a.Technology,
                            ProjectType = a.ProjectType,
                            UserId = a.UserID,
                            StartDate = a.StartDate,
                            EndDate = a.EndDate,
                            Cost = a.Cost
                        }).ToList();
                }
    
                return dtos;
            }
    
            public void CreateProject(DtoProject dto)
            {
                using (var context = new ProjectMgmntEntities())
                {
                    var project = new Project
                    {
                        ClientName = dto.ClientName,
                        ProjectName = dto.ProjectName,
                        Technology = dto.Technology,
                        ProjectType = dto.ProjectType,
                        UserID = dto.UserId,
                        StartDate = dto.StartDate,
                        EndDate = dto.EndDate,
                        Cost = dto.Cost
                    };
    
                    context.Projects.Add(project);
                    context.SaveChanges();
                }
            }
    
            public void UpdateProject(DtoProject dto)
            {
                var project = new Project();
    
                using (var context = new ProjectMgmntEntities())
                {
                    project = (context.Projects.Where(a => a.ProjectId == dto.ProjectId)).SingleOrDefault();
                }
    
                if (project != null)
                {
                    project.ClientName = dto.ClientName;
                    project.ProjectName = dto.ProjectName;
                    project.Technology = dto.Technology;
                    project.ProjectType = dto.ProjectType;
                    project.UserID = dto.UserId;
                    project.StartDate = dto.StartDate;
                    project.EndDate = dto.EndDate;
                    project.Cost = dto.Cost;
                }
    
                using (var dbcontext = new ProjectMgmntEntities())
                {
                    if (project == null) return;
                    dbcontext.Entry(project).State = EntityState.Modified;
                    dbcontext.SaveChanges();
                }
            }
    
            public void DeleteProject(int id)
            {
                Project project;
    
                using (var context = new ProjectMgmntEntities())
                {
                    project = (context.Projects.Where(a => a.ProjectId == id)).SingleOrDefault();
                }
    
                if (project == null) return;
    
                using (var newContext = new ProjectMgmntEntities())
                {
                    var tasks = new DaoTask().GetTasksByProjectId(project.ProjectId);
                    using (TransactionScope scope = new TransactionScope())
                    {
                        foreach (var task in tasks)
                        {
                            new DaoTask().DeleteTask(task.TaskId);
                        }
    
                        newContext.Entry(project).State = EntityState.Deleted;
                        newContext.SaveChanges();
    
                        scope.Complete();
                    }
                }
            }
        }
    }
    
    

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Sunday, April 8, 2018 9:34 PM
  • User-906047806 posted

    @DA924

    Sorry, but you are totally wrong… My controllers do nothing related to database activity… They look like this. I only follow the MS documentation…

    And my unit tests look like this (with exception of DataGenerator()).

    Monday, April 9, 2018 6:49 AM
  • User1120430333 posted

    @DA924

    Sorry, but you are totally wrong… My controllers do nothing related to database activity… They look like this. I only follow the MS documentation…

    And my unit tests look like this (with exception of DataGenerator()).

    Yeah, I see the tutorial. And it's calling the Repository or whatever you are trying to follow,  calling it from the controller instead of calling it from the Model, which I consider the tutorial a horrible example that does not use the MVC pattern in a SoC manner breaking the MVC UI design pattern principles

    Monday, April 9, 2018 11:37 AM
  • User1120430333 posted

    And I did look at the unit test, and no, myself, I would not be trying to unit test the controller with the Repository setting there in the controller. The path I would have taken is to make the call from the controller to the model and mocking out the model object based on the Interface for the model in a unit test.

    The model object would be making the call to the Repository, which would be  following the MVC SoC  UI design pattern  principles where it is the model that makes the calls to the repository and not the controller making direct calls to the database or even using a repository to make the calls either on its behalf. It's the model's job to do it and not the controller.

    Just because one see someone doing something in a tutorial, it  is not the gospel and is only one person's view of how he or she thinks things should be done, which is a lot of problems with tutorials. Developers that view a tutorial as some kind of blueprint and takes it no further of not thinking outside of the box seem to not do things in an optimal manner.  

    Monday, April 9, 2018 1:00 PM
  • User-906047806 posted

    Yeah, Andrew Troelsen, Philip Japikse, Adam Freeman and MS guys are completely wrong… These are bad guys for my references (just to be sure: it is ironical).

    Man, you do not give me any answer… you waste your time, and more than this, you waste MY time.

    If you enjoy to lose your time, know that life is short, and I can not afford to waste mine. So please, just ignore me, as well as my posts.


    Edit Thursday, May 31 2018

    @DA924

    I apologize.

    Even if it was not the answer that I expected, after reconsideration, I find it very useful!

    Thanks again.

    Monday, April 9, 2018 2:39 PM
  • User1120430333 posted

    Yeah, Andrew Troelsen, Philip Japikse, Adam Freeman and MS guys are completely wrong… These are bad guys for my references (just to be sure: it is ironical).

    Man, you do not give me any answer… you waste your time, and more than this, you waste MY time.

    If you enjoy to lose your time, know that life is short, and I can not afford to waste mine. So please, just ignore me, as well as my posts.

    Yeah, I started in IT in 1971, started programming  professionally in 1980 ,  went to the MS platform in the 1990(s), went to .NET in year 2000 and still going strong. I don't think there is too much anyone you are talking about could show me. :)

    You show a lot of disrespect, and you act more like a Donald Trump more than you know. 

    Monday, April 9, 2018 3:14 PM