DRY实体框架搜索调用
本文关键字:调用 搜索 框架 实体 DRY | 更新日期: 2023-09-27 18:25:00
我有一个名为Entities
的实体框架(v5.0)DbContext
,它是由框架自动生成的(我认为我的设计模式是数据库优先)。
我有这个搜索命令(显示在下面的代码段中),我正在整个应用程序中调用它。我想清空我的控制器代码,并将其重新考虑到方法调用中。
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
}
如何实现这一目标?什么是最佳实践?
我可能会采用服务方法;您使用三个主要组件构建您的网站:
- 演示层
这是MVC网站(但可以是移动网站和应用程序,不管怎样) - 服务层
它处理表示层和数据层之间的调用,应用业务逻辑或任何其他必要的校验和(并使其远离表示层) - 数据层
这里是您的Entities
所在地和数据库的上下文
为了简单起见,您可以将其保留在一个项目中,但如果它成为一个大型应用程序,您可能需要将其重构到单独的库中。
现在,关于如何重构您的情况Now,我们在其中添加了服务层。我喜欢使用接口,这样以后测试就更容易了。我可以在进行单元测试时实现一个"伪"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);
}
}
随着项目的发展,您可以使用CRUD操作更新IEventService
(就像我前面提到的):
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
。
您可以使用分部类来实现这一点。
接口:
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();
}
}