启动2个DBContext对象,一个用于日志,另一个用于c#控制台应用程序中的业务数据

joh*_* Gu 5 c# ado.net entity-framework dbcontext entity-framework-5

我正在研究ac#console应用程序,我使用实体框架5.0作为sql server的数据访问层.现在我想跟踪更改并将它们保存在日志表中.所以这样做我发起了2个DbContext对象,一个用于业务数据,另一个用于日志数据,如下所示:

class Sync
    {
        static void Main(string[] args)
        {
            string syncResult = "Sync started";
            Entities entities = new Entities();//for business data
            Entities entities2 = new Entities();//for logs
            try
            {
              //code goes here
              entities.SaveChanges();
            }
            catch (Exception e)
            {
                syncResult = string.IsNullOrEmpty(e.Message) ? "Error" : e.Message;

            }
            entities.Dispose();
            entities2.LogHistories.Add(new LogHistory() { Description = syncResult });
            entities2.SaveChanges();
            entities2.Dispose(); 
Run Code Online (Sandbox Code Playgroud)

现在我为我的日志提供了单独的DbContext对象,原因如下: -

  1. 如果我的第一个实体对象由于任何原因(例如未处理的验证错误或尝试破解系统等)而无法保存更改,则第二个实体2仍将能够保存日志条目.让我们举个例子.假设我正在使用第三方API进行集成,我期望它们以特定格式返回JSON.现在让我们假设返回json对象缺少数据,在这种情况下,当我尝试添加它将引发的对象时,它会异常...现在因为我有日志的单独实体对象,所以日志条目将被保存(不会受到任何业务数据异常的影响).但如果我有一个DBContext对象,那么日志条目将无法保存,因为我无法保存业务数据..所以我的问题是如果启动2个DBContext对象一个用于日志而另一个用于业务数据是一个有效的方法跟随,或者是一个不好的决定?

Ale*_*rck 6

不要使用2个上下文,您应该使用记录器(例如使用AdoNetAppender的log4net).正如Evk在下面的评论中指出的那样,EF会在您调用时自动将所有内容包装到事务中SaveChanges(),因此一旦发生错误,就不会向数据库提交任何内容,您可以记录错误.例如:

static void Main(string[] args)
{
    ILog log = LogManager.GetLogger("Entities");

    using(var ctx = new Entities())
    {
        try
        {
            ...
            ctx.SaveChanges();
        }
        catch(Exception ex)
        {
           log.Error(ex.Message);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,您的应用程序保持干净,只有SaveChanges()using块结束时调用一切都成功时才会更新,并且仅在发生异常时进行记录.即使发生意外异常,使用块总是处理您的上下文也会更好.记录器将负责将错误写入另一个线程中的数据库,而不会降低程序的速度.也许你可以试试NLog,我听说它比log4net更好(=更容易配置/使用),但我还是要自己尝试一下.


Wil*_*ras 1

如果您的数据库包含多个数据库模式并且您希望将每个数据库模式作为单独的自包含区域进行处理,则为单个数据库拥有多个上下文可能会很有用。如果是这种情况,从您的代码/要求中不清楚。

如果您正在使用的表位于相同的数据库和相同的架构中,那么我看不出您使用两个 DbContext 的理由。即使出现验证错误或异常,您仍然可以使用相同的上下文保存到日志表中。

如果您尝试记录错误和/或其他相关信息,为什么不使用 log4net 来进行日志记录呢?

编辑

在我看来,日志记录应该独立于您的正常事务,因此您不必考虑这种情况。话虽这么说,在事务中您可以保存并记录,而且如果出现异常也可以记录。除非我遗漏了什么,否则我仍然认为不需要 2 个 DBContext。

请查看以下内容,了解有关交易的一些指导。

https://msdn.microsoft.com/en-us/data/dn456843.aspx