3

我有一个由框架自动生成的实体框架(v5.0)DbContextEntities我认为我的设计模式是数据库优先)。

我在整个应用程序中调用了这个搜索命令(如下面的代码片段所示)。我想干掉我的控制器代码并将其重新分解为方法调用。

using (var db = new Entities())
{
    DateTime now = DateTime.Today;
    var activeEvents = db.Events.Where(
        b => !b.removed &&
        b.start_date <= now &&
        b.end_date >= now
    );
}

重构后的示例。

using (var db = new Entities())
{
    var activeEvents = db.Events.GetActive();
    // Or maybe it looks like db.GetActiveEvents();
    // I assume this is dictated by best practice
}

如何实现这一目标?什么被认为是最佳实践?

4

2 回答 2

2

我可能会采取服务方式;您使用三个主要组件构建您的网站:

  • 表示层
    这是 MVC 网站(但也可以是移动网站和应用程序等)
  • 服务层
    处理表示层和数据层之间的调用,应用业务逻辑或任何其他可能需要的校验和(并使其远离表示层)
  • 数据层
    这里是您的Entities驻留和数据库的上下文。

为简单起见,您可以将其保留在一个项目中,但如果这成为一个大型应用程序,您可能希望将其重构为单独的库。

现在,至于如何重构您现在的情况,我们在其中添加服务层。我喜欢使用接口,因此以后可以轻松测试我可以IWhateverService在进行单元测试时实现“虚拟”,但在运行实际应用程序时保留当前实现。然后,您实现接口以与数据交互并返回您需要的内容(或执行任何必要的操作 [CRUD])。例如

public interface IEventService
{
    IEnumerable<Event> GetActive();
}

public class EventService : IEventService
{
    private readonly Entities entities;
    public EventService(Entities entities)
    {
        this.entities = entities;
    }
    public IEnumerable<Event> GetActive()
    {
        DateTime now = DateTime.Today;
        return this.entities.Events
            .Where(x => !x.removed)
            .Where(x => x.start_date <= now && x.end_date >= now)
            .AsEnumerable();
    }
}

现在我们有了服务,我们可以将其连接到控制器:

public class EventsController : Controller
{
    private readonly IEventService eventService;

    public EventsService()
    {
        this.eventsService = new EventsService(new Entities());
    }

    // action that gets and views the active events
    public ActionResult Active()
    {
        var activeEvents = this.eventsService.Getactive();
        return View(activeEvents);
    }
}

随着项目的发展,您可以IEventService使用 CRUD 操作更新您的操作(就像我之前提到的):

public interface IEventService
{
    IEnumerable<Event> All { get; }

    void AddOrUpdateEvent(Event event);
    IEnumerable<Event> GetActive();
    void RemoveEvent(Event event);
}

当然是通过管道连接到EventService,然后最终在EventsController.

为了更进一步[几个]步骤,您可以查看依赖注入,您可以在其中指定(一次)如何构建IEventsService然后,当您需要它时,将其作为参数传递给控制器​​的构造函数(如下所示):

public OtherController : Controller
{
    private readonly IUserService;
    private IEventService eventService;

    public OtherController(IUserService userService, IEventService eventService)
    {
        this.userService = userService;
        this.eventService = eventService;
    }

    /* actions */
}

然后,您可以使用 Castle Windsor、ninject 或任何其他涉及到这些接口的单个​​映射的解决方案,然后(神奇地)将它们提供给控制器的构造函数以供使用。举个例子,这是一个 Castlewindsor 配置:

container.Register(
    Component.For<IEventService>().ImplementedBy<EventService>()
        .LifestyleSingleton()
);

这基本上说每次我需要IEventService供应EventService

于 2013-07-26T14:50:03.347 回答
1

也许您可以使用部分类来实现这一点。

界面:

interface IMethods<T>
{
    IEnumerable<T> ActiveItems();
}

部分类:

partial class Event :IMethods<Event>
{
    public IEnumerable<Event> ActiveItems()
    {
        try
        {
            using (var db = new Entities())
            {
                DateTime now = DateTime.Today;
                return db.Events.Where(b => !b.removed && b.start_date <= now && b.end_date >= now);
            }
        }
        catch (Exception)
        {
            return null;
        }

    }
}

测试方法:

 public class TestClass
{
    public void MyTest()
    {
        var ativevnts = new Event().ActiveItems();
    }
}
于 2013-07-26T13:55:38.877 回答