我正在开发一个c#控制台应用程序,我使用实体框架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();
现在我为我的日志提供了单独的DbContext对象,原因如下: -
答案 0 :(得分:6)
不要使用2个上下文,您应该使用记录器(例如log4net with AdoNetAppender)。正如Evk在下面的评论中指出的那样,当您调用SaveChanges()
时,EF会自动将所有内容包装到事务中,因此一旦发生错误,就不会将任何内容提交到数据库,您可以记录错误。例如:
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);
}
}
}
通过这种方式,您的应用程序保持干净,只有在SaveChanges()
块结束时调用using
并且仅在发生异常时才记录,所有内容都会成功更新。使用块来始终处理您的上下文也更好,即使会发生意外的异常。记录器将负责将错误写入另一个线程中的数据库,而不会降低程序的速度。也许你可以尝试NLog,我听说它比log4net更好(=更容易配置/使用),但我仍然需要自己尝试一下。
答案 1 :(得分:1)
如果您的数据库包含多个数据库模式,并且您希望将每个上下文作为单独的自包含区域处理,则为单个数据库提供多个上下文可能很有用。如果是这种情况,你的代码/要求就不清楚了。
如果您正在使用的表位于同一个数据库和相同的架构,然后我看不出你使用两个DbContexts的原因。即使您有验证错误或异常,您仍然可以使用相同的上下文保存到日志表中。
如果您尝试记录错误和/或其他相关信息,为什么不使用log4net进行日志记录?
修改强>
在我看来,日志记录应该与您的正常交易无关,因此您不必考虑这种情况。话虽这么说,在一个事务中你可以保存和记录,但如果有异常也会记录。除非我遗漏了某些内容,否则我仍然不需要2个DBContexts。
请查看以下内容,了解有关交易的一些指导。
答案 2 :(得分:0)
有一些问题。
如果我们在数据输入方面遇到异常(如果任何状态不受影响,我们可以继续运行)。但是如果我们在登录时遇到异常,我们就不会处理?
我们的业务逻辑在做什么?如果我们得到错误的json数据,我们的业务逻辑应检查并处理它。
好吧,让我们说json是有效的,它传递业务逻辑。我们在db上使用varchar(20)有字符串字段,但数据有25个字符。那么我们的模型验证是做什么的呢?
你应该在上层处理这些事情。
违反了单一责任。此方法应该只有一个责任,即将实体保存到db。它也不应该对记录负责。你应该在另一个班级实现它。
因此,您的问题就出现了。你试图给这个方法两个可靠性。然后你尝试选择我需要的1个dbcontext或2个dbcontexts。如果您遵循单一责任,则不会出现此问题。
您应该实施记录器服务。您的课程不应该知道或关心记录器服务如何处理它。您可以将其保存到数据库,文件或云,如loggly。此外,您的记录器服务不应与其他类共享相同的上下文。
答案 3 :(得分:-2)
Entity Framework 5代码首次迁移只能管理每个物理数据库实例的单个DbContext。 Entity Framework 6代码首次迁移能够管理每个物理数据库实例的多个DbContext。
查看非常好的例子: