在实体框架中使用更新数据库时子查询返回超过 1 个值错误

Posted

技术标签:

【中文标题】在实体框架中使用更新数据库时子查询返回超过 1 个值错误【英文标题】:Subquery returned more than 1 value error when using Update-Database in Entity Framework 【发布时间】:2017-04-21 13:29:51 【问题描述】:

我正在使用实体框架并尝试从 Visual Studio 中的包管理器控制台运行数据库迁移。当我这样做时,我收到以下错误和堆栈跟踪。

PM> Update-Database -Verbose 使用启动项目“项目”。使用 NuGet 项目“数据模型”。指定“-Verbose”标志以查看 应用于目标数据库的 SQL 语句。目标数据库 是:'数据库'(数据源:服务器,提供者:System.Data.SqlClient, 来源:配置)。应用显式迁移: [201612061704158_MigrationName]。应用显式迁移: 201612061704158_MigrationName。 ALTER TABLE [dbo].[TableName] 添加 [ColumnName] [bit] NOT NULL DEFAULT 0 System.Data.SqlClient.SqlException (0x80131904):子查询返回 超过 1 个值。当子查询跟随=时,这是不允许的 !=、、>= 或当子查询用作表达式时。这 声明已终止。在 System.Data.SqlClient.SqlConnection.OnError(SqlException 异常, Boolean breakConnection, Action1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) 在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler、SqlDataReader 数据流、 BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean & dataReady) 在 System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(字符串 方法名,布尔异步,Int32 超时,布尔异步写入)在 System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<NonQuery>b__0(DbCommand t, DbCommandInterceptionContext1 c) 在 System.Data.Entity.Infrastructure.Interception.InternalDispatcher1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func3 操作,TInterceptionContext 拦截上下文, Action3 executing, Action3 执行)在 System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.NonQuery(DbCommand 命令,DbCommandInterceptionContext 拦截上下文)在 System.Data.Entity.Internal.InterceptableDbCommand.ExecuteNonQuery() 在 System.Data.Entity.Migrations.DbMigrator.ExecuteSql(MigrationStatement migrationStatement、DbConnection 连接、DbTransaction 事务,DbInterceptionContext 拦截上下文)在 System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ExecuteSql(MigrationStatement migrationStatement、DbConnection 连接、DbTransaction 事务,DbInterceptionContext 拦截上下文)在 System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable1 migrationStatements, DbConnection connection, DbTransaction transaction, DbInterceptionContext interceptionContext) at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsWithinTransaction(IEnumerable1 migrationStatements、DbTransaction 事务、DbInterceptionContext 拦截上下文)在 System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsWithinNewTransaction(IEnumerable1 migrationStatements, DbConnection connection, DbInterceptionContext interceptionContext) at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable1 migrationStatements、DbConnection 连接、DbInterceptionContext 拦截上下文)在 System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable1 migrationStatements, DbConnection connection) at System.Data.Entity.Migrations.DbMigrator.<>c__DisplayClass30.<ExecuteStatements>b__2e() at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.<>c__DisplayClass1.<Execute>b__0() at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func1 操作)在 System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute(操作 操作)在 System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable1 migrationStatements, DbTransaction existingTransaction) at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable1 迁移声明)在 System.Data.Entity.Migrations.Infrastructure.MigratorBase.ExecuteStatements(IEnumerable1 migrationStatements) at System.Data.Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId, VersionedModel targetModel, IEnumerable1 操作, IEnumerable1 systemOperations, Boolean downgrading, Boolean auto) at System.Data.Entity.Migrations.DbMigrator.ApplyMigration(DbMigration migration, DbMigration lastMigration) at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ApplyMigration(DbMigration migration, DbMigration lastMigration) at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable1 pendingMigrations, 字符串 targetMigrationId, 字符串 lastMigrationId) 在 System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, 字符串 targetMigrationId, 字符串 lastMigrationId) 在 System.Data.Entity.Migrations.DbMigrator.UpdateInternal(字符串 目标迁移)在 System.Data.Entity.Migrations.DbMigrator.c__DisplayClassc.b__b() 在 System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(操作 mustSucceedToKeepDatabase) 在 System.Data.Entity.Migrations.Infrastructure.MigratorBase.EnsureDatabaseExists(操作 mustSucceedToKeepDatabase) 在 System.Data.Entity.Migrations.DbMigrator.Update(字符串 目标迁移)在 System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(字符串 目标迁移)在 System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.Run() 在 System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate) 在 System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate) 在 System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner 亚军)在 System.Data.Entity.Migrations.Design.ToolingFacade.Update(字符串 targetMigration,布尔力)在 System.Data.Entity.Migrations.UpdateDatabaseCommand.c__DisplayClass2.<.ctor>b__0() 在 System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(操作 命令)ClientConnectionId:40e2fc22-5bbd-4d83-88f3-ce5b2bc378dc 错误 Number:512,State:1,Class:16 子查询返回超过 1 个值。这 当子查询跟随 =、!=、、>= 或 当子查询用作表达式时。该声明已 终止。

我不知道这里发生了什么。直接运行SQL语句就可以了

ALTER TABLE [dbo].[TableName] ADD [ColumnName] [bit] NOT NULL DEFAULT 0

这就是迁移文件的样子

public partial class MigrationName : DbMigration

    public override void Up()
    
        AddColumn("dbo.TableName", "ColumnName", c => c.Boolean(nullable: false));
    

    public override void Down()
    
        DropColumn("dbo.TableName", "ColumnName");
    

如果我再注释掉迁移文件中Up()的内容,就可以成功运行(空)迁移了。

另外,如果我针对空数据库运行所有迁移,包括这次迁移,一切正常。所以导致错误的数据存在一些问题(这是预期的,给定错误消息)。

我已尝试查看 SQL Server Profiler 以尝试找出正在执行的 SQL,但没有任何显示。

到目前为止,我还有大约 20 个其他迁移运行良好,但是这个和上一个一直在抛出这个错误。

有谁知道潜在的问题可能是什么,或者我如何才能获得有关问题所在的更多信息?

【问题讨论】:

[TableName] 上是否有任何触发器? @Blorgbeard 好问题。有,但如果我放弃它,迁移也会以同样的方式失败。 【参考方案1】:

我的连接字符串设置了MultipleActiveResultSets=True。从连接字符串中删除它解决了这个问题。

【讨论】:

【参考方案2】:

您是否尝试自己编写迁移。我会做这样的事情

public override void Up()

    DropColumn("dbo.TablaName", "ColumnName");
    AddColumn("dbo.TableName", "ColumnName", c => c.Boolean(nullable: false));

public override void Up()

    AlterColumn("dbo.TableName", "ColumnName", c => c.Boolean(nullable: false));

或者只是添加一列

 public override void Up()

    DropColumn("dbo.TablaName", "ColumnName");
    AddColumn("dbo.TableName", "ColumnName", c => c.Boolean(nullable: false));

我会把 Down 留空。

public override void Down()

干杯!

【讨论】:

好吧,该列不存在,这就是我尝试添加它的原因。将迁移更改为您的会导致 ALTER TABLE DROP COLUMN failed because column 'ColumnName' does not exist in table 'TableName'. 因此,如果您想要做的只是一列,那么只需使用 AddColumn("NAME_OF_YOUR_TABLE", "NAME_OF_YOUR_COLUMN", c=&gt;c.Boolean(nullable: false) 并将 Down 留空 仅供参考,您需要将 ColumnName 替换为您正在使用的列的名称。 这正是我的问题。 好的,你有多少个迁移文件?因为如果您有待处理的迁移文件,它将无法工作。因此,请尝试查找除了最新的迁移之外是否还有任何待处理的迁移【参考方案3】:

按照 Kris 的建议,更改连接字符串也对我有用,但我担心这会如何影响使用相同连接字符串的其他任何内容。

对我也有用的是清空Up()Down() 方法,运行迁移并使用update-database -targetmigration:"PreviousMigrationName" 回滚到上一个迁移。完成此操作后,我可以重新创建迁移并在不更改连接字符串的情况下运行它。

【讨论】:

以上是关于在实体框架中使用更新数据库时子查询返回超过 1 个值错误的主要内容,如果未能解决你的问题,请参考以下文章

如何使实体框架对每条记录使用 1 个更新查询而不是 1 个?

使用 STRING_AGG 函数时子查询返回多行

使用“NOT IN”时子查询非常慢

使用实体框架时是不是可以从查询中返回字符串值?

谈ENTITYFRAMEWORK数据更新之技巧

数据库子查询