【发布时间】:2012-04-06 20:02:14
【问题描述】:
设置:将 DataReader 加载到 DataTable 中。加载后尝试更改 DataTable 中的列。
问题:尝试更改列时触发 ReadOnlyException。
条件:
- 当函数(udf 或系统)应用于别名列时 在存储过程中,该列变为 ReadOnly。
- 如果列只是简单的别名而没有应用任何函数,则不会触发错误。
- 如果将选择移动到表函数,则不会触发错误,然后 proc 从该函数中选择。
- 在 C# 中将列属性设置为 ReadOnly 时(显然)不会发生错误。
问题:有没有办法改变一个过程,使一个应用了函数的别名列不是只读的?我正在寻找一种替代方法来更改 C# 或创建一个函数来执行 proc 已经执行的操作。
C#:
var dt = new DataTable();
using( var sqlDR = objDocsFBO.GetActiveDocsMerged(KeyID) )
{
dt.Load(sqlDR);
}
foreach( DataRow dr in dt.Rows )
{
//Testing Alias Alone - Pass
dr["DocumentPathAlias"] = "file:///" + Server.UrlEncode(dr["DocumentPathAlias"].ToString()).Replace("+", "%20");
//Testing Function Applied - Fail
//dr["DocumentPath"] = "file:///" + Server.UrlEncode(dr["DocumentPath"].ToString()).Replace("+", "%20");
}
SQL:
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[usp_ActiveDocs_RetrieveMerged]
@KeyID INT
AS
BEGIN
--Testing Select From Function
--SELECT * FROM dbo.ufn_ActiveDocs_RetrieveMerged(@KeyID) --Pass
SELECT AD.ADMergeLogID
, AD.TemplateName
, CONVERT(NVARCHAR(10), AD.InitiatedOn, 101) [CreatedOn]
, (SELECT fn.UserName FROM dbo.ufn_User_GetFullName(AD.InitiatedBy) fn) [CreatedBy]
, AD.DocumentName
, AD.DocumentPath [DocumentPathAlias] --Pass
--, REPLACE(AD.DocumentPath, '\\', '\') [DocumentPath] --Fail
--, dbo.udf_VerifyPath(AD.DocumentPath) [DocumentPath] --Fail
FROM dbo.ActiveDocsMergeLog AD
WHERE AD.DocumentPath != 'DocumentPath not found.'
AND AD.KeyID = @KeyID
END
【问题讨论】:
-
它会更新什么?由于列只是函数的结果,代码将写入什么?
-
存储过程只运行一个
SELECT。列在哪里需要读/写? -
@JoshuaDrake 一旦查询的结果在 DataTable 中,列就有了它们的值,而代码并不关心这些值来自哪里。它确实尊重列的任何属性。问题不直接与正在写入的列有关(在设置 ReadOnly = false 时可以)。我猜 SQL 会在计算列上应用默认的 ReadOnly,无论该列是在表、视图、过程还是函数中。我希望有一个设置来覆盖它。
-
@AaronBertrand 我正在尝试更改 C# 中的列值。
-
我以为你已经注意到当它在一个表中时它没有遇到问题,你能否进一步解释你的陈述:如果将select移到a,则不会触发错误表函数.
标签: c# sql-server-2008 tsql