0

我对创建依赖于某种持久数据存储(例如数据库/实体框架)的可重用组件的最佳方法感到烦恼。

例如,假设我想创建一个可重用的事件记录器,我只是通过 nuget 将其导入我的项目中。我希望它将其数据存储在主应用程序正在使用的同一数据库中,但我不想让记录器依赖于我的应用程序其余部分正在使用的数据上下文;这样做似乎会将组件与该特定应用程序联系起来。相反,我想知道它是否应该有自己的数据上下文,或者有另一个处理数据持久性的抽象......

我想我想问的问题是,在使用实体框架时,当它定义了一堆在我的主项目中存在的具体事物时,我如何对通用接口进行编程......?

public class SqlEventLogger : IEventLogger
{
    private DataContext _ctx;
    private Repository<ExceptionLog> repo;

    public SqlEventLogger(DataContext ctx)
    {
        _ctx = ctx;
        repo = new Repository<ExceptionLog>(ctx);
    }

    public void Log(string message, Severity severity, Exception exception = null, string requestType = null, string user = null, string location = null, string data = null)
    {
        repo.Add(new ExceptionLog
        {
            CreatedDate = DateTime.UtcNow,
            Message = String.Format("{0} || {1}", message, exception.Message),
            Source = exception.Source,
            StackTrace = exception.StackTrace,
            TargetSite = exception.TargetSite.ToString(),
            RequestForm = data,
            Url = location,
            RequestType = requestType,
            CurrentUser = user
        });

        _ctx.SaveChanges();
    }

在这种情况下,DataContext 是我的代码优先 DbContext,而 ExceptionLog 是实体。

4

1 回答 1

2

您应该使用自己的抽象将所有特定于持久性的代码提取到其类中。这样,您可以拥有一个仅包含记录器逻辑的记录器类,并且可以在每个项目的基础上交换持久性实现。

但是,在您的示例中,SqlEventLogger该类仅包含与持久性相关的逻辑。如果这是实际情况,则无需提取该持久性逻辑,因为您最终会得到一个空的记录器实现。因此,如果这是您的实际情况,那IEventLogger是唯一要处理的抽象。您的可重用组件应该只包含该IEventLogger抽象,并且可能包含一个或多个默认实现。

这实际上是大多数日志框架的工作方式。在您的框架中使用默认 SQL 记录器时,使用普通 SQL 或存储过程并提供带有包的 SQL 脚本可能会更容易,这样用户就可以创建所需的表和存储过程来启动并运行日志记录框架分钟。

即使您使用实体框架,该 EF 模型也是特定于您的实现的,并且应该放在您的可重用库中。所以没有必要注入它。相反,用户应该提供SQLEventLogger连接字符串。但是,您仍然需要为用户提供 SQL 脚本。为了让生活更轻松,您可以允许为SqlEventLogger用户自动创建表(使用特定配置开关时)。这也是CuttingEdge.LoggingSqlLoggingProvider所做的事情。

于 2013-07-08T10:42:19.313 回答