帮助提高(重构)我的code。 Automapper - EF - asp.net MVC-3 [英] Help improving (refactoring) my code. Automapper - EF - asp.net mvc-3

查看:160
本文介绍了帮助提高(重构)我的code。 Automapper - EF - asp.net MVC-3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的4款车型 - 2域模型和2的DTO

I have this 4 models - 2 Domain Models and 2 DTOs

public class Project
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public virtual ICollection<Task> Tasks { get; set; }
    }

    public class Task
    {
        public int ID { get; set; }
        public virtual int ProjectID { get; set; }
        public string Name { get; set; }
        public virtual Project Project { get; set; }
    }

    public class ProjectDTO
    {
        [Required]
        public string Name { get; set; }
        public List<TaskDTO> Tasks { get; set; }
    }

    public class TaskDTO
    {
        [Required]
        public string Name { get; set; }
        public int ID { get; set; }
        public bool MarkRemove { get; set; }
    }

我的继承人automapper配置

Heres my automapper configuration

Mapper.CreateMap<Project, ProjectDTO>();
Mapper.CreateMap<ProjectDTO, Project>().ForMember(p =>p.ID, opt=>opt.Ignore()).ForMember(p=>p.Tasks, opt=>opt.Ignore());
Mapper.CreateMap<Task, TaskDTO>();
Mapper.CreateMap<TaskDTO, Task>().ForMember(task=>task.ProjectID, opt=>opt.Ignore()).ForMember(task=>task.Project, opt=>opt.Ignore());

我的继承人HttpPost Edit操作

Heres my HttpPost Edit action

[HttpPost]
        public ActionResult Edit(int id, ProjectDTO p)
        {
            if (ModelState.IsValid)
            {
                var dbProject = db.Projects.Where(pr => pr.ID == id).Single();
                Mapper.Map(p, dbProject);
                foreach (var task in p.Tasks)
                {
                    Task dbTask;
                    try
                    {
                        dbTask = dbProject.Tasks.Where(t => t.ID == task.ID).Single();
                    }
                    catch
                    {
                        dbTask = new Task();
                        Mapper.Map(task, dbTask);
                        dbProject.Tasks.Add(dbTask);
                    }
                    if (task.MarkRemove)
                    {
                        db.Tasks.Remove(dbTask);
                    }
                    else {
                        Mapper.Map(task, dbTask);                    
                    }                  
                }
                db.Entry(dbProject).State = EntityState.Modified;
                db.SaveChanges();                
                TempData["Success"] = "Modelo Valido";
                return RedirectToAction("Index");
            }
            return View(p);
        }

我不是完全满意的,但我不认为有是处理更清洁的方式这个有点复杂的场景......

Im not completely happy with this but I dont think there is a much cleaner approach to handling this somewhat complex scenario....

现在,它是工作,我想至少重构这个使用存储库模式或东西的方式,控制器动作是不是令人费解..这最终将生产code:■

now that it is working I would like to at least refactor this to use repository pattern or something in a way that the controller action is not that convoluted.. this will eventually be production code :s

任何人都可以给我如何重构这一些建议吗?
请帮助。

can anyone give me some advice on how to refactor this? please help.

推荐答案

我会用一个服务层,像这样的:

I would use a service layer, like this:

public interface IProjectsService
{
    void RemoveTasks(int projectId, IEnumerable<int> taskIdsToRemove);
}

,然后控制器将取决于该服务层上:

and then the controller would depend on this service layer:

public class ProjectsController : Controller
{
    private readonly IProjectsService _service;
    public ProjectsController(IProjectsService service)
    {
        _service = service;
    }

    public ActionResult Edit(int id)
    {
        // TODO: Add methods to your service layer
        // allowing to retrieve projects, then map
        // the resulting project into a view model
        throw new NotImplementedException();
    }

    [HttpPost]
    public ActionResult Edit(int id, ProjectDTO p)
    {
        if (!ModelState.IsValid)
        {
            return View(p);
        }

        var taskIdsToRemove = p.Tasks.Where(x => x.MarkRemove).Select(x => x.ID);
        _service.RemoveTasks(id, taskIdsToRemove);
        TempData["Success"] = "Modelo Valido";
        return RedirectToAction("Index");
    }
}

这样的控制器逻辑更弱连接到我们的数据访问的方式。这是一个实现细节,一个控制器不应该担心。

This way the controller logic is more weakly coupled to the way we do data access. That's an implementation detail that a controller should never have to worry about.

作为进一步的改进以RemoveTasks方法,你可以把它返回一个布尔值指示与错误消息一起操作的成功或失败,这样的编辑操作可能重新显示视图,并显示错误的情况下,不顺心的事。

As a further improvement to the RemoveTasks method you could make it return a boolean indicate the success or failure of the operation along with an error message so that the Edit action could redisplay the view and show the error in case something goes wrong.

现在,只要这个服务层而言, RemoveTasks 方法是,可以在与一些库多CRUD操作来建立一个商业运作。所以这个服务层本身将取决于存储库。只有这个仓库,将有了解EF或无论您使用的是做你的数据访问。

Now as far as this service layer is concerned, the RemoveTasks method is a business operation that could be built upon multiple CRUD operations with some repository. So this service layer would itself depend on a repository. It is only this repository that will have to know about EF or whatever you are using to do your data access.

所以基本上每次我看到有人问一个关于ASP.NET MVC和EF问题的同时,对我来说,这是两个完全不同的问题。 ASP.NET MVC不应该知道什么EF。 EF应埋远的仓库的抽象后面。

So basically everytime I see someone asking a question about ASP.NET MVC and EF at the same time, for me, those are two completely different questions. ASP.NET MVC should not know anything about EF. EF should be buried away behind an abstraction of a repository.

这篇关于帮助提高(重构)我的code。 Automapper - EF - asp.net MVC-3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆