none
DTOs, Repositories, BALs RRS feed

  • Question

  • First of all,  I'm sorry for the long text. 
    I'm a noob on DTOs, DALs, BALs, Repository patterns and stuff. So every time  I see one info about it, I use it, when I see another, I see if I can use the new method and if(true) Console.Write("I used it"); rsrsrsrs

    So, I'm having like a teenager love crisis, I can't have my focus on one info, because I don't have enough experience to guide me through this amount of info.

    On one of my post here on MSDN, a user named DA924x, told me about DTOs a few times, and my scavenging for info according my actual skill (I usually don't use info, that makes me learn new info to use that, is just too time consuming sometimes), and I found repository, repository pattern.

    I found a very very cool thing Are DTOs the same as using the Repository pattern? 

    The app that my team is developing will need to make CRUD operations.

    I was having problems on the crud, so I decided that I should map the tables by creating the classes, something like EF Model does (EF isn't working on my case, and I passed that, so there's no point on talk about it).

    I was seeking to use DTOs, but I use a CRUD Dapper extension and this extension, create a Interface and a class with CRUD operations all from my classes

    public class Friend
        {
            public int FriendID { get; set; }
            public string Name { get; set; }
            public string City { get; set; }
    
            public string PhoneNumber { get; set; }
    
        }
    
     public interface IFriendRepository
            {
                List<Friend> SelectFriend();
                void InsertFriend(Friend friend);
                void UpdateFriend(Friend friend);
                void DeleteFriend(Friend friend);
            }
    
     public class FriendRepository : IFriendRepository
            {
            
                public List<Friend> SelectFriend()
                {
                    // Select
                     
                }
                public void InsertFriend(Friend friend)
                {
                    // Insert
                    
                }
                public void UpdateFriend(Friend friend)
                {
                    // Update
                    
                }
                public void DeleteFriend(Friend friend)
                {
                    // Delete
                    
                }
            }

    I just remove the logic, but it all work as expected. So I copied the same technique to my team's project (the part I'm working in) but now I have a class like this one:

     public class Animal
        {
            public int Id{ get; set; }
            public string Name { get; set; }
            public int IdCategory { get; set; }
    
        }
    
     public class CategoryOfAnimal
        {
            public int Id{ get; set; }
            public string Category{ get; set; }
        }


    The problem is, when I do the select using the technique I just said, I have to write something like this: 

    select a.id, a.name, c.category from animal, categoryofanimal where a.IdCategory=c.id

    But I have to return it as a whole (with both animal and categoryofanimal) to the end consumer, I could just alter the class, but Its seems not right.

    So I'm thinking that I could use something I could only transfer the final data, something like a database view.

    My superior here at work is someone that only write code, he doesn't look for patterns and stuff, test classes (I'm not good on that, but I try to write them). Probably my superior here he is coding like things should exit and now how thing should be.

    For example is he probably has a class or something with both Animal and Category in one place without the real ones (at least this is not the way it must be in database design techniques).

    Before all, I'm sorry one more time for the long text. 

    I just don't have no one to talk about it by voice.

    And second, please define like you're explaining to a child (please) what is, when its used, what does serves for: DTOs, BALs and repositories.

    And then give me a solution of my problem (please) with simple examples.

    Please, I just now how to code, learning the rules is the hardest thing, I might know what is a bool, but not to use it perfectly. That's my problem right now with layered applications and CRUD.

    Please don't use advanced things, I understand the code, but this DTOs and repository thing is really messing with me.

    And if here's is not the place to ask such questions, please point me to the right one.

    Please, it's my 1st job and I really need to start writing better code, even if only I can tell.

    PS: When I said I mapped, I'm talking about the models ( something like that ones on Asp.net, then you use it to create a View)


    BP-LP 2005/2016 @ll rights reserved




    Monday, December 17, 2018 8:50 AM

Answers

  • using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc.Rendering;
    
    namespace ProgMgmntCore2UserIdentity.Models
    {
        public class ProjectViewModels
        {
            public class Project
            {
                public int ProjectId { get; set; }
    
                [Required(ErrorMessage = "Client Name is required")]
                [StringLength(50)]
                public string ClientName { get; set; }
    
                [Required(ErrorMessage = "Project Name is required")]
                [StringLength(50)]
                public string ProjectName { get; set; }
    
                [Required(ErrorMessage = "Technology is required")]
                [StringLength(50)]
                public string Technology { get; set; }
    
                [Required(ErrorMessage = "Project Type is required")]
                public string ProjectType { get; set; }
    
                [Required(ErrorMessage = "Start Date is required")]
                [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM-dd-yyyy}")]
                public DateTime? StartDate { get; set; }
    
                [Required(ErrorMessage = "End Date is required")]
                [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM-dd-yyyy}")]
                public DateTime? EndDate { get; set; }
    
                [Required(ErrorMessage = "Cost is required")]
                public decimal? Cost { get; set; }
    
                public List<SelectListItem> ProjectTypes { get; set; }
            }
           
            public List<Project> Projects { get; set; }
            
        }
    }

    using System;
    using System.Linq;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.ModelBinding;
    using ProgMgmntCore2UserIdentity.Models;
    
    namespace ProgMgmntCore2UserIdentity.Controllers
    {
        public class ProjectController : Controller
        {
            private readonly IProjectModel _projectModel;
            private readonly IModelHelper _modelHelper;
           
            public ProjectController(IProjectModel projectModel,   IModelHelper modelHelper)
            {
                _projectModel = projectModel;
                _modelHelper = modelHelper;
            }
    
            // GET: Project
            [Authorize]
            public ActionResult Index()
            {
                return View(_projectModel.GetProjectsByUserId(User.Identity.Name));
            }
    
            [Authorize]
            public ActionResult Details(int id = 0)
            {
                return id == 0 ? null : View(_projectModel.Edit(id));
            }
    
            [Authorize]
            public ActionResult Create()
            {
                return View(_projectModel.Create());
            }
    
            [Authorize]
            [HttpPost]
            public ActionResult Create(ProjectViewModels.Project project, string submit)
            {
                if (submit == "Cancel") return RedirectToAction("Index");
    
                ValidateddlProjectTypes();
    
                project.ProjectType = (Request.Form["ddlProjectTypes"]);
    
                if (ModelState.IsValid && _modelHelper.IsEndDateLessThanStartDate(project, "Project"))
                    ModelState.AddModelError(string.Empty, "End Date cannot be less than Start Date.");
    
                if (!ModelState.IsValid) return View(_projectModel.PopulateSelectedList(project));
    
                _projectModel.Create(project, User.Identity.Name);
                return RedirectToAction("Index");
            }
    
            [Authorize]
            public ActionResult Edit(int id = 0)
            {
                return id == 0 ? null : View(_projectModel.Edit(id));
            }
    
            [Authorize]
            [HttpPost]
            public ActionResult Edit(ProjectViewModels.Project project, string submit)
            {
                if (submit == "Cancel") return RedirectToAction("Index");
    
                if (ModelState.IsValid && _modelHelper.IsEndDateLessThanStartDate(project, "Project"))
                    ModelState.AddModelError(String.Empty, "End Date cannot be less than Start Date.");
    
                if (!ModelState.IsValid) return View(_projectModel.PopulateSelectedList(project));
    
                var theproject = new ProjectViewModels.Project();
    
                theproject = project;
    
                theproject.ProjectType = Request.Form["ProjectType"];
    
                _projectModel.Edit(theproject, User.Identity.Name);
                return RedirectToAction("Index");
            }
    
            public ActionResult Delete(int id = 0)
            {
                if (id > 0) _projectModel.Delete(id);
    
                return RedirectToAction("Index");
            }
       
            public ActionResult Cancel()
            {
                return RedirectToAction("Index", "Home");
            }
    
            public ActionResult UploadFile(int id)
            {
                return RedirectToAction("Index", "Upload", new { id = id, type = "PM" });
            }
    
            private void ValidateddlProjectTypes()
            {
                if (Request.Form["ddlProjectTypes"] == string.Empty)
                  return;
           
                foreach (var key in ModelState.Keys.ToList().Where(key => ModelState.ContainsKey(key)))
                {
                    if (key != "ProjectType") continue;
                    ModelState[key].Errors.Clear();
                    ModelState[key].ValidationState = ModelValidationState.Valid;
                }
            }
        }
    }

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Entities;
    using Microsoft.AspNetCore.Mvc.Rendering;
    using Microsoft.Extensions.Caching.Memory;
    using ProgMgmntCore2UserIdentity.WebApi;
    
    namespace ProgMgmntCore2UserIdentity.Models
    {
        public class ProjectModel : IProjectModel
        {
            private readonly IMemoryCache _memoryCache;
            private readonly IWebApi _webApi;
    
            public ProjectModel(IWebApi webApi, IMemoryCache memoryCache)
            {
                _memoryCache = memoryCache;
                _webApi = webApi;
            }
    
            public ProjectViewModels GetProjectsByUserId(string userid)
            {
                var vm = new ProjectViewModels {Projects = new List<ProjectViewModels.Project>()};
    
                var dtos = _webApi.GetProjsByUserIdApi(userid).ToList();
                
                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 responseDto = _webApi.GetProjByIdApi(id);
    
                var project = new ProjectViewModels.Project
                {
                    ProjectId = responseDto.ProjectId,
                    ClientName = responseDto.ClientName,
                    ProjectName = responseDto.ProjectName,
                    Technology = responseDto.Technology,
                    ProjectType = responseDto.ProjectType,
                    StartDate = responseDto.StartDate,
                    EndDate = responseDto.EndDate,
                    Cost = responseDto.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
                };
    
                _webApi.CreateProjectApi(dto);
            }
    
            public ProjectViewModels.Project Edit(int id)
            {
                var responseDto = _webApi.GetProjByIdApi(id);
    
                var project = new ProjectViewModels.Project
                {
                    ProjectId = responseDto.ProjectId,
                    ClientName = responseDto.ClientName,
                    ProjectName = responseDto.ProjectName,
                    Technology = responseDto.Technology,
                    ProjectType = responseDto.ProjectType,
                    StartDate = responseDto.StartDate,
                    EndDate = responseDto.EndDate,
                    Cost = responseDto.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
                };
    
                _webApi.UpdateProjectApi(dto); 
            }
    
            public void Delete(int id)
            {
                _webApi.DeleteProjectApi(new DtoId{Id = id});
            }
    
            public ProjectViewModels.Project PopulateSelectedList(ProjectViewModels.Project project)
            {
                bool isExist = _memoryCache.TryGetValue("DtoCache", out DtoCache dtocache);
    
                if (!isExist)
                {
                    dtocache = _webApi.GetCacheApi();
              
                    var cacheEntryOptions = new MemoryCacheEntryOptions()
                        .SetSlidingExpiration(TimeSpan.FromSeconds(30));
                    
                    _memoryCache.Set("DtoCache", dtocache, cacheEntryOptions);
                }
    
                project.ProjectTypes = new List<SelectListItem>();
    
                foreach (var pt in dtocache.ProjectTypes)
                {
                    var sli = new SelectListItem {Value = pt.Value, Text = pt.Text};
                    project.ProjectTypes.Add(sli);
                }
           
                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;
    using System.Collections.Generic;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Text;
    using Entities;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    
    namespace ProgMgmntCore2UserIdentity.WebApi
    {
        public class WebApi : IWebApi
        {
            #region ProjectApi
            
            public List<DtoProject> GetProjsByUserIdApi(string userid)
            {
                var dtoprojects = new List<DtoProject>();
    
                using (var client = new HttpClient())
                {
                    var uri = new Uri("http://progmgmntcore2api.com/api/project/GetProjsByUserId?userid=" + userid);
    
                    var response = client.GetAsync(uri).Result;
    
                    if (!response.IsSuccessStatusCode)
                        throw new Exception(response.ToString());
    
                    var responseContent = response.Content;
                    var responseString = responseContent.ReadAsStringAsync().Result;
    
                    dynamic projects = JArray.Parse(responseString) as JArray;
    
                    foreach (var obj in projects)
                    {
                        DtoProject dto = obj.ToObject<DtoProject>();
    
                        dtoprojects.Add(dto);
                    }
                }
    
                return dtoprojects;
            }
    
            public DtoProject GetProjByIdApi(int id)
            {
                DtoProject dto;
    
                using (var client = new HttpClient())
                {
                    var uri = new Uri("http://progmgmntcore2api.com/api/project/GetProjById?id=" + id);
                    HttpResponseMessage getResponseMessage = client.GetAsync(uri).Result;
    
                    if (!getResponseMessage.IsSuccessStatusCode)
                        throw new Exception(getResponseMessage.ToString());
    
                    var responsemessage = getResponseMessage.Content.ReadAsStringAsync().Result;
    
                    dynamic project = JsonConvert.DeserializeObject(responsemessage);
    
                    dto = project.ToObject<DtoProject>();
                }
    
                return dto;
            }
    
            public void CreateProjectApi(DtoProject dto)
            {
                using (var client = new HttpClient { BaseAddress = new Uri("http://progmgmntcore2api.com") })
                {
                    string serailizeddto = JsonConvert.SerializeObject(dto);
    
                    var inputMessage = new HttpRequestMessage
                    {
                        Content = new StringContent(serailizeddto, Encoding.UTF8, "application/json")
                    };
    
                    inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                    HttpResponseMessage message =
                        client.PostAsync("api/project/CreateProject", inputMessage.Content).Result;
    
                    if (!message.IsSuccessStatusCode)
                        throw new Exception(message.ToString());
                }
            }
    
            public void UpdateProjectApi(DtoProject dto)
            {
                using (var client = new HttpClient { BaseAddress = new Uri("http://progmgmntcore2api.com") })
                {
                    string serailizeddto = JsonConvert.SerializeObject(dto);
    
                    var inputMessage = new HttpRequestMessage
                    {
                        Content = new StringContent(serailizeddto, Encoding.UTF8, "application/json")
                    };
    
                    inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                    HttpResponseMessage message =
                        client.PostAsync("api/project/UpdateProject", inputMessage.Content).Result;
    
                    if (!message.IsSuccessStatusCode)
                        throw new Exception(message.ToString());
                }
            }
    
            public void DeleteProjectApi(DtoId dto)
            {
                using (var client = new HttpClient { BaseAddress = new Uri("http://progmgmntcore2api.com") })
                {
                    string serailizeddto = JsonConvert.SerializeObject(dto);
    
                    var inputMessage = new HttpRequestMessage
                    {
                        Content = new StringContent(serailizeddto, Encoding.UTF8, "application/json")
                    };
    
                    inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                    HttpResponseMessage message =
                        client.PostAsync("api/project/DeleteProject", inputMessage.Content).Result;
    
                    if (!message.IsSuccessStatusCode)
                        throw new Exception(message.ToString());
                }
            }
    
    }

    using System.Collections.Generic;
    using DAL;
    using Entities;
    using Microsoft.AspNetCore.Mvc;
    
    namespace ProgMgmntCore2Api.Controllers
    {
        [Produces("application/json")]
        [Route("api/[controller]")]
        [ApiController]
    
        public class ProjectController : ControllerBase, IProjectController
        {
            private readonly IDaoProject _daoProject;
    
            public ProjectController(IDaoProject daoProject)
            {
                _daoProject = daoProject;
            }
    
            [HttpGet]
            [Route("GetProjById")]
            public DtoProject GetProjectById(int id)
            {
                return  _daoProject.GetProjectById(id);
            }
            
            [HttpGet]
            [Route("GetProjsByUserId")]
            public List<DtoProject> GetProjectsByUserId(string userid)
            {
                return _daoProject.GetProjectsByUserId(userid);
            }
    
            [HttpPost]
            [Route("CreateProject")]
            public void Post_CreateProject(DtoProject dto)
            {
                _daoProject.CreateProject(dto);
            }
    
            [HttpPost]
            [Route("DeleteProject")]
            public void Post_DeleteProject(DtoId dto)
            {
                _daoProject.DeleteProject(dto.Id);
            }
    
            [HttpPost]
            [Route("UpdateProject")]
            public void Post_UpdateProject(DtoProject dto)
            {
                _daoProject.UpdateProject(dto);
            }
        }
    }
    

    using System.Collections.Generic;
    using System.Linq;
    using System.Transactions;
    using DAL.Models.DB;
    using Entities;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Options;
    
    namespace DAL
    {
        public class DaoProject :IDaoProject
        {
            private readonly IOptions<ConnectionStrings> _options;
            
            public DaoProject(IOptions<ConnectionStrings> options)
            {
                _options = options;
            }
    
            public DtoProject GetProjectById(int id)
            {
                var dto = new DtoProject();
    
                using (var context = new ProjectManagementContext(_options))
                {
                    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 ProjectManagementContext(_options))
                {
                    
                    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 ProjectManagementContext(_options))
                {
                    var project = new Projects
                    {
                        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 Projects();
                
                using (var context = new ProjectManagementContext(_options))
                {
                   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 ProjectManagementContext(_options))
                {
                    if (project == null) return;
                    dbcontext.Entry(project).State = EntityState.Modified;
                    dbcontext.SaveChanges();
                }
            }
    
            public void DeleteProject(int id)
            {
                Projects project;
    
                using (var context = new ProjectManagementContext(_options))
                {
                   project = (context.Projects.Where(a => a.ProjectId == id)).SingleOrDefault();
                }
    
                if (project == null) return;
    
                using (var newContext = new ProjectManagementContext(_options))
                {
                   
                    var tasks = new DaoTask(_options).GetTasksByProjectId(project.ProjectId);
                    using (TransactionScope scope = new TransactionScope())
                    {
                        foreach (var task in tasks)
                        {
                            new DaoTask(_options).DeleteTask(task.TaskId);
                        }
    
                        newContext.Entry(project).State = EntityState.Deleted;
                        newContext.SaveChanges();
    
                        scope.Complete();
                    }
                }
            }
        }
    }
    

    using System;
    
    namespace Entities
    {
        public class DtoProject
        {
            public int ProjectId { get; set; }
            public string ClientName { get; set; }
            public string ProjectName { get; set; }
            public string Technology { get; set; }
            public string ProjectType { get; set; }
            public string UserId { get; set; }
            public DateTime StartDate { get; set; }
            public DateTime EndDate { get; set; }
            public decimal Cost { get; set; }
        }
    }
    



    Monday, December 17, 2018 12:25 PM

All replies

  • I'm very excited when I read something like your article. It is very nice to see when people learn new skills and techniques. 

    Don't limit yourself. At first, what you use is not repository pattern, it is DAO pattern. Repository is much complex class which takes some persistence out of database. DAO pattern is not bad access for smaller project or project when you needn't more complexity. 

    Don't limit yourself when you get data from database. Create update/insert/delete methods to work with table. It means these methods take object as you described as parameter. But select method can return some another object which can bring data what you need. When you need for one case object which is same as record you can return object which is parameter of update/delete/insert methods. In another case you can return object which brings text representation of animal category. So there will be more then one method for select and there can be join to tables which you need. 

    It means there can be difference between objects which go from data layer to layer above and objects which go from layer above to data layer. Application layer, or in smaller application it can be presenter/controller class, where mapping from/to data layer objects is. 

    Monday, December 17, 2018 11:32 AM
  • I found a very very cool thing Are DTOs the same as using the Repository pattern? 

    The DTO pattern is NOT the Repository pattern. The DTO is an object that carries data between processes like a Web service client program sending/receiving data between  the Web service program using a client/service architectural styled  application, the DTO is used to send data between layers  using a layered architectural styled  application  or the DTO is used to send data between tiers using a n-tier styled application are  examples where the DTO pattern can be used. 

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

    https://www.codeproject.com/Articles/1050468/Data-Transfer-Object-Design-Pattern-in-Csharp

    https://docs.microsoft.com/en-us/previous-versions/msp-n-p/ee658117(v=pandp.10)

    The app that my team is developing will need to make CRUD operations.

    I was having problems on the crud, so I decided that I should map the tables by creating the classes, something like EF Model does (EF isn't working on my case, and I passed that, so there's no point on talk about it).

    If the class/object is to be a DTO then name the object appropriately with a prefix that starts with DTO. It is DtoFriend  so that any developer looking a the class and knows about the usage of the DTO knows the purpose of DtoFriend. It has no other purpose but the carry data, which would be obvious to any one looking at the code.

    I was seeking to use DTOs, but I use a CRUD Dapper extension and this extension, create a Interface and a class with CRUD operations all from my classes

    ORM(s) like EF, nHibernate and an micro  ORM like Dapper have classes called the virtual object model that are used for data persistence/CRUD with the underlying database technology that is their purpose the persistence model.

    A DTO is NOT a ORM's virtual object model object a persistence object. The DTO's job is to carry data between processes , layers or tiers.

    So don't confuse the DTO or a domain object/business object with the persistence model of the ORM.

    https://blog.sapiensworks.com/post/2012/04/07/Just-Stop-It!-The-Domain-Model-Is-Not-The-Persistence-Model.aspx

    You have to map the persistence object to the DTO and visa versa of DTO mapped back to the persistence object in doing CRUD operation using the ORM with the underlying DB technology. 

    About the Repository pattern that was invented  by Martin Fowler when he invented Doman Driven Design back in the early 2000(s), the repository pattern is a DOMAIN OBJECT a BUSSINES OBJECT. it is not a data persistence object that so many developers have twisted into something that it was not indented to do.

    https://martinfowler.com/eaaCatalog/repository.html

    <copied>

    A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers.

    <end>

    https://programmingwithmosh.com/entity-framework/common-mistakes-with-the-repository-pattern/

    <copied>

    Save/Update method in repositories

    Yet another very common mistake! As I’ve explained in my YouTube video before, your repositories should not have a Save() or Update() method. I repeat: think of a repository as a collection of domain objects in memory. Do collections have a Save() or Update() method? No!

    <end>

    http://blog.sapiensworks.com/post/2012/11/01/Repository-vs-DAO.aspx

    A DAO is much closer to the underlying storage , it's really data centric. That's why in many cases you'll have DAOs matching db tables or views 1 on 1. A DAO allows for a simpler way to get data from a storage, hiding the ugly queries. But the important part is that they return data as in object state.

    A repository sits at a higher level. It deals with data too and hides queries and all that but, a repository deals with** business/domain objects**. That's the difference. A repository will use a DAO to get the data from the storage and uses that data to restore a business object. Or it will take a business object and extract the data that will be persisted. If you have an anemic domain, the repository will be just a DAO. Also when dealing with querying stuff, most of the time a specialized query repository is just a DAO sending DTOs to a higher layer.

    <end>

    Man, you have an anemic domain that has no business using the repository pattern,  and your repository object is no more than a glorified DAO. Your BAL should be using a Data Access Layer DAL with the DAL using the DAO pattern and your solution should be using the DTO pattern.

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

    https://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm

    I am going to show you one more time with code in a subsequent post as to how the DAO with DTO pattern comes into play in an ASP.NET MVC solution that is using WebAPI the DTO and DAO pattern that is working with a single database table called Project as one element in a project tracking application. The DtoProject is kept in a classlib project called Entities and all the other tiers and WebAPI service  have project reference to Entities and knows about the DTO



    Monday, December 17, 2018 12:11 PM
  • using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc.Rendering;
    
    namespace ProgMgmntCore2UserIdentity.Models
    {
        public class ProjectViewModels
        {
            public class Project
            {
                public int ProjectId { get; set; }
    
                [Required(ErrorMessage = "Client Name is required")]
                [StringLength(50)]
                public string ClientName { get; set; }
    
                [Required(ErrorMessage = "Project Name is required")]
                [StringLength(50)]
                public string ProjectName { get; set; }
    
                [Required(ErrorMessage = "Technology is required")]
                [StringLength(50)]
                public string Technology { get; set; }
    
                [Required(ErrorMessage = "Project Type is required")]
                public string ProjectType { get; set; }
    
                [Required(ErrorMessage = "Start Date is required")]
                [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM-dd-yyyy}")]
                public DateTime? StartDate { get; set; }
    
                [Required(ErrorMessage = "End Date is required")]
                [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM-dd-yyyy}")]
                public DateTime? EndDate { get; set; }
    
                [Required(ErrorMessage = "Cost is required")]
                public decimal? Cost { get; set; }
    
                public List<SelectListItem> ProjectTypes { get; set; }
            }
           
            public List<Project> Projects { get; set; }
            
        }
    }

    using System;
    using System.Linq;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.ModelBinding;
    using ProgMgmntCore2UserIdentity.Models;
    
    namespace ProgMgmntCore2UserIdentity.Controllers
    {
        public class ProjectController : Controller
        {
            private readonly IProjectModel _projectModel;
            private readonly IModelHelper _modelHelper;
           
            public ProjectController(IProjectModel projectModel,   IModelHelper modelHelper)
            {
                _projectModel = projectModel;
                _modelHelper = modelHelper;
            }
    
            // GET: Project
            [Authorize]
            public ActionResult Index()
            {
                return View(_projectModel.GetProjectsByUserId(User.Identity.Name));
            }
    
            [Authorize]
            public ActionResult Details(int id = 0)
            {
                return id == 0 ? null : View(_projectModel.Edit(id));
            }
    
            [Authorize]
            public ActionResult Create()
            {
                return View(_projectModel.Create());
            }
    
            [Authorize]
            [HttpPost]
            public ActionResult Create(ProjectViewModels.Project project, string submit)
            {
                if (submit == "Cancel") return RedirectToAction("Index");
    
                ValidateddlProjectTypes();
    
                project.ProjectType = (Request.Form["ddlProjectTypes"]);
    
                if (ModelState.IsValid && _modelHelper.IsEndDateLessThanStartDate(project, "Project"))
                    ModelState.AddModelError(string.Empty, "End Date cannot be less than Start Date.");
    
                if (!ModelState.IsValid) return View(_projectModel.PopulateSelectedList(project));
    
                _projectModel.Create(project, User.Identity.Name);
                return RedirectToAction("Index");
            }
    
            [Authorize]
            public ActionResult Edit(int id = 0)
            {
                return id == 0 ? null : View(_projectModel.Edit(id));
            }
    
            [Authorize]
            [HttpPost]
            public ActionResult Edit(ProjectViewModels.Project project, string submit)
            {
                if (submit == "Cancel") return RedirectToAction("Index");
    
                if (ModelState.IsValid && _modelHelper.IsEndDateLessThanStartDate(project, "Project"))
                    ModelState.AddModelError(String.Empty, "End Date cannot be less than Start Date.");
    
                if (!ModelState.IsValid) return View(_projectModel.PopulateSelectedList(project));
    
                var theproject = new ProjectViewModels.Project();
    
                theproject = project;
    
                theproject.ProjectType = Request.Form["ProjectType"];
    
                _projectModel.Edit(theproject, User.Identity.Name);
                return RedirectToAction("Index");
            }
    
            public ActionResult Delete(int id = 0)
            {
                if (id > 0) _projectModel.Delete(id);
    
                return RedirectToAction("Index");
            }
       
            public ActionResult Cancel()
            {
                return RedirectToAction("Index", "Home");
            }
    
            public ActionResult UploadFile(int id)
            {
                return RedirectToAction("Index", "Upload", new { id = id, type = "PM" });
            }
    
            private void ValidateddlProjectTypes()
            {
                if (Request.Form["ddlProjectTypes"] == string.Empty)
                  return;
           
                foreach (var key in ModelState.Keys.ToList().Where(key => ModelState.ContainsKey(key)))
                {
                    if (key != "ProjectType") continue;
                    ModelState[key].Errors.Clear();
                    ModelState[key].ValidationState = ModelValidationState.Valid;
                }
            }
        }
    }

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Entities;
    using Microsoft.AspNetCore.Mvc.Rendering;
    using Microsoft.Extensions.Caching.Memory;
    using ProgMgmntCore2UserIdentity.WebApi;
    
    namespace ProgMgmntCore2UserIdentity.Models
    {
        public class ProjectModel : IProjectModel
        {
            private readonly IMemoryCache _memoryCache;
            private readonly IWebApi _webApi;
    
            public ProjectModel(IWebApi webApi, IMemoryCache memoryCache)
            {
                _memoryCache = memoryCache;
                _webApi = webApi;
            }
    
            public ProjectViewModels GetProjectsByUserId(string userid)
            {
                var vm = new ProjectViewModels {Projects = new List<ProjectViewModels.Project>()};
    
                var dtos = _webApi.GetProjsByUserIdApi(userid).ToList();
                
                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 responseDto = _webApi.GetProjByIdApi(id);
    
                var project = new ProjectViewModels.Project
                {
                    ProjectId = responseDto.ProjectId,
                    ClientName = responseDto.ClientName,
                    ProjectName = responseDto.ProjectName,
                    Technology = responseDto.Technology,
                    ProjectType = responseDto.ProjectType,
                    StartDate = responseDto.StartDate,
                    EndDate = responseDto.EndDate,
                    Cost = responseDto.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
                };
    
                _webApi.CreateProjectApi(dto);
            }
    
            public ProjectViewModels.Project Edit(int id)
            {
                var responseDto = _webApi.GetProjByIdApi(id);
    
                var project = new ProjectViewModels.Project
                {
                    ProjectId = responseDto.ProjectId,
                    ClientName = responseDto.ClientName,
                    ProjectName = responseDto.ProjectName,
                    Technology = responseDto.Technology,
                    ProjectType = responseDto.ProjectType,
                    StartDate = responseDto.StartDate,
                    EndDate = responseDto.EndDate,
                    Cost = responseDto.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
                };
    
                _webApi.UpdateProjectApi(dto); 
            }
    
            public void Delete(int id)
            {
                _webApi.DeleteProjectApi(new DtoId{Id = id});
            }
    
            public ProjectViewModels.Project PopulateSelectedList(ProjectViewModels.Project project)
            {
                bool isExist = _memoryCache.TryGetValue("DtoCache", out DtoCache dtocache);
    
                if (!isExist)
                {
                    dtocache = _webApi.GetCacheApi();
              
                    var cacheEntryOptions = new MemoryCacheEntryOptions()
                        .SetSlidingExpiration(TimeSpan.FromSeconds(30));
                    
                    _memoryCache.Set("DtoCache", dtocache, cacheEntryOptions);
                }
    
                project.ProjectTypes = new List<SelectListItem>();
    
                foreach (var pt in dtocache.ProjectTypes)
                {
                    var sli = new SelectListItem {Value = pt.Value, Text = pt.Text};
                    project.ProjectTypes.Add(sli);
                }
           
                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;
    using System.Collections.Generic;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Text;
    using Entities;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    
    namespace ProgMgmntCore2UserIdentity.WebApi
    {
        public class WebApi : IWebApi
        {
            #region ProjectApi
            
            public List<DtoProject> GetProjsByUserIdApi(string userid)
            {
                var dtoprojects = new List<DtoProject>();
    
                using (var client = new HttpClient())
                {
                    var uri = new Uri("http://progmgmntcore2api.com/api/project/GetProjsByUserId?userid=" + userid);
    
                    var response = client.GetAsync(uri).Result;
    
                    if (!response.IsSuccessStatusCode)
                        throw new Exception(response.ToString());
    
                    var responseContent = response.Content;
                    var responseString = responseContent.ReadAsStringAsync().Result;
    
                    dynamic projects = JArray.Parse(responseString) as JArray;
    
                    foreach (var obj in projects)
                    {
                        DtoProject dto = obj.ToObject<DtoProject>();
    
                        dtoprojects.Add(dto);
                    }
                }
    
                return dtoprojects;
            }
    
            public DtoProject GetProjByIdApi(int id)
            {
                DtoProject dto;
    
                using (var client = new HttpClient())
                {
                    var uri = new Uri("http://progmgmntcore2api.com/api/project/GetProjById?id=" + id);
                    HttpResponseMessage getResponseMessage = client.GetAsync(uri).Result;
    
                    if (!getResponseMessage.IsSuccessStatusCode)
                        throw new Exception(getResponseMessage.ToString());
    
                    var responsemessage = getResponseMessage.Content.ReadAsStringAsync().Result;
    
                    dynamic project = JsonConvert.DeserializeObject(responsemessage);
    
                    dto = project.ToObject<DtoProject>();
                }
    
                return dto;
            }
    
            public void CreateProjectApi(DtoProject dto)
            {
                using (var client = new HttpClient { BaseAddress = new Uri("http://progmgmntcore2api.com") })
                {
                    string serailizeddto = JsonConvert.SerializeObject(dto);
    
                    var inputMessage = new HttpRequestMessage
                    {
                        Content = new StringContent(serailizeddto, Encoding.UTF8, "application/json")
                    };
    
                    inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                    HttpResponseMessage message =
                        client.PostAsync("api/project/CreateProject", inputMessage.Content).Result;
    
                    if (!message.IsSuccessStatusCode)
                        throw new Exception(message.ToString());
                }
            }
    
            public void UpdateProjectApi(DtoProject dto)
            {
                using (var client = new HttpClient { BaseAddress = new Uri("http://progmgmntcore2api.com") })
                {
                    string serailizeddto = JsonConvert.SerializeObject(dto);
    
                    var inputMessage = new HttpRequestMessage
                    {
                        Content = new StringContent(serailizeddto, Encoding.UTF8, "application/json")
                    };
    
                    inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                    HttpResponseMessage message =
                        client.PostAsync("api/project/UpdateProject", inputMessage.Content).Result;
    
                    if (!message.IsSuccessStatusCode)
                        throw new Exception(message.ToString());
                }
            }
    
            public void DeleteProjectApi(DtoId dto)
            {
                using (var client = new HttpClient { BaseAddress = new Uri("http://progmgmntcore2api.com") })
                {
                    string serailizeddto = JsonConvert.SerializeObject(dto);
    
                    var inputMessage = new HttpRequestMessage
                    {
                        Content = new StringContent(serailizeddto, Encoding.UTF8, "application/json")
                    };
    
                    inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                    HttpResponseMessage message =
                        client.PostAsync("api/project/DeleteProject", inputMessage.Content).Result;
    
                    if (!message.IsSuccessStatusCode)
                        throw new Exception(message.ToString());
                }
            }
    
    }

    using System.Collections.Generic;
    using DAL;
    using Entities;
    using Microsoft.AspNetCore.Mvc;
    
    namespace ProgMgmntCore2Api.Controllers
    {
        [Produces("application/json")]
        [Route("api/[controller]")]
        [ApiController]
    
        public class ProjectController : ControllerBase, IProjectController
        {
            private readonly IDaoProject _daoProject;
    
            public ProjectController(IDaoProject daoProject)
            {
                _daoProject = daoProject;
            }
    
            [HttpGet]
            [Route("GetProjById")]
            public DtoProject GetProjectById(int id)
            {
                return  _daoProject.GetProjectById(id);
            }
            
            [HttpGet]
            [Route("GetProjsByUserId")]
            public List<DtoProject> GetProjectsByUserId(string userid)
            {
                return _daoProject.GetProjectsByUserId(userid);
            }
    
            [HttpPost]
            [Route("CreateProject")]
            public void Post_CreateProject(DtoProject dto)
            {
                _daoProject.CreateProject(dto);
            }
    
            [HttpPost]
            [Route("DeleteProject")]
            public void Post_DeleteProject(DtoId dto)
            {
                _daoProject.DeleteProject(dto.Id);
            }
    
            [HttpPost]
            [Route("UpdateProject")]
            public void Post_UpdateProject(DtoProject dto)
            {
                _daoProject.UpdateProject(dto);
            }
        }
    }
    

    using System.Collections.Generic;
    using System.Linq;
    using System.Transactions;
    using DAL.Models.DB;
    using Entities;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Options;
    
    namespace DAL
    {
        public class DaoProject :IDaoProject
        {
            private readonly IOptions<ConnectionStrings> _options;
            
            public DaoProject(IOptions<ConnectionStrings> options)
            {
                _options = options;
            }
    
            public DtoProject GetProjectById(int id)
            {
                var dto = new DtoProject();
    
                using (var context = new ProjectManagementContext(_options))
                {
                    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 ProjectManagementContext(_options))
                {
                    
                    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 ProjectManagementContext(_options))
                {
                    var project = new Projects
                    {
                        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 Projects();
                
                using (var context = new ProjectManagementContext(_options))
                {
                   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 ProjectManagementContext(_options))
                {
                    if (project == null) return;
                    dbcontext.Entry(project).State = EntityState.Modified;
                    dbcontext.SaveChanges();
                }
            }
    
            public void DeleteProject(int id)
            {
                Projects project;
    
                using (var context = new ProjectManagementContext(_options))
                {
                   project = (context.Projects.Where(a => a.ProjectId == id)).SingleOrDefault();
                }
    
                if (project == null) return;
    
                using (var newContext = new ProjectManagementContext(_options))
                {
                   
                    var tasks = new DaoTask(_options).GetTasksByProjectId(project.ProjectId);
                    using (TransactionScope scope = new TransactionScope())
                    {
                        foreach (var task in tasks)
                        {
                            new DaoTask(_options).DeleteTask(task.TaskId);
                        }
    
                        newContext.Entry(project).State = EntityState.Deleted;
                        newContext.SaveChanges();
    
                        scope.Complete();
                    }
                }
            }
        }
    }
    

    using System;
    
    namespace Entities
    {
        public class DtoProject
        {
            public int ProjectId { get; set; }
            public string ClientName { get; set; }
            public string ProjectName { get; set; }
            public string Technology { get; set; }
            public string ProjectType { get; set; }
            public string UserId { get; set; }
            public DateTime StartDate { get; set; }
            public DateTime EndDate { get; set; }
            public decimal Cost { get; set; }
        }
    }
    



    Monday, December 17, 2018 12:25 PM
  • BTW: You're Mosh, bro?

    BP-LP 2005/2016 @ll rights reserved

    Monday, December 17, 2018 12:25 PM

  • I am going to show you one more time with code in a subsequent post as to how the DAO with DTO pattern comes into play in an ASP.NET MVC solution that is using WebAPI the DTO and DAO pattern that is working with a single database table called Project as one element in a project tracking application. The DtoProject is kept in a classlib project called Entities and all the other tiers and WebAPI service  have project reference to Entities and knows about the DTO


    Can you make a project using the repository and DTOs, with at least 3 classes and simples examples. And upload, so I can study?

    It doesn't need to work, I just need to have a model that I can use as base

    BP-LP 2005/2016 @ll rights reserved

    Monday, December 17, 2018 12:29 PM
  • It is very nice to see when people learn new skills and techniques. 

    Don't limit yourself. At first, what you use is not repository pattern, it is DAO pattern.  DAO pattern is not bad access for smaller project or project when you needn't more complexity. 

    Don't limit yourself when you get data from database. Create update/insert/delete methods to work with table. It means these methods take object as you described as parameter. But select method can return some another object which can bring data what you need. When you need for one case object which is same as record you can return object which is parameter of update/delete/insert methods. In another case you can return object which brings text representation of animal category. So there will be more then one method for select and there can be join to tables which you need. 

    It means there can be difference between objects which go from data layer to layer above and objects which go from layer above to data layer. Application layer, or in smaller application it can be presenter/controller class, where mapping from/to data layer objects is. 

    I understood that I can create multiple select according the output I need.

    public class Book
        {
            public int Id { get; set; }
    
            public string Titulo { get; set; }
    
            public int NumeroDePaginas { get; set; }
    
            public int Tamanho { get; set; }
    
            public DateTime DataDePublicacao { get; set; }
    
            public int IdFormatoDoLivro { get; set; }
    
            public int IdIdiomaLivro { get; set; }
    
    
            //id, titulo, numeroDePaginas, tamanho, dataDePublicacao, idFormatoDoLivro, idIdiomaLivro
        }
    
    
    //method from the Book repository
     public List<Book> GetAll()
            {
                // Select
                List<Book> book;
    
     //as obvious this is the connection string
          using (var db = new MySqlConnection(StringDeConexao.Conexao()))            {
                    const string sql = @" SELECT id, titulo, numeroDePaginas, tamanho, dataDePublicacao, idFormatoDoLivro, idIdiomaLivro FROM Book;";
    
                    book= db.Query<Book>(sql, commandType: CommandType.Text).ToList();
                }
                return book;
            }

    PS: I've translate a few thing to English.

    So, idk why, but Dapper adds/is adding the info to all the properties to all my book list, but they have to have the same names as the columns on the query.

    My issue is, so in other to return a "personalized" object, I have to have the same properties on the list of object receiving the query.

    That's where I told I need something like a database view, because if I make a different select, I will need a list of objects containing the same properties.
    Or I will need to make something like this:

     public List<Author> GetAll(List<Author> authorStudent, List<Author> authorTeacher)
            {
                // Select
                var author = new List<Author>();
    
                foreach (var stu in authorStudent)
                {
                    author.Add(stu);
    
                }
                foreach (var tea in authorTeacher)
                {
                    author.Add(tea);
    
                }
    
                return author;
            }
    
    
            public List<Author> GetStudents()
            {
                // Select
                List<Author> author;
                using (var db = new MySqlConnection(StringDeConexao.Conexao()))
                {
                    const string sql = @"select  au.id, a.nomeCompleto, ca.categoria 
                    from aluno a ,autor au, categoriadoAutor ca,  alunoautor aa where aa.idAluno=a.id and
                    aa.idAutor=au.id and au.idCategoriaAutor=ca.id;";
    
                    author = db.Query<Author>(sql, commandType: CommandType.Text).ToList();
                }
                return author;
            }
    
    
    
            public List<Author> GetTeachers()
            {
                // Select
                List<Author> author;
                using (var db = new MySqlConnection(StringDeConexao.Conexao()))
                {
                    const string sql = @"select  au.id, p.nomeCompleto, ca.categoria from professor p ,
                autor au, categoriadoAutor ca,  professorautor pa where 
                pa.idProfessor=p.id and pa.idAutor=au.id and au.idCategoriaAutor=ca.id;";
    
                    author = db.Query<Author>(sql, commandType: CommandType.Text).ToList();
                }
                return author;
            }
    
    

    As you can see, there's two types of Authors, I get them both separately, then I ask them in the GetAll method to be able really get all. Can I try to do something similar or I need to create a third class in case the output is combine with other table



    BP-LP 2005/2016 @ll rights reserved

    Monday, December 17, 2018 12:31 PM
  • BTW: You're Mosh, bro?

    BP-LP 2005/2016 @ll rights reserved


    I don't know what that means.
    Monday, December 17, 2018 12:35 PM
  • BTW: You're Mosh, bro?


    BP-LP 2005/2016 @ll rights reserved


    I don't know what that means.

    So, I thought you were Mosh Hamedani because of "As I’ve explained in my YouTube video" part

    BP-LP 2005/2016 @ll rights reserved

    Monday, December 17, 2018 12:42 PM
  •  
     {
       }



    Can you send me the project?

    BP-LP 2005/2016 @ll rights reserved

    Monday, December 17, 2018 12:44 PM
  • BTW: You're Mosh, bro?


    BP-LP 2005/2016 @ll rights reserved


    I don't know what that means.


    So, I thought you were Mosh Hamedani because of "As I’ve explained in my YouTube video" part

    BP-LP 2005/2016 @ll rights reserved

    Nope I am just an old dog that has been in IT since 1971 and started with the Windows platform and VB COM in 1994 somewhere in there after moving off yhr IBM platform and mainframes COBOL and 360/370 Assembler.  I  went .NET around year 2001 and still going strong. 

    I am USA man USA red, white and blue, but I am a brown skinned minority and I identify with you. :) 


    • Edited by DA924x Monday, December 17, 2018 12:59 PM
    Monday, December 17, 2018 12:57 PM

  • I am going to show you one more time with code in a subsequent post as to how the DAO with DTO pattern comes into play in an ASP.NET MVC solution that is using WebAPI the DTO and DAO pattern that is working with a single database table called Project as one element in a project tracking application. The DtoProject is kept in a classlib project called Entities and all the other tiers and WebAPI service  have project reference to Entities and knows about the DTO


    Can you make a project using the repository and DTOs, with at least 3 classes and simples examples. And upload, so I can study?

    It doesn't need to work, I just need to have a model that I can use as base

    BP-LP 2005/2016 @ll rights reserved

    You are wrongly using the Repository pattern which is not a data persistence pattern. It is a domain/business object pattern that calls upon a mapping/data persistence layer in a DAL. You should abandon the repository pattern and use the DAO pattern in the DAL  I have given you a Java link explaining the usage of the DAO pattern. I have given you code on how to use the DTO and DAO patterns.

    The one part I left out is the IDAOProject that DAOProject implements.

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Entities;
    
    namespace DAL
    {
        public interface IDaoProject
        {
            DtoProject GetProjectById(int id);
            List<DtoProject> GetProjectsByUserId(string userid);
            void CreateProject(DtoProject dto);
            void UpdateProject(DtoProject dto);
            void DeleteProject(int id);
        }
    }


    • Edited by DA924x Monday, December 17, 2018 1:13 PM
    Monday, December 17, 2018 1:12 PM
  • I am a brown skinned minority and I identify with you. :) 


    Me2.
    Sorry, asking this again and again...Bro can you please send me the project, I will understand it better on the IDE

    BP-LP 2005/2016 @ll rights reserved

    Monday, December 17, 2018 1:12 PM
  • I'll look into doing something  on GitHub, but later in the day. I just moved into a new home this past Tuesday and I am  still unpacking.

    Monday, December 17, 2018 1:25 PM
  • I will wait.

    BP-LP 2005/2016 @ll rights reserved

    Monday, December 17, 2018 1:33 PM

  • You are wrongly using the Repository pattern which is not a data persistence pattern. It is a domain/business object pattern that calls upon a mapping/data persistence layer in a DAL. You should abandon the repository pattern and use the DAO pattern in the DAL  I have given you a Java link explaining the usage of the DAO pattern. I have given you code on how to use the DTO and DAO patterns.

    The one part I left out is the IDAOProject that DAOProject implements.

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Entities;
    
    namespace DAL
    {
        public interface IDaoProject
        {
            DtoProject GetProjectById(int id);
            List<DtoProject> GetProjectsByUserId(string userid);
            void CreateProject(DtoProject dto);
            void UpdateProject(DtoProject dto);
            void DeleteProject(int id);
        }
    }


    I'm working on naming the project, I understood that I'm using the wrong name, naming as repositories, but they are DTOs in fact. So is like this:
    Repository to DTO

    Is okay? Or should the interface be named as IDAOProfessor and same for the class t?


    BP-LP 2005/2016 @ll rights reserved

    Tuesday, December 18, 2018 8:27 AM
  • DTO is only POCO object. It is only container with properties without some logic. There might not be interface.

    DAO is pattern which create something like gateway to database tables. There are methods Get/Update/Insert/Delete. There could be interface. 

    Tuesday, December 18, 2018 8:58 AM
  • DTO is only POCO object. It is only container with properties without some logic. There might not be interface.

    DAO is pattern which create something like gateway to database tables. There are methods Get/Update/Insert/Delete. There could be interface. 

    DTOs are POCO, got it :) 
    DTOs are also different than the Models?

    BP-LP 2005/2016 @ll rights reserved


    Tuesday, December 18, 2018 9:01 AM
  • I'm working on naming the project, I understood that I'm using the wrong name, naming as repositories, but they are DTOs in fact. So is like this:
    Repository to DTO

    Is okay? Or should the interface be named as IDAOProfessor and same for the class t?

    No it is not OK. The Repository object becomes a DAO a Data Access Object. There is no Repository classlib project anymore.  

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

    You create a classlib project name DataAccessLayer or DAL. You create the DAO and its interface in the DAL the DAO works in the DAL,  and the DAO uses the DTO pattern of a single DTO or a DTO(s) in a collection to do CRUD with the underlying DB technology.

    You can clearly see the DAO pattern being used in the Java tutorial.

    https://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm

    Student is a DTO being acted  upon by DaoStudent, which is a 1 to 1 relationship  to a Student database table with columns on the table and properties in the Student class.

    My example code I have presented of  the DAL using the DAO and DTO patterns in using EF. The  DAO is using the DTO for CRUD using EF  with EF working with the underlaying database technology.

    This is clearly being shown how it works.

    The code I have presented ,  the MVC Projectcontroller is going to call the ProjectModel object's methods in the ASP.NET MVC project, the presentation layer to eventual do CRUD based on user interaction at the views/

    The Projectmodel object calls the WebAPI object methods with the WebAPI object being part of the ASP.NET MVC project, and the WebAPI object being in the presentation layer acting as tunnel between the  ASP.NET MVC presentation layer, and the actual ASP.NET WebAPI service project.

    The ASP.NET WebAPI has project reference to the DAL project that is sitting behind the ASP.NET WebAPI project.

     The DAOproject in the DAL is doing CRUD using the DTOProject  (DTO is data carrier) with the Project object, the persistence object  that EF is using, and EF is doing CRUD with the underlaying database technology for the MS SQL Server database tabled called Projects..

    In it's most simplistic form, that is what is happening. You should be able to follow the code and come up with your own implementation of how to use a DAL using the DAO and DTO pattern and passing the DTO(s) through the layers with each layer acting upon or using the DTO as it is in a given layer. 

     


    Tuesday, December 18, 2018 9:27 AM

  • In it's most simplistic form, that is what is happening. You should be able to follow the code and come up with your own implementation of how to use a DAL using the DAO and DTO pattern and passing the DTO(s) through the layers with each layer acting upon or using the DTO as it is in a given layer. 

     


    My project is has the same implementation as https://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm


    You create a classlib project name DataAccessLayer or DAL

    I already have it :)

    You create the DAO and its interface in the DAL

    Already too.

    the DAO works in the DAL,  and the DAO uses the DTO pattern of a single DTO or a DTO(s) in a collection to do CRUD with the underlying DB technology. 

    That's what is happening :)



    My DTOs do as is written here. 

    Now some pictures:

    DAL lib projectDAL interfacesDAL Classes 1:1 with the DBData Access Objects, implementing the interface

    From the right to the left.
    1st -The DAL lib project
    2nd -The DAL interfaces

    3rd - The Dao Classes 1:1 with the DB tables

    4th -The Data Access Objects

    My problem now is the naming. My project does what it need to be done, but now I need to name and organize the right way.
    I already had all that, I just didn't have in doing what it should (now fixed) and named correctly (unfixed) 


    BP-LP 2005/2016 @ll rights reserved


    Tuesday, December 18, 2018 10:13 AM
  • DTO(s) are just simple classes that carry data. How can a DTO have an IDTO, an interface? DTO(s) don't have interfaces.

    Do you see an IDTO being used anywhere in the DTO tutorial?

    https://www.codeproject.com/Articles/1050468/Data-Transfer-Object-Design-Pattern-in-Csharp

    Where are any classes that are designated as a DAO that should be prefixed with DAO that implements an IDAO interface. The DAO has the CRUD methods in them.

    My DAL code, if you are actually looking at the code,  with the DAOproject and DAOproject implementing IDAOproject  is clearly being shown in a previous post,

    The DTOProject  in the Entities classlib project is clearly being shown.

    Just by looking at the namespaces the classes are in that represent that they are in their respective classlib projects,  you should be able to clearly understand naming conventions and what and what should not be implementing an Interface and what project they are in.

     You should look at the code I have presented and follow the pattern of usage concerning how the DAL is using the DAO and DTO objects in the DAL.

    Tuesday, December 18, 2018 11:03 AM
  • DTO(s) are just simple classes that carry data. How can a DTO have an IDTO, an interface? DTO(s) don't have interfaces.


    Where are any classes that are designated as a DAO that should be prefixed with DAO that implements an IDAO interface. The DAO has the CRUD methods in them.


    Just by looking at the namespaces the classes are in that represent that they are in their respective classlib projects,  you should be able to clearly understand naming conventions and what and what should not be implementing an Interface and what project they are in.

     You should look at the code I have presented and follow the pattern of usage concerning how the DAL is using the DAO and DTO objects in the DAL.

    I read your code.
    Since there's no IDaoProject, IProjectController, DtoId, and other things that I didn't find out
    I just start inventing (extract the interface to be specific) things out. I probably missed a few things and I got on the wrong path while I was trying things on my own.
    PS: I didn't wanted to create a new ASP:NET, so I was making it "console possible"

    But I think I got it. 
    My DTO, keep being the POCO as they are, my Business Objects (the one that says EntidadesDaTabela)... Well I don't know what do with them for now. I need to rename the IDTO->IDAO
    Then I must create a DAO class and they implement the IDAO interfaces.

    am I in the right path now?



    BP-LP 2005/2016 @ll rights reserved

    Tuesday, December 18, 2018 11:52 AM
  • Since there's no IDaoProject, IProjectController, DtoId, and other things that I didn't find out

    Other than IDoaProject that DAOProject implements and is an Interface that has posted in this thread,  the Interface, the rest of what you are talking about is not paramount in you understanding about how to use the DAO and DTO patterns in the DAL. The Interface for DAOProject has been posted in this thread in a separate post. 

    I just start inventing (extract the interface to be specific) things out. I probably missed a few things and I got on the wrong path while I was trying things on my own.

    I'll agree that you went off course.

    My DTO, keep being the POCO as they are, my Business Objects (the one that says EntidadesDaTabela)... Well I don't know what do with them for now. I need to rename the IDTO->IDAO
    Then I must create a DAO class and they implement the IDAO interfaces.

    The DTO should be used throughout the layers, and by simply creating a classlib project called Entitles and putting the DTO classes in the Entities project, all of your other projects can set project reference to Entities and know what the DTO(s) are about.  You see 'using Entities' at the top of all classes in the code I have presented that is referencing the DTO(s) in the Entities project.

    am I in the right path now?

    I am not sure.

     

    Tuesday, December 18, 2018 2:44 PM

  • The DTO should be used throughout the layers, and by simply creating a classlib project called Entitles and putting the DTO classes in the Entities project, all of your other projects can set project reference to Entities and know what the DTO(s) are about.  You see 'using Entities' at the top of all classes in the code I have presented that is referencing the DTO(s) in the Entities project.

     

     

    I think I got it now :) 

    IDAO interface and DAO ClassNew Lib project
    DTOs on a new Lib project, I will rename it soonOne using and the other on the namespace

    Got them :) 


    Why I have to split into another project Entities from DAL, since the Entities are DTOs, they aren't part of Data Access Layer?

    And I have the table as classes on the project, and I'm not referencing them, only the DTOs. should I remove and let only the DTOs or I probably gonna need them later on something that I'm missing?


    BP-LP 2005/2016 @ll rights reserved


    Tuesday, December 18, 2018 3:45 PM
  • I hope you don't mind if I jump in here ...

    >>Why I have to split into another project Entities from DAL, since the Entities are DTOs, they aren't part of Data Access Layer?

     And I have the table as classes on the project, and I'm not referencing them, only the DTOs. should I remove and let only the DTOs or I probably gonna need them later on something that I'm missing?<<
     
    You should always have a separate project/DLL for DTOs (an Entities project, as @DA calls them in his example, you can call it whatever you like). The reason for this is that DTOs get passed around between layers (projects/DLLs) and so they need to be available to all the other layers (simply by referencing the project in those other layer projects). Therefore, they need to be in their own separate project.


    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Tuesday, December 18, 2018 4:06 PM
    Moderator
  • I hope you don't mind if I jump in here ...

     

    You should always have a separate project/DLL for DTOs (an Entities project, as @DA calls them in his example, you can call it whatever you like). The reason for this is that DTOs get passed around between layers (projects/DLLs) and so they need to be available to all the other layers (simply by referencing the project in those other layer projects). Therefore, they need to be in their own separate project.


    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Thanks for jumping in. I got it.
    And what about the table that I map into classes that I have and I don't use, am I going to need them on something I don't know yet?

    I was planning to make Code First, but I fail, so I use them as my business objects, but I don't have any reference on them.

     


    BP-LP 2005/2016 @ll rights reserved

    Tuesday, December 18, 2018 4:16 PM
  • And what about the table that I map into classes that I have and I don't use, am I going to need them on something I don't know yet?

    I was planning to make Code First, but I fail, so I use them as my business objects, but I don't have any reference on them.

    Hmmm … not sure what you mean.

    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Tuesday, December 18, 2018 4:38 PM
    Moderator
  • I hope you don't mind if I jump in here ...

     

    You should always have a separate project/DLL for DTOs (an Entities project, as @DA calls them in his example, you can call it whatever you like). The reason for this is that DTOs get passed around between layers (projects/DLLs) and so they need to be available to all the other layers (simply by referencing the project in those other layer projects). Therefore, they need to be in their own separate project.


    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Thanks for jumping in. I got it.
    And what about the table that I map into classes that I have and I don't use, am I going to need them on something I don't know yet?

    I was planning to make Code First, but I fail, so I use them as my business objects, but I don't have any reference on them.

     


    BP-LP 2005/2016 @ll rights reserved

    Bonnie finally got through to you about the DTO(s) and how they are passed through the layers,  and all projects need to know about them by using a classlib project to hold the DTOs(s) with all other projects referencing that classlib project. I guess you view anything that the DTO(s) were derived from as something you don't  pass through the layers. If you are  talking about a ADO.NET datatable, then why are you even using them when you are using the DTO pattern? 
    Tuesday, December 18, 2018 5:24 PM
  • Bonnie finally got through to you about the DTO(s) and how they are passed through the layers,  and all projects need to know about them by using a classlib project to hold the DTOs(s) with all other projects referencing that classlib project. I guess you view anything that the DTO(s) were derived from as something you don't  pass through the layers. If you are  talking about a ADO.NET datatable, then why are you even using them when you are using the DTO pattern? 
    Oh, was he talking about an ADO.NET DataTable? If so, DataSets/DataTables can be treated as DTOs. I do that all the time. After all, a DataSet/DataTable is just a class.  It's just semantics. ;0)

    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com


    Tuesday, December 18, 2018 6:58 PM
    Moderator
  • Bonnie finally got through to you about the DTO(s) and how they are passed through the layers,  and all projects need to know about them by using a classlib project to hold the DTOs(s) with all other projects referencing that classlib project. I guess you view anything that the DTO(s) were derived from as something you don't  pass through the layers. If you are  talking about a ADO.NET datatable, then why are you even using them when you are using the DTO pattern? 

    Oh, was he talking about an ADO.NET DataTable? If so, DataSets/DataTables can be treated as DTOs. I do that all the time. After all, a DataSet/DataTable is just a class.  It's just semantics. ;0)

    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com


    Of course you can use a datatable in a DTO capacity. But myself, I wouldn't touch a datatable with a ten foot pole under any circumstances.  I think if a datatable is being used,  then it may be used in some kind of CRUD scenario due to the OP doesn't know how to use an ADO.NET datareader with DTO(s) and the OP may not  know how to use parameterized T-SQL or stored procedure with using the DTO(s) in CRUD operations.
    Tuesday, December 18, 2018 8:53 PM
  • Hi Belarmino Vic,

    Thank you for posting here.

    What is the type of your project?

    If your question is more related to asp.net, please post in the following forum.

    https://forums.asp.net/

    Best regards,

    Jack J Jun.


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, December 19, 2018 1:43 AM
    Moderator
  • Hi Belarmino Vic,

    Thank you for posting here.

    What is the type of your project?

    If your question is more related to asp.net, please post in the following forum.

    https://forums.asp.net/

    Best regards,

    Jack J Jun.


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Just becuase the OP is talking about architectural styles and design patterns does it imply that ASP.NET is being used, which can be applied to desktop solutions too.

    Wednesday, December 19, 2018 5:12 AM
  • Why I have to split into another project Entities from DAL, since the Entities are DTOs, they aren't part of Data Access Layer?

    The presentation layer, the business logic layer and the data access layer needed to know about the DTO(s) as they pass through the layers or tiers. 

    So what are you going to do? Are you going to go to each layer or tier  and make the DTO(s)? That seems like a lot of work. And what if you have to make changes to one or more DTO(s), which would result in you making  changes to all the DTO(s) in each layer or tier? Again that's a lot of work.

    On the other hand, if you create the classlib project I called Entities, put the DTO(s) there, have all layer or tier projects set reference to Entities, then there is only on spot where you will need to make a change to a DTO or add a new DTO that all layers or tiers will see and know about it.

    If you are using a presentation layer no matter if it's  a Web form, Windows form, WPF form, etc. and etc., then no ORM object on the virtual object model makes it to the controls in the presentation layer. 

    It doesn't matter if you are using one of the UI design patterns too  such as MVC, MVP or MVVM, the ORM objects never make it to the UI controls , but rather the DTO(s) make there  and  are used.

    https://juristr.com/blog/2012/10/lessions-learned-dont-expose-ef-entities-to-the-client-directly/

    Wednesday, December 19, 2018 10:42 AM
  • I think … :) DTO is not necessary for each layer. I use layers as follow:

    1) UI (MVP/MVC/MVVM). There are not DTO objects. Only models which are used by controller/view, … In controller/presenter I have mappers to transform DTO from application layer to model entities.

    2) Application layer. There are DTO objects used for input/output data in/to system. These are defined by contracts with another layer (UI) or another system. I don't return or accept data out of these contracts. Application layer has mappers to transform another object to DTO.

    3) Data layer. This layer doesn't have DTO. There are two object types which are returned. 

    a) Data entity (for example something like row) is exposed to application layer. It is used for simple manipulation of data when I want to expose data from database directly without any business rule to apply.

    b) Business entity. This entity is defined by contract in business layer. Business entity is required by application layer and application layer call actions on this entity to apply business rules. 

    It can be done because data layer depends on (has reference to) business layer and not vice versa. So business layer defines entities and functionality which data layer musts implement. There is not necessary to create DTO in data layer because some of transformation from DTO to business entity is need in application layer. Instead of it I expose business entity directly from data layer when contract is not established.

    In some cases I implement extension methods of data layer object (repository, DAO) in application layer to directly mapping from data entity to DTO which is went from system and vice versa. It is better solution than expose data entities from data layer. 

    So there is application layer only who has DTO objects. It is because application layer is gateway to system and it is necessary to define system inputs and outputs. Another layers (business, data) are inside system and cannot be accessible directly from outside of system. When business layer defines business entity and data layer depends on business then data layer can return business entities directly because these object don't make sense without business layer. 

    There could be reason to return DTO from data layer which are consumed by application layer without business rules. But it could be solved by extension methods of data layer in application layer and these methods can return DTO directly.

    I will try to write some example what I mean exactly. 

    Wednesday, December 19, 2018 12:06 PM
  • https://social.msdn.microsoft.com/Forums/en-US/home?forum=adodotnetentityframework

    Maybe, the post will help you with the MySQL issue and using EF DB first, a more recent post wit possible solution was made to the thread.


    • Edited by DA924x Thursday, December 20, 2018 4:12 PM
    Thursday, December 20, 2018 4:12 PM
  • I prepare some example how it can works. Example is large to post here so I got it in my github.

    https://github.com/petrberek/MSDNForum/tree/master/81f98c94-1327-406f-b6eb-1f0d424814ca

    There are fourth project. SchoolSystemApp is windows forms application which only takes data from application layer and show it to user by some forms.

    ApplicationLayer is application layer which is only facade to system. You can see there is interface which is used to define application use cases. This layer can execute business action on business entity or can return data directly from data layer by data layer extension methods. You can see there are DTO objects which go out of system. When there will be object which goes into system, validation of this object is in this layer.

    Business layer defines business entity which has method with business rules. In this case there is only rule to verify student results to check student can go to next class. Business layer defines contract to data layer (you can find it as infrastructure layer). 

    Data layer implements contracts from business layer only. There is not full DAO pattern. There are methods which are defined by contracts only. Save full student detail can be implemented in application layer as data layer extension method when there is no business rule when it is saving. So Save method in data layer takes business entity as parameter.

    For everyone: I decided to start implement some larger examples from this forum to show what I mean when I describe something by word. Code can be better than thousands of words. If you see there is some mistakes in my code, please be contributor to do better examples for this forum. Thank you.


    • Edited by Petr B Wednesday, December 26, 2018 1:23 PM
    Wednesday, December 26, 2018 1:13 PM
  • I prepare some example how it can works. Example is large to post here so I got it in my github.

    https://github.com/petrberek/MSDNForum/tree/master/81f98c94-1327-406f-b6eb-1f0d424814ca


    For everyone: I decided to start implement some larger examples from this forum to show what I mean when I describe something by word. Code can be better than thousands of words. If you see there is some mistakes in my code, please be contributor to do better examples for this forum. Thank you.


    Thanks.
    BTW: This name "81f98c94-1327-406f-b6eb-1f0d424814ca" is quite explanatory lol .


    BP-LP 2005/2016 @ll rights reserved

    Thursday, December 27, 2018 8:09 AM
  • This is guid in url of this topic. So it could be in relation with this topic. In commit note there is name of this topic. I don't know another way how to identify topic. By name it could be very hard. Maybe there can be md file with description. 
    Thursday, December 27, 2018 8:37 AM