2016-03-07 80 views
1

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

我用来执行数据库更新的代码如下。对于更新的工艺类型的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][email protected] 
       ,[CraftTypeDescription][email protected] 
      WHERE [email protected]     
      SET @rowcount1 = @@ROWCOUNT 
     IF @rowcount1 =0 
      SELECT -167; 
     ELSE 
      SELECT 167;   
     END 
END 

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

感谢您的帮助.....

+0

我认为你可以在这里使用事务,所以它会更新全部或失败,假设你不想在环路之间更新失败时部分更新记录。 –

+0

我可以在哪里设置交易?由于存储过程是在C#循环内部调用的,因此它的作用域在sp的每次执行中都会得到正确的结果。 那么我如何识别sp的前一次执行是否已完成回滚? – Bimzee

+0

你可以在SQL Server中设置事务,这篇文章可以帮助http://www.codeproject.com/Articles/4451/SQL-Server-Transactions-and-Error-Handling –

回答

0

我需要更新的行成功更新数量的网页API输出和发生更新失败的行数。

你可以用下面的例子输出clause..see这给你一些想法

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 [email protected] 
    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 @[email protected]+1 END 

正如你可以在上面的脚本中看到,在100个行发生错误,我输出更新的行数和数量使用while循环,总之,你需要传递的数据表存储proc.So这里是一般的步骤,这失败可以成为你的阵列或列表减去此行...

用了..的

1 。创建类型表
2.convert数组或列表中的数据表
3.Pass数据表来存储过程

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

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 

希望这有助于

+0

做的“TABLE test1234”是一个临时表? @TheGameiswar 有没有办法把它放在单个存储过程中? 还有一个问题。如何在c#代码中不使用循环的情况下将完整的数据插入test1234 ? – Bimzee

+0

是的,这是一个温度,我没有得到这部分有一种方法可以把它放在单个存储过程? TheGameiswar

+0

我的问题是如何将所有更新数据插入到单个查询中的临时表中? 插入查询的数量因输入值的数量而异。 那么是否有一种方法在SQL SP中接受可变数量的输入值以将行插入表中? – Bimzee