EF Core没有提供自己的跟踪机制。但是,它会记录大量的数据库交互事件。我们可以收集这些日志消息,检查它们的EventId
来确定特定操作是否发生。以下是EF Core使用的关系事件列表:
EF Core 1.1.2:RelationalEventId枚举。
EF Core 2.0.0预览版1:RelationalEventId类(破坏性变更!)。
我们需要做的就是创建一个虚假的日志记录器并将其传递给上下文:
[Fact]
public async Task TransactionCommit_Logger_ContainsEvent()
{
var logger = new FakeLogger();
var factoryMock = new Mock<ILoggerFactory>();
factoryMock.Setup(f => f.CreateLogger(It.IsAny<string>()))
.Returns(logger);
using (var context = new FooContext(factoryMock.Object))
{
using (var transaction = await context.Database.BeginTransactionAsync())
{
transaction.Commit();
}
}
Assert.True(logger.Events.Contains((int)RelationalEventId.CommittingTransaction));
}
FakeLogger
将一个已记录的事件 ID 添加到 Events
列表中。
public class FakeLogger : ILogger
{
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception,
Func<TState, Exception, string> formatter)
{
Events.Add(eventId.Id);
}
public List<int> Events { get; set; } = new List<int>();
public bool IsEnabled(LogLevel logLevel) => true;
public IDisposable BeginScope<TState>(TState state) => null;
}
调用UseLoggerFactory
将工厂实例附加到上下文:
public class FooContext : FooParentContext
{
private readonly ILoggerFactory _loggerFactory;
public FooContext() { }
public FooContext(ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.UseLoggerFactory(_loggerFactory);
}
}
P.S. 你甚至可以更深入地分析日志消息,甚至是EF生成的原始SQL。