我正在使用ASP.NET核心创建Web API,并对如何将其发布到审核/日志表感到困惑。
有两个表,一个事件表和一个事件日志表。如果用户创建一个新事件,则它将在事件和事件日志表中都添加一个条目。如果用户编辑事件的名称/描述,它还将在事件日志表中创建一个新条目。请注意,事件日志表的结构与事件表大部分相同。
事件表
+------------------+
| Event Table |
+------------------+
| Id |
| EventName |
| EventDescription |
| CreatorId |
+------------------+
事件日志表
+------------------+
| Event Log Table |
+------------------+
| Id |
| EventId |
| EventName |
| EventDescription |
| EditorId |
| TimeEdited |
+------------------+
当前,我的Web API中针对两个表中的每个表都有两个单独的控制器,即事件控制器和事件日志控制器。
当前发生的情况:当有事件的发布/投放时,它将创建事件日志控制器的实例,并调用post方法创建事件日志,并传入新的创建/更新的事件日志对象。
这里有一些简化的代码...
在EventController.cs中。
public IActionResult PostEvent([FromBody] Event event)
{
_context.Event.Add(event);
_context.Event.SaveChanges();
EventLogController logController = new EventLogController(context);
logController.PostEventLog(event);
return Ok();
}
在EventLogController.cs中...
public IActionResult PostEventLog([FromBody] Event event)
{
var eventLog = _mapper.Map<EventLog>(event);
eventLog.TimeEdited = DateTime.Now;
_context.EventLog.Add(eventLog);
_context.EventLog.SaveChanges();
return Ok();
}
虽然目前效果很好,但我非常担心这是否是最佳实践(创建一个仅调用一个方法的新控制器似乎很糟糕)。可能需要注意的是,我不想向每个控制器发送两个单独的API调用。我希望由于添加/更新条目而创建事件日志。
据我所知,我可以采取其他一些方法...
创建存储库/服务?用于将EventLog添加到数据库并将其注入EventController。虽然这样做确实可以避免创建控制器,但听说在ASP.NET Core中创建存储库是不必要的抽象。
在EventController的PostEvent操作中添加事件日志条目,而无需创建控制器或存储库/服务。但是,这意味着该操作方法将处理两个请求。
继续使用当前方法,只是注入EventLog控制器而不创建新实例。
至于我认为我做不到的事情...
我认为我无法在数据库本身内创建触发器,因为创建事件条目所包含的信息不足以创建事件日志(因为数据库不会意识到编辑器)。
我也不认为我可以使用RedirectToAction,因为它是一个后发请求,需要在体内发送一些东西。
所以我的问题是:在相关实体的每次创建/更新上创建日志/审核条目的正确方法是什么?
答案 0 :(得分:1)
我希望创建一个单独的类,您实际上在“其他方法1”中提到过。然后您可以从多个地方调用它。
通常,如您所知,许多方法都是可行的。经验法则应该始终是:“控制器只能控制,它本身不能完成工作。”这意味着控制器应该只知道调用什么才能完成工作。如果遵循此原则,则可以将实际代码放在单独的类中,然后可以根据需要从一个或多个控制器的多个位置调用它。
答案 1 :(得分:0)
一个单独的班级将成为您的朋友。当然,如果实现非常简单并且应用程序不是很大,那么创建最简单的解决方案就没有错。无论如何,调用另一个控制器将耦合您的代码。
我做了一个简单的例子,通常我喜欢类似的情况。
public class EventService
{
private IEventLogger logger;
public EventService(IEventLogger logger)
{
this.logger = logger;
}
internal void AddNew(Event @event)
{
// Here is your code to persist event.
// For example, context.SaveChanges(@event)
// or whatever you want.
// When event is saved, I have called object that
// implements IEventLogger interface. It is just a simple
// interface to introduce Log(Event @event) -method.
//
// When this service is created, you can pass logger
// implementation. You can also use different way to pass
// right implementation if constructor isn't work for you.
if(logger != null) {
this.logger.Log(@event);
}
}
}
# In your controller you can use service like this.
# Of course, service is not needed to create inside the action
# but I just wanted to make a simple example.
public IActionResult PostEvent([FromBody] Event @event)
{
IEventLogger logger = new EventLogger();
EventService eventService = new EventService(logger);
eventService.AddNew(@event);
return Ok();
}
它不应是知道实现细节的控制器。如前所述,控制器只是控制。
在这里,我介绍了一项负责处理持久事件的服务。您可以使用context
初始化服务。我将示例保持简单,不再赘述,但您可能会明白。
当调用方法AddNew(event)时,服务将了解您的业务规则。对于您而言,我认为“日志记录”是您需要的规则之一。您希望保留更改日志,以便在使用服务时始终可以使用记录器。
IEventLogger
是一个简单的界面。实现它时,可以在其中使用相同的上下文,然后在实现内部处理日志。
if(logger != null)
不是强制性的,但通常是一种不错的选择,可以在不需要时选择不使用日志记录。
如果需要,您始终可以将EventLogController
分隔开来,这些返回的记录数据可以从API返回使用。您的EventLogController具有方法PostEventLog
。现在,如果需要,您可以在控制器操作中使用相同的记录器来保留日志事件。