无法将参数值从Binary转换为Byte []。 -带有SQL时间戳参数的SqlDataSource

时间:2019-01-11 07:44:52

标签: c# arrays sql-server sqldatasource sql-timestamp

首先,不幸的是,我无法更改数据库并寻找“费时的”解决方案。我意识到我要的不是最佳实践,而是足够的免责声明...

  1. MS SQL Server
  2. C#/ .NET 4.xx
  3. WebForms
  4. dbo.MyTable-不允许应用直接访问表
  5. dbo.MyTable_ [OP] CRUD系列存储过程(_GET,_INSERT,_UPDATE等)
  6. MyTable的时间戳列为“ ts”

在适当的情况下,CRUD进程都包含@ts的输入/输出参数,以避免并发问题。

我正在使用DevExpress WebForms GridView-完美运行,而不是问题。

GridView正在使用MS SqlDataSource。它的选择命令正在调用MyTable_List proc。它的插入命令将调用MyTable_Insert proc。两者都能完美地工作。

不是更新。上网浏览并尝试找出是否有可能。所以更新基本上是这样:

SQL:

CREATE PROC MyTable_Update
  @key int
  @name varchar(100)
  @ts timestamp output
AS
  IF (SELECT TOP 1 1 FROM MyTable WHERE key = @key and ts = @ts) IS NULL 
BEGIN
   RAISEERROR('someone else changed this, reload, try again, 00, 00);
   RETURN;
END
--[simple update the table logic]
SELECT @ts = ts FROM MyTable WHERE key = @key

数据源:

<asp:SqlDataSource id="ds" runat="server" ... OnUpdating="ds_Updating" UpdateCommand="MyTable_UPDATE" UpdateCommandType="StoredProcedure">
  <UpdateParameters>
    <asp:Parameter Name="key" Type="Int32" />
    <asp:Parameter Name="name" Type="String" />
    <asp:Parameter Direction="InputOutput" Name="ts" Type="String" DefaultValue="0" />  <!-- i know, bear with me -->
   </UpdateParameters>
 </asp:SqlDataSource>

C#:

protected void myGrid_StartRowEditing(object sender, [DevEx].ASPxStartRowEditingEventArgs e)
{  
  //get the timestamp value from the db for this row being edited
  int key = (Int32)myGrid.GetRowValuesByKeyValue(e.EditingKeyValue, "key");
  var ts = db.MyTable_Get(key).First().ts; //actually getting the ts from the database
  Session["MyTable_ts"] = ts;
}

protected void ds_Updating(object sender, SqlDataSourceCommandEventArgs e)
{ 
  //override what was set in the aspx
  var p = e.Command.Parameters["@ts"];
  p.DbType = Binary;
  p.Direction = ParameterDirection.InputOutput;
  p.Size = 8;
  var ts = (System.Data.Linq.Binary)Session["MyTable_ts"];
  p.Value = ts;
}

最后,当我开始在网格中的一行上进行编辑时,将启动StartRowEditing,并按预期方式将db中的时间戳值保存到会话var中(显然,.NET中的格式与SQL不同)。当我尝试提交更改(在De​​vEx网格编辑器上单击“更新”)时,ts_Updating触发,所有代码无一例外地完成。然后,当SqlDataSource触发实际更新时,它抛出“无法从中转换参数值”到DevEx网格的“二进制到字节[]”。并通过网格的UI进行报告。

我如何(甚至有可能?)将db时间戳值改组为会话,然后通过SqlDataSource更新参数发送它?

同样,我意识到我可以通过写出所有CSLA甚至只使用ObjectDataSource并写出所有更新逻辑来克服这个问题,但是我花了一些时间来完成一些网格并移动和移动继续-在项目中炸更大的鱼。

谢谢!

1 个答案:

答案 0 :(得分:1)

想通了-很愚蠢,我却忽略了它。 System.Data.Linq.Binary的ToArray()将转换为Byte []。在函数的最后一行上向ts添加.ToArray()将转换为SqlDataSource可以传递回数据库的适当类型,从而允许Timestamp值匹配,从而通知db没有并发问题。

protected void ds_Updating(object sender, SqlDataSourceCommandEventArgs e)
{ 
  //override what was set in the aspx
  var p = e.Command.Parameters["@ts"];
  p.DbType = Binary;
  p.Direction = ParameterDirection.InputOutput;
  p.Size = 8;
  var ts = (System.Data.Linq.Binary)Session["MyTable_ts"];
  p.Value = ts.ToArray();  //Binary must be cast to an Array (of Byte)
}