



















今天看了下SQL SERVER 2005 CLR Integration (SQL SERVER 2005 CLR 集成),如是尝试写个例子看看:
仅仅将一个表的数据通过C#写的方法读出来,代码如下:
[SqlFunction(Name = "f_test", FillRowMethodName = "fillRows", TableDefinition = "a int,b int,c nvarchar(5)")]
public static IEnumerable GetData()
{
using (SqlConnection connection = new SqlConnection("context connection=true;"))
{
connection.Open();
SqlCommand cmd = new SqlCommand("select id,t_id,t_name from temp", connection);
SqlDataReader datareader = cmd.ExecuteReader();
while (datareader.Read())
yield return datareader;
}
}static void fillRows(object obj, ref SqlInt32 a, ref SqlInt32 b, ref SqlString c)
{
if (null != obj)
{
SqlDataReader reader = (SqlDataReader)obj;
a = reader.GetSqlInt32(0);
b = reader.GetSqlInt32(1);
c = reader.GetSqlString(2);
}
}
编译后,直接部署,执行
select * from dbo.f_test()
期待的结果没出现,报错了:
消息 6260,级别 16,状态 1,第 1 行
从用户定义的表值函数获取新行时出错:
System.InvalidOperationException: Data access is not allowed in this context. Either the context is a function or method not marked with DataAccessKind.Read or SystemDataAccessKind.Read, is a callback to obtain data from FillRow method of a Table Valued Function, or is a UDT validation method.
System.InvalidOperationException:
at System.Data.SqlServer.Internal.ClrLevelContext.CheckSqlAccessReturnCode(SqlAccessApiReturnCode eRc)
at System.Data.SqlServer.Internal.ClrLevelContext.GetDatabase(SmiEventSink sink, Int32* pcbLen, IntPtr* ppwsName)
at Microsoft.SqlServer.Server.InProcConnection.GetCurrentDatabase(SmiEventSink eventSink)
at System.Data.SqlClient.SqlInternalConnectionSmi.Activate()
at System.Data.SqlClient.SqlConnectionFactory.GetContextConnection(SqlConnectionString options, Object providerInfo, DbConnection owningConnection)
at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection)
at System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup)
at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
at System.Data.SqlClient.SqlConnection.Open()
at UserDefinedFunctions.<GetData>d__0.MoveNext()
。
通过提示,修改SqlFunction属性为:
[SqlFunction(DataAccess = DataAccessKind.Read, Name = "f_test", FillRowMethodName = "fillRows", TableDefinition = "a int,b int,c nvarchar(5)")]
和
[SqlFunction(DataAccess = DataAccessKind.Read, SystemDataAccess = SystemDataAccessKind.Read, Name = "f_test", FillRowMethodName = "fillRows", TableDefinition = "a int,b int,c nvarchar(5)")]
重新部署,执行查询,依然报那个错.......仔细看了下错误详情,里面有:UserDefinedFunctions.<GetData>d__0.MoveNext(),我决定使用Reflector.exe看看编译后究竟是啥玩意,反编译后的东西为:
public class UserDefinedFunctions
{
// Methods
private static void fillRows(object obj, ref SqlInt32 a, ref SqlInt32 b, ref SqlString c)
{
if (null != obj)
{
SqlDataReader reader = (SqlDataReader) obj;
a = reader.GetSqlInt32(0);
b = reader.GetSqlInt32(1);
c = reader.GetSqlString(2);
}
}
[SqlFunction(DataAccess
=DataAccessKind.Read, Name="f_test", FillRowMethodName="fillRows", TableDefinition="a int,b int,c nvarchar(5)")] [DebuggerHidden]
IEnumerator
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
[DebuggerHidden]
void IEnumerator.Reset()看到这写代码,恍然大悟.....编译器将实际访问数据库的代码移到它自己生成的 MoveNext 方法了,而这个方法并没有SqlFunctionAttribute声明,所以报ata access is not allowed in this context.错了.
将代码修改如下:
[SqlFunction(DataAccess = DataAccessKind.Read, Name = "f_test", FillRowMethodName = "fillRows", TableDefinition = "a int,b int,c nvarchar(5)")]
public static IEnumerable GetData()
{
IList<Item> items = new List<Item>();using (SqlConnection connection = new SqlConnection("context connection=true;"))
{
connection.Open();
SqlCommand cmd = new SqlCommand("select id,t_id,t_name from temp", connection);
SqlDataReader datareader = cmd.ExecuteReader();
while (datareader.Read())
items.Add(new Item(datareader));
}
return items;
}static void fillRows(object obj, ref SqlInt32 a, ref SqlInt32 b, ref SqlString c)
{
if (null != obj)
{
Item item = (Item)obj;
a = item.id;
b = item.t_id;
c = item.t_name;
}
}struct Item
{
public readonly SqlInt32 id;
public readonly SqlInt32 t_id;
public readonly SqlString t_name;
public Item(SqlDataReader reader)
{
this.id = reader.GetSqlInt32(0);
this.t_id = reader.GetSqlInt32(1);
this.t_name = reader.GetSqlString(2);
}
}
执行查询,预期结果出现....
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。