如果WCF在MVC应用程序中,它是否应该使用控制器访问数据库以保持“干燥”

如果WCF在MVC应用程序中,它是否应该使用控制器访问数据库以保持“干燥”,wcf,model-view-controller,rest,architecture,dry,Wcf,Model View Controller,Rest,Architecture,Dry,我有一个可以访问SQL和WindowsAzure的MVC应用程序。逻辑流如下所示: Person <--> View <--> Controller.ConvertPersonHere(x) <--> StorageContext.DoDataAction <--> AzurePersonTableEntity 现在我将WCF添加到混合中,我应该如何访问数据函数?假设我当前在控制器中有一个.SavePerson方法,并希望从我的WCF调用中保存P

我有一个可以访问SQL和WindowsAzure的MVC应用程序。逻辑流如下所示:

Person <--> View <--> Controller.ConvertPersonHere(x) <--> StorageContext.DoDataAction <--> AzurePersonTableEntity
现在我将WCF添加到混合中,我应该如何访问数据函数?假设我当前在控制器中有一个.SavePerson方法,并希望从我的WCF调用中保存Person

我是否需要提取控制器中的数据操作


我会像这样重构代码-将功能从Person转换为PersonEntity,反之亦然,移动到单独的映射器,将保存功能移动到单独的存储库,并将调用映射器和存储库的控制器代码移动到单独的服务。 因此,控制器中的方法将类似于:

public ActionResult SomeMethod(Person person)
{
    if (ModelState.IsValid)
    {
        _personService.Save(person)
        return View("Success");
    }
    return View();
}

在您的WCF服务中,您将能够重用代码。为了使用DataAnnotations属性验证WCF中的类,您可以使用与以下类似的方法-

从本例中可以看出,如果您的Mvc项目已被Wpf项目取代,那么您的其他功能仍然可用。如果两个项目都有,它们可以引用核心功能。在其他项目中有与UI MVC或WPF无关的实现。通过这种方式,这些UI项目可以引用此功能

public interface IConverter<TDataModel, TModel> { TModel MapToDomain(TDataModel source);}
public interface IPersonConverter : IConverter<PersonEntity, Person> { }
public interface IPersonRepository { Person GetById(int id); }

public class PersonConverter : IPersonConverter
{
    public Person MapToDomain(PersonEntity source)
    {
        return new Person { ID = source.ID, Name = source.Name };
        //or use an AutoMapper implementation   
    }
}

public class PersonRepository : IPersonRepository
{
    private readonly IPersonConverter _personConverter;

    public PersonRepository(IPersonConverter personConverter)
    {
        _personConverter = personConverter;
    }

    public Person GetById(int id)
    {
        PersonEntity personEntity = new PersonEntity(); //get from storage
        return _personConverter.MapToDomain(personEntity);
    }
}

public class MvcController
{
    private readonly IPersonRepository _personRepository;

    public MvcController(PersonRepository personRepository)
    {
        _personRepository = personRepository;
    }

    public ActionResult SomeMethod(int id)
    {
        Person person = _personRepository.GetById(id);

        //make your view model based on the person domain model
        //with another convert / map, to fit view as personForm
        //(if this is overkill you can use person).

        return View(personForm);
    }
}
Mvc或Wpf项目

个性化用户界面模型 控制器或Wpf类 Person->PersonForm转换器 列表项 核心项目

人 IPersonRepository 基础设施项目

人员存储库 个人实体 Azure人员表实体 存储上下文
我知道这是一个切线,但是如果你混合使用WCF和ASP.NETMVC,你至少应该知道。这是一个良好的开端


不,这甚至不是为了回答你的实际问题

几个问题:personService看起来像什么?存储库StorageContext是否在我的案例中?另外,我很想听听您对此的看法,personService是一种与人合作的服务。它也可以命名为存储库,但这取决于实现。Service for me是一个与一个或多个存储库或/或其他服务一起工作的类。Repository是一个只存储、加载和删除数据存储器中的数据的类。是的,在您的情况下,它是一个存储库StorageContext。谢谢您。。。其中是数据访问层。我被告知这是我处理异常的地方。我是否应该将基础设施项目中的对象称为通道?在我看来,Azure队列与表EntityInfrastructure项目的级别相同,它是数据访问层,具有数据访问实现。至于通道命名约定,我不确定。如果基础设施是DAL,那么应该在存储库或storageContext中管理异常吗?这取决于异常发生的位置以及您希望如何处理它,这取决于您的设计。您也可以在core中创建自己的异常类型,作为捕获到的DAL异常的结果,抛出那些要捕获的异常或进一步出错的异常…我只是快速查看了一下。。。它支持.NET4和MVC3吗?我没有看到任何.NET4信息。不知道它是否matters@makerofthings:它不支持MVC3,它取代MVC3,将其作为通过http交付内容的一种方式—即,以统一的方式交付RESTful服务/站点,而不是通过古怪的装置(如WCF)和/或重协议(如SOAP)对服务方面进行特殊封装。如果它不支持.NET4,我会非常惊讶。我会非常惊讶,如果它适合你,如果你下面的链接并没有让你走那么远…我已经从MVC路由中排除了*.svc,我不会忽略它。我会花更多的时间在上面,但我正忙于学习jquery;ScottGu发布了今晚结束的免费在线课程。
public interface IConverter<TDataModel, TModel> { TModel MapToDomain(TDataModel source);}
public interface IPersonConverter : IConverter<PersonEntity, Person> { }
public interface IPersonRepository { Person GetById(int id); }

public class PersonConverter : IPersonConverter
{
    public Person MapToDomain(PersonEntity source)
    {
        return new Person { ID = source.ID, Name = source.Name };
        //or use an AutoMapper implementation   
    }
}

public class PersonRepository : IPersonRepository
{
    private readonly IPersonConverter _personConverter;

    public PersonRepository(IPersonConverter personConverter)
    {
        _personConverter = personConverter;
    }

    public Person GetById(int id)
    {
        PersonEntity personEntity = new PersonEntity(); //get from storage
        return _personConverter.MapToDomain(personEntity);
    }
}

public class MvcController
{
    private readonly IPersonRepository _personRepository;

    public MvcController(PersonRepository personRepository)
    {
        _personRepository = personRepository;
    }

    public ActionResult SomeMethod(int id)
    {
        Person person = _personRepository.GetById(id);

        //make your view model based on the person domain model
        //with another convert / map, to fit view as personForm
        //(if this is overkill you can use person).

        return View(personForm);
    }
}