实体框架仅在更新时引发异常-无效的对象名称“ dbo.BirdBrain.service”

Sea*_*lak 5 c# sql sql-server entity-framework ef-core-2.2

我已经从现有数据库创建了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;
Run Code Online (Sandbox Code Playgroud)

而且我不知道这是如何导致针对'BirdBrain.dbo.services'数据库运行更新的BirdBrain_test。

相关的DbContext代码

Server=****;Database=BirdBrain_test;User Id=****;Password=****;Trusted_Connection=False;Multisubnetfailover=true;
Run Code Online (Sandbox Code Playgroud)

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

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())");
        });
    }
}

Run Code Online (Sandbox Code Playgroud)

相关更新代码

[Table("services")]
public class Service
{
  ...
}
Run Code Online (Sandbox Code Playgroud)

获取,插入和删除在同一张表上进行。

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'.
Run Code Online (Sandbox Code Playgroud)

编辑:我按照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
Run Code Online (Sandbox Code Playgroud)

Sea*_*lak 2

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

为了解决这个问题,我按照 @IvanStoev 的建议向 DbContext 添加了日志记录,并确认 EF 实际上services正确地定位了对象,而不是 BirdBrain.dbo.services我最初认为的那样。

然后,我使用 SSMS 连接到数据库并扩展表以查看其触发器,这就是我发现违规触发器的地方。

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