可以改进这种MVC中代码分离的方法吗?

时间:2015-04-26 08:38:05

标签: c# asp.net asp.net-mvc entity-framework

首先,我不是专业程序员,我只是在学习C#,MVC和Web开发。

我在这里描述的大部分内容都是自学成才,来自Stack Overflow上的大量Google搜索和帖子。我采用了Mike Brind's recent blog post

中概述的方法

问题: 你们中有些人比我更有经验地批判性地看待我的方法,让我知道我能做出更好的方法或改进吗?我不能帮助,但认为有更好的方法来实现服务层,因为似乎有很多复制的代码。

My Code Snippets

VehicleWorksRequest模型

我从反映数据库中包含的实体的模型开始。

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Web;

namespace ATAS.Models
{
    public class VehicleWorkRequest : IControllerHooks
    {
        [Key]
        public int RequestId { get; set; }
        public bool Closed { get; set; }
        public bool Critical { get; set; }
        [Display(Name = "Fleet number")]
        public int? VehicleId { get; set; }
        [Display(Name = "Odometer Reading")]
        public int? OdometerReadingId { get; set; }
        [Display(Name = "Report Date")]
        public DateTime? DateReported { get; set; }
        [Display(Name = "Person reporting")]
        public int ReportingEmployeeId { get; set; }           
        [StringLength(255)]
        public string Request { get; set; }
        [StringLength(255)]
        public string Comment { get; set; }
        // don't update the database context with posted-back data 
        [PersistPropertyOnEdit(false)]
        // don't show the CreatedDate on any of the views 
        [ScaffoldColumn(false)]
        public DateTime? CreatedDate { get; set; }
        [Editable(false)]
        [DisplayOnEditView(true)]
        [DataType(DataType.Date)]
        public DateTime? ModifiedDate { get; set; }
        [Editable(false)]
        [DisplayOnEditView(true)]
        public string LastModifiedBy { get; set; }
        [ForeignKey("ReportingEmployeeId")]
        public virtual Employee ReportingEmployee { get; set; }
        public void OnCreate()
        {
            CreatedDate = DateTime.UtcNow;
            ModifiedDate = CreatedDate;
            LastModifiedBy = HttpContext.Current.User.Identity.Name;
            Closed = false;
            Critical = false;
        }
        public void OnEdit()
        {
            ModifiedDate = DateTime.UtcNow;
            LastModifiedBy = HttpContext.Current.User.Identity.Name;
        }
    }
}

查看主页视图模型 我理解的视图模型,正如Mike指出的那样,它充当视图数据的容器。 我的主页视图(实际上是一个仪表板)包含在VehicleWorkRequest数据库表中保存的几条信息

  • 所有重要工作请求的列表
  • 所有日常工作要求的清单
  • 所有已完成工作请求的列表
  • 其他一些显示工作要求等的措施。

虽然我知道可以将工作请求集合传递给视图,然后在那里过滤各种类别的工作请求(Critical,Routine和Completed),但是从我从Mikes发布的内容中读到并理解建议的方法是将这种逻辑保留在视图之外,这就是它在视图模型中完成的原因。

我认为这可能是一个我可以改进的地方,因为所有的工作请求列表都根据其重要性和开放性来提供相同的信息,只是它的不同子集。

using System.Collections.Generic;

namespace ATAS.Models.ViewModels
    {
    public class HomeViewModel
        {
        public List<Vehicle> Vehicles { get; set; }
        public int VehicleCount { get; set; }
        public List<VehicleWorkRequest> VehicleWorkRequests { get; set; }
        public List<VehicleWorkRequest> VehicleCriticalWorkRequests { get; set; }
        public List<VehicleWorkRequest> VehicleRoutineWorkRequests { get; set; }
        public List<VehicleWorkRequest> VehicleCompletedWorkRequests { get; set; }
        public int VehicleWorkRequestCount { get; set; }

        }
    }

服务层 它负责与我的数据访问层(EF)交谈并将数据传递给控制器​​,以便它可以将其传递给视图。它最终也将接受来自我的控制器的数据并用它做任何需要的事情。 我无法帮助,但我认为我可以更好地重构,因为似乎我有很多重复的代码和数据库请求,基本上相同的信息。

using ATAS.Data;
using ATAS.Models;
using System.Collections.Generic;
using System.Linq;

namespace ATAS.Services
{

    public class VehicleService : IVehicleService
    {
        public List<Vehicle> GetVehicles()
        {
            using (DataManager db = new DataManager())
            {

                var ActiveVehicles = from v in db.Vehicles
                                     where v.Active == true
                                     orderby v.FleetNumber ascending
                                     select v;

               return ActiveVehicles.ToList();
            }
        }

    public Vehicle GetVehicle(int id)
        {
            using (DataManager db = new DataManager())
            {
                return db.Vehicles.Find(id);
            }
        }

    public List<VehicleWorkRequest> GetAllVehiclesWorkRequests()
        {
            using (DataManager db = new DataManager())
            {

                var Requests = from vwr in db.VehicleWorkRequest
                               where vwr.Closed == false
                               orderby vwr.DateReported ascending
                               select vwr;

                return Requests.ToList();
            }
        }

    public List<VehicleWorkRequest> GetAllVehiclesCriticalWorkRequests()
        {
            using (DataManager db = new DataManager())
            {

                var Requests = from vwr in db.VehicleWorkRequest
                               where vwr.Closed == false && vwr.Critical == true 
                               orderby vwr.DateReported ascending
                               select vwr;

                return Requests.ToList();
            }
        }

    public List<VehicleWorkRequest> GetAllVehiclesRoutineWorkRequests()
        {
            using (DataManager db = new DataManager())
            {

                var Requests = from vwr in db.VehicleWorkRequest
                               where vwr.Closed == false && vwr.Critical == false

                               orderby vwr.DateReported ascending
                               select vwr;

                return Requests.ToList();
            }
        }

     public List<VehicleWorkRequest> GetAllVehiclesCompletedWorkRequests()
        {
            using (DataManager db = new DataManager())
            {

                var Requests = from vwr in db.VehicleWorkRequest
                               where vwr.Closed == true
                               orderby vwr.DateReported ascending
                               select vwr;

                return Requests.ToList();
            }
        }

    public VehicleWorkRequest GetIndividualVehiclesWorkRequests(int id)
        {
            using (DataManager db = new DataManager())
            {
                return db.VehicleWorkRequest.Find(id);
            }
        }
    }
}

服务层接口 为了促进代码分离,我创建了一个服务层接口。

using ATAS.Models;
using System.Collections.Generic;
namespace ATAS.Services
{
public interface IVehicleService
    {
    List<Vehicle> GetVehicles();
    Vehicle GetVehicle(int id);
    VehicleWorkRequest GetIndividualVehiclesWorkRequests(int id);
    List<VehicleWorkRequest> GetAllVehiclesWorkRequests();
    List<VehicleWorkRequest> GetAllVehiclesCriticalWorkRequests();
    List<VehicleWorkRequest> GetAllVehiclesRoutineWorkRequests();
    List<VehicleWorkRequest> GetAllVehiclesCompletedWorkRequests();
    }
}

最后是控制器 索引操作的第一个任务是实例化HomeViewModel。视图模型的数据由服务接口提供,服务接口又使用服务层中的类与数据访问层进行交互。

using System.Web.Mvc;
using ATAS.Data; 
using ATAS.Models.ViewModels;
using ATAS.Services;
namespace ATAS.Controllers
{
[Authorize]
public class HomeController : Controller
    {
    private DataManager db = new DataManager();

    // GET: home/index
    public ActionResult Index()
    {
        IVehicleService service = new VehicleService();
        HomeViewModel Model = new HomeViewModel
            {
                Vehicles = service.GetVehicles(),
                VehicleCount = service.GetVehicles().Count,
                VehicleWorkRequestCount = service.GetAllVehiclesWorkRequests().Count,
                VehicleWorkRequests = service.GetAllVehiclesWorkRequests(),
                VehicleCriticalWorkRequests = service.GetAllVehiclesCriticalWorkRequests(),
                VehicleRoutineWorkRequests = service.GetAllVehiclesRoutineWorkRequests(),
                VehicleCompletedWorkRequests = service.GetAllVehiclesCompletedWorkRequests()
            };
        return View(Model);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

您可以编写一个通用方法,通过将Expression<Func>作为搜索参数发送到GetVehicle方法来获取数据以减少重复。

public IEnumerable<Vehicle> GetVehicles(Expression<Func<Vehicle, bool>> predicate = null)
{
    using (DataManager db = new DataManager())
    {
        if (predicate == null)
            return db.Vehicles.ToList();

        var vehicles = db.Vehicles.Where(predicate).ToList();
        return vehicles;
    }
}

public ActionResult Index()
{
    IVehicleService service = new VehicleService();
    var allVehicles = service.GetVehicles();
    var vehicleWorkRequest = service.GetVehicles(v => v.Closed == false);
    var vehicleCriticalWorkRequests = service.GetVehicles(v => v.Closed == false && v.Critical == true).OrderByDescending(v => v.DateReported);
    var vehicleRoutineWorkRequests= service.GetVehicles(v => v.Closed == false && v.Critical == false).OrderByDescending(v => v.DateReported);
    var vehicleCompletedWorkRequests = service.GetVehicles(v => v.Closed == true).OrderByDescending(v => v.DateReported);

    var Model = new HomeViewModel
        {
            Vehicles = allVehicles,
            VehicleCount = allVehicles.Count(),
            VehicleWorkRequestCount = vehicleWorkRequest.Count(),
            VehicleWorkRequests = vehicleWorkRequest,
            VehicleCriticalWorkRequests = ehicleCriticalWorkRequests,
            VehicleRoutineWorkRequests = vehicleRoutineWorkRequests,
            VehicleCompletedWorkRequests = vehicleCompletedWorkRequests
        };
    return View(Model);
    }
}

您还可以将其设置为异步以获得更好的性能:

public async Task<IEnumerable<Vehicle>> GetVehiclesAsync(Expression<Func<Vehicle, bool>> predicate = null)
{
    using (DataManager db = new DataManager())
    {
        if (predicate == null)
            return await db.Vehicles.ToListAsync();

        return await db.Vehicles.Where(predicate).ToListAsync();
    }
}


public async Task<ActionResult> Index()
{
    IVehicleService service = new VehicleService();
    var allVehicles = await service.GetVehiclesAsync();
    var vehicleWorkRequest = await service.GetVehiclesAsync(v => v.Closed == false);
    var vehicleCriticalWorkRequests = await service.GetVehiclesAsync(v => v.Closed == false && v.Critical == true).OrderByDescending(v => v.DateReported);
    var vehicleRoutineWorkRequests= await service.GetVehiclesAsync(v => v.Closed == false && v.Critical == false).OrderByDescending(v => v.DateReported);
    var vehicleCompletedWorkRequests = await service.GetVehiclesAsync(v => v.Closed == true).OrderByDescending(v => v.DateReported);

    var Model = new HomeViewModel
        {
            Vehicles = allVehicles,
            VehicleCount = allVehicles.Count(),
            VehicleWorkRequestCount = vehicleWorkRequest.Count(),
            VehicleWorkRequests = vehicleWorkRequest,
            VehicleCriticalWorkRequests = ehicleCriticalWorkRequests,
            VehicleRoutineWorkRequests = vehicleRoutineWorkRequests,
            VehicleCompletedWorkRequests = vehicleCompletedWorkRequests
        };
    return View(Model);
    }
}