【问题标题】:sql update for dynamic row number动态行号的sql更新
【发布时间】:2016-06-20 14:33:09
【问题描述】:

我正在开发一个 ASP.net WebAPI 项目。 项目需求的一项功能是更新工艺类型。 工艺表包含craftTypeKey、craftTypeName 和craftTypeDescription 列。 我需要更新craftTypeName 和craftTypeDescription 列。 我面临的问题是,UI 提供的行数是动态的。 它可以是一个数组(或列表)。 我正在使用 SQL 存储过程来执行数据库更新操作。 现在我正在使用一个更新表格的一行并在循环中调用 SP 直到所有元素都更新的 SP。 我的方法的问题是,如果我在循环之间出现更新错误(出于某种原因),我无法通知 UI 部分,它们在更新时发生了错误。 仅向 UI 客户端提供最后一行更新状态(JSON 格式。) 我需要使用成功更新的行数和发生更新失败的行数来更新 Web api 输出。

我用来执行数据库更新的代码如下。

ALTER PROCEDURE [dbo].[usp_UpdateCraftType]
@OrgKey INT,
@CraftTypeKey INT,
@CraftTypeName VARCHAR(50),
@CraftTypeDescription VARCHAR(128)   AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @rowcount1 
        BEGIN   
            UPDATE  [dbo].[CraftTypes]
            SET
               [CraftTypeName]=@CraftTypeName
               ,[CraftTypeDescription]=@CraftTypeDescription
            WHERE CraftTypeKey=@CraftTypeKey                
            SET @rowcount1 = @@ROWCOUNT
        IF @rowcount1 =0
            SELECT  -167;
        ELSE
            SELECT  167;        
        END 
END

更新工艺类型api的C#代码是

 public PageViewModel UpdateCraftType( CraftTypes[] craftType)
    {
      objPageViewModel = new PageViewModel();
        EmployeeAccessService emplAccess = new EmployeeAccessService();

        for (int i = 0; i < craftType.Length; i++)
        {
            if (craftType[i] != null)
            {
                DataSet dsCraftTypeUpdateResult = new DataSet();
                dsCraftTypeUpdateResult = emplAccess.UpdateCraftType(new {  CraftTypeKey = craftType[i].CraftTypeKey, CraftTypeName = craftType[i].CraftTypeName, CraftTypeDescription = craftType[i].CraftTypeDescription });
                if (dsCraftTypeUpdateResult != null && dsCraftTypeUpdateResult.Tables[0].Rows.Count > 0)
                {
                    if (Convert.ToInt32(dsCraftTypeUpdateResult.Tables[0].Rows[0][0]) == 167)
                    {
                        objPageViewModel.FillPageViewModelObject(ResponseStatus.CraftTypeUpdated);
                    }
                    else
                    {
                        objPageViewModel.FillPageViewModelObject(ResponseStatus.CraftTypeUpdateFailure);
                    }
                }
            }
        }

        return objPageViewModel;
    }
 public DataSet UpdateCraftType(object model)
    {
        DataSet dsCraftTypeUpdated = new DataSet();
        DatabaseModel dbModel = new DatabaseModel();

        IDataAccess dataAceess = new DataAccessObject();
        dbModel.CommandText = StoredProcedure.usp_UpdateCraftType;
        dbModel.Params = model;

        dsCraftTypeUpdated = dataAceess.GetData(dbModel);

        return dsCraftTypeUpdated;
    }

public DataSet GetData(DatabaseModel dbmodel)
    {
        string connectionstring = _context.Database.Connection.ConnectionString; //_context.Database.Connection.ConnectionString;
        SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectionstring);
        builder.ConnectTimeout = Convert.ToInt32(ConfigManager.GetAppSettingValue("ConnectionTimeOut"));
        SqlConnection connection = new SqlConnection(builder.ConnectionString);
        datahelper = new DataAccessHelper(connection);
        SqlDataAdapter da = null;
        DataSet ds = new DataSet();

        connection.Open();
        using (SqlCommand cmd = datahelper.GetCommandObject(dbmodel))
        {
            da = new SqlDataAdapter(cmd);
            da.Fill(ds);
        }

        connection.Close();

        return ds;
    }

public class PageViewModel
{
    public int StatusCode { get; set; }
    public string StatusMessage { get; set; }
    public int TotalCount { get; set; }
    public object ModelObject { get; set; }

    public PageViewModel FillPageViewModelObject(ResponseStatus statusCode_i, object modelObject_i = null)
    {
        this.StatusCode = (int)statusCode_i;
        this.StatusMessage = EnumerationHelper.GetEnumDescription(statusCode_i);
        this.ModelObject = modelObject_i;
        return this;
    }
}

感谢您的帮助.....

【问题讨论】:

  • 我认为你可以在这里使用事务,所以它要么全部更新要么失败,假设你不想在循环之间更新失败时部分更新记录。
  • 在哪里可以设置交易?由于存储过程是在 C# 循环中调用的,因此它的作用域在 sp 的每次执行中都会覆盖。那么如何识别之前执行的 sp 是否已完成回滚呢?
  • 可以在SQL Server中设置事务,这个帖子可以帮到codeproject.com/Articles/4451/…

标签: sql-server stored-procedures asp.net-web-api sql-update


【解决方案1】:

我需要使用成功更新的行数和发生更新失败的行数来更新 Web api 输出。

你可以使用输出子句..见下面的例子,它会给你一些想法

CREATE TABLE test1234 (id int)

INSERT INTO test1234

SELECT top 100 n
FROM numbers
WHERE n<=100

SET nocount ON

DECLARE @id int

SET @id=1

DECLARE @table TABLE (id int)

WHILE (@id<=100)
BEGIN
    BEGIN try
      UPDATE test1234
      SET id= CASE WHEN id<>100 THEN id+1 ELSE 'a' END--error occurs at 100th row**
    OUTPUT deleted.* INTO @table WHERE id=@id
    END try
    BEGIN catch
      SELECT error_message()
      SELECT count(DISTINCT id)
      FROM @table--when error occurs we are outputting number of rows updated so far
    END catch
SET @id=@id+1 END

正如您在上面的脚本中看到的,错误发生在第 100 行,我正在输出更新的行数和失败的行数可以是您的数组或列表减去这个...

在不使用while循环的情况下,总而言之,您需要将数据表传递给存储的proc。所以这里是一般的步骤..

1.创建类型表
2.将数组或列表转换为数据表
3.将数据表传递给存储过程

使用这种方法,您的最终结果将是全部或无..

create type test1 as table
(
cratftype int,
All columns
)

create proc usp_test
(
@test test1 readonly
)
as
begin

update 
set t.id=t2.id
from
test1 t
join
@
@test t2
on t1.id=t2.id

end

希望对你有帮助

【讨论】:

  • “TABLE test1234”是临时表吗? @TheGameiswar有没有办法把它放在单个存储过程中?还有一个问题。如何在不使用 c# 代码循环的情况下将完整数据插入 test1234?
  • 是的,这是一个临时的,我不明白这部分 有没有办法把它放在单个存储过程中?
  • 我的问题是如何在单个查询中将所有更新数据插入到临时表中?插入查询的数量取决于输入值的数量。那么sql SP中有没有办法接受可变数量的输入值来将行插入到表中?
猜你喜欢
  • 2012-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多