【问题标题】:Why does my .NET SQL UPDATE only work once?为什么我的 .NET SQL UPDATE 只工作一次?
【发布时间】:2019-05-04 20:08:20
【问题描述】:

由于某种原因,下面的代码实际上只在触发后运行一次(如果幸运的话,有时会运行两次)。

之后它返回一个res > 0,但数据库中的行没有改变。知道为什么会发生这种情况以及如何解决吗?

我已经尝试过处理 DbCommand 对象(如您所见)。

public static async Task<bool> SetWallpaper(CornUser User, ulong ID)
{
    using (DbCommand dbCommand = DbProviderFactory.CreateCommand()) 
    { 
        dbCommand.Connection = SQLConnection;

        dbCommand.CommandText = @"
            UPDATE Users
            SET Wallpaper = @Wallpaper
            WHERE DiscordID = @DISCORDID";

        dbCommand.Parameters.Add(new SqlParameter("@DISCORDID", System.Data.SqlDbType.BigInt) { Value = User.ID });
        dbCommand.Parameters.Add(new SqlParameter("@Wallpaper", System.Data.SqlDbType.Int) { Value = ID });

        dbCommand.Prepare();

        int res = await dbCommand.ExecuteNonQueryAsync();
        return (res > 0);
    }
}

我希望它实际上将Wallpaper 列更改为一直提供的ID

【问题讨论】:

  • 你为什么使用TOP(1)?对我来说,DiscordID 对用户来说似乎不是唯一的,您正在更新随机行
  • 并且,如果没有“ORDER BY, if DiscordID”不是唯一的,那么上面的查询将使用适当的 ID 更新表 Users 中的“随机”行(可能是每次都使用相同的 ID,但这只是巧合,即使每次都几乎)。
  • @LukaszSzozda 我是 MS-Sql 的新手,有人告诉我 TOP(1) 会导致它在找到第一行匹配 WHERE 子句以进行优化的第一行后停止更新。可能是 bs,虽然我不能说真的。
  • 对于使用唯一 ID 的查询(我猜想它会被(集群)索引)添加 TOP 1 将没有任何好处。数据引擎对值执行的搜索将是数据引擎所需的全部,并且它会知道只有一行要更新。如果您要更新未知数量的行,使用 TOP 1 不会给您想要的行为。
  • 您似乎拥有一个全局共享连接。你也有全球永无止境的交易吗?您的数据库不是处于快照隔离模式吗?以及如何验证数据库中的行没有变化?

标签: c# .net sql-server tsql


【解决方案1】:

太好了……我找到了解决办法。

因此,经过几天的修修补补,我彻底重写了整个 UserDataService 类(包含此类任务。

并将命令更改为以下内容:

using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
        {
            using (DbConnection connection = DbProviderFactory.CreateConnection())
            {
                connection.ConnectionString = SQLConnectionString;
                await connection.OpenAsync();
                DbCommand command = connection.CreateCommand();
                command.CommandText = "UPDATE Users SET Wallpaper=@WallpaperID WHERE DiscordID=@DiscordID";
                command.Parameters.Add(new SqlParameter("@DiscordID", SqlDbType.BigInt) { Value = UserID });
                command.Parameters.Add(new SqlParameter("@WallpaperID", SqlDbType.BigInt) { Value = WallpaperID });
                await command.ExecuteNonQueryAsync();
                scope.Complete();
                return true;
            }
        }

这似乎成功了!

感谢@RazvanSocol 引导我朝着正确的方向前进!

【讨论】:

    猜你喜欢
    • 2012-03-09
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-21
    • 2019-10-08
    • 2017-05-29
    相关资源
    最近更新 更多