Entity Framework 仅在更新时抛出异常 - 对象名称无效 'dbo.BirdBrain.service'

Entity Framework throws exception on updates only - Invalid object name 'dbo.BirdBrain.service'

我已经从现有数据库创建了一个 EF Core 模型,除了更新之外,对实体的所有操作都有效;更新时 EF Core 使用了不正确的数据库名称。

例如。当我执行更新时,我得到 SqlException: Invalid object name 'BirdBrain.dbo.services'.BirdBrainContext 是我的 DbContext 的名称,但我要连接的数据库是 BirdBrain_test.

我尝试从 EF Core 2.1 更新到 EF Core 2.2,但问题仍然存在。当连接到名为 BirdBrain 的生产数据库时,相同的代码可以完美运行。

我正在使用如下所示的连接字符串初始化我的上下文

Server=****;Database=BirdBrain_test;User Id=****;Password=****;Trusted_Connection=False;Multisubnetfailover=true;

我不知道当数据库为 BirdBrain_test.

时,这如何导致更新 运行 而不是 'BirdBrain.dbo.services'

相关DbContext代码

public class BirdBrainContextFactory
{
    private readonly string _connectionString;

    public BirdBrainContextFactory(string connectionString)
    {
        _connectionString = connectionString;
    }

    public BirdBrainContext Create()
    {
        var optionsBuilder = new DbContextOptionsBuilder<BirdBrainContext>();
        optionsBuilder.UseSqlServer(_connectionString);
        return new BirdBrainContext(optionsBuilder.Options);
    }
}

public class BirdBrainContext : DbContext
{
    public BirdBrainContext(DbContextOptions<BirdBrainContext> options)
        : base(options)
    {
    }

    public DbSet<Service> Services { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Service>(entity =>
        {
            entity.HasIndex(e => e.Tag)
                .IsUnique();

            entity.Property(e => e.CreatedAt)
                .HasDefaultValueSql("(getutcdate())");

            entity.Property(e => e.UpdatedAt)
                .HasDefaultValueSql("(getutcdate())");
        });
    }
}

关联的table我正在使用TableAttribute来引用table名称。

[Table("services")]
public class Service
{
  ...
}

相关更新代码

public Service UpdateService(Service service)
{
    using (var context = _contextFactory.Create())
    {
        EnforceServiceExists(context, service);
        context.Entry(service).State = EntityState.Modified;
        context.SaveChanges();
        return service;
    }
}

获取、插入和删除同样适用于此 table。

Microsoft.EntityFrameworkCore.DbUpdateException
  HResult=0x80131500
  Message=An error occurred while updating the entries. See the inner exception for details.
  Source=Microsoft.EntityFrameworkCore.Relational
  StackTrace:
   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(DbContext _, ValueTuple`2 parameters)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable`1 commandBatches, IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Storage.RelationalDatabase.SaveChanges(IReadOnlyList`1 entries)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IReadOnlyList`1 entriesToSave)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
   at DataService.BirdBrainContext.SaveChanges() in C:\git\BirdBrainAPI\src\DataService\BirdBrainContext.cs:line 180
...

Inner Exception 1:
SqlException: Invalid object name 'BirdBrain.dbo.services'.

编辑:我按照 Ivan Stoev 的建议添加了 EF Core 日志记录,并在下方粘贴了更新结果。看起来 EF 正在连接到 BirdBrain_test 数据库并且 运行 宁 UPDATE [services] ... 而不是错误提示的 UPDATE [BirdBrain].[dbo].[services] 。仍然不确定发生了什么。

dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
      Opened connection to database 'BirdBrain_test' on server '****'.
dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
      Beginning transaction with isolation level 'ReadCommitted'.
dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
      Executing DbCommand [Parameters=[@p19='?' (DbType = Int32), @p0='?' (DbType = DateTime), ...], CommandType='Text', CommandTimeout='30']
      SET NOCOUNT ON;
      UPDATE [services] SET [created_at] = @p0, ... , [updated_at] = @p18
      WHERE [id] = @p19;
      SELECT @@ROWCOUNT;
fail: Microsoft.EntityFrameworkCore.Database.Command[20102]
      Failed executing DbCommand (61ms) [Parameters=[@p19='?' (DbType = Int32), @p0='?' (DbType = DateTime), ...], CommandType='Text', CommandTimeout='30']
      SET NOCOUNT ON;
      UPDATE [services] SET [created_at] = @p0, ... , [updated_at] = @p18
      WHERE [id] = @p19;
      SELECT @@ROWCOUNT;
System.Data.SqlClient.SqlException (0x80131904): Invalid object name 'BirdBrain.dbo.services'.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
   at System.Data.SqlClient.SqlDataReader.get_MetaData()
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.ExecuteReader()
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary`2 parameterValues)
ClientConnectionId:b2b87fd1-8e34-4fcf-80f1-290de30b28dd
Error Number:208,State:1,Class:16

问题是在使用 BirdBrain.dbo.services 命名的数据库上有一个基础更新触发器。我测试了将命名从 BirdBrain.dbo.services 更改为 services,这解决了错误。最终我完全删除了触发器,因为它处理的逻辑在目前是不必要的。

为了解决这个问题,我按照@IvanStoev 的建议添加了 logging to the DbContext,并确认 EF 实际上是正确地针对 services 对象,而 不是 BirdBrain.dbo.services 正如我最初相信的那样。

然后我使用 SSMS 连接到数据库并展开 table 以查看其触发器,这是我发现有问题的触发器的地方。

如果您遇到类似的问题,您应该检查您正在修改的 table 上是否有任何触发器。