【问题标题】:Entity Framework throws exception on updates only - Invalid object name 'dbo.BirdBrain.service'实体框架仅在更新时引发异常 - 无效的对象名称“dbo.BirdBrain.service”
【发布时间】:2019-07-12 19:00:57
【问题描述】:

我已经从现有数据库创建了一个 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())");
        });
    }
}

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

[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;
    }
}

获取、插入和删除在同一个表上工作。

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

【问题讨论】:

  • 您是否使用了使用 3 部分命名进行编码的 SP?
  • 是的,BirdBrain.dbo. 来自哪里?通常是 EF Core 2.2。不向表名添加模式前缀。是否有一些数据注释或流利的配置未在帖子中显示?
  • @Larnu 我没有使用任何存储过程
  • 这当然很奇怪。可能来自 db trigger (instead of update?) 之类的。打开 EF Core Logging 并查看 EF Core 尝试执行的 SQL 命令。
  • 证明问题不在EF Core。由于您使用的是现有数据库,因此您必须检查数据库。例如,使用 VS SqlServer 对象资源管理器,连接到数据库,展开表 - dbo.services,然后查看代码或查看设计器并在里面寻找BirdBrain。或联系数据库设计者/管理员。谁知道,services 甚至可能不是表,而是视图,或者可能有触发器替换插入、更新、删除,更新触发器有错误。在 EF Core 方面您无能为力。

标签: c# sql sql-server entity-framework ef-core-2.2


【解决方案1】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多