@IT会議室は、ITエンジニアに特化した質問・回答コミュニティ「QA@IT」に生まれ変わりました。ぜひご利用ください。
- PR -

SQLCLRテーブル値関数の中でデータアクセス

1
投稿者投稿内容
ばた
会議室デビュー日: 2006/08/22
投稿数: 2
投稿日時: 2006-08-22 13:52
皆さんこんにちは。初投稿です。緊張しています。。。
不束者ですが、宜しくお願いします(>_<)

SQLCLRのテーブル値関数の中でADOでのデータアクセスを行おうと調査していますが、エラーになってしまいます。
コンパイルはOKで、SQLServerManagementStudioのクエリウィンドウで実行すると下記エラーが発生します。
-------------------------------------------------------------------------
メッセージ 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:
-------------------------------------------------------------------------

何かしらのアドバイスを頂きたいと思い、投稿しました。

下記サイトを参考にしました。
http://msdn2.microsoft.com/ja-jp/library/ms165054.aspx

下記にテストしたソースを添付します。
TestFunc0001()は、通常のファンクションでのデータアクセスの調査で作成したものです。
(TestFunc0001()だけは、期待通りに動いてくれました。)

コード:
using System;
using System.Data;
using System.Data.Sql;
using System.Data.SqlTypes;
using System.Collections;
using System.Data.SqlClient;
using Microsoft.SqlServer.Server;

public partial class UserDefinedFunctions
{
    [SqlFunction(DataAccess = DataAccessKind.Read)]
    public static SqlString TestFunc0001()
    {
        DataSet ds = new DataSet();
        string cmdText = "select UserGroupName from ProtoUserGroupMember";

        using (SqlConnection cn = new SqlConnection("context connection=true"))
        using (SqlCommand cm = new SqlCommand(cmdText, cn))
        using (SqlDataAdapter da = new SqlDataAdapter(cm))
        {
            da.Fill(ds);
        }
        return ds.Tables[0].Rows.Count.ToString();
    }
    
    struct primeIndex
    {
        public string UserGroupName;
        public primeIndex(string u)  
        {
            this.UserGroupName = u;
        }
    }

    [SqlFunction(DataAccess = DataAccessKind.Read, 
                 FillRowMethodName = "FillRow", 
                 TableDefinition = "UserGroupName nvarchar(50)")]
    public static IEnumerable TableOfPrimes(string userName)
    {
        DataSet ds = new DataSet();
        string cmdText = "select UserGroupName from ProtoUserGroupMember";

        using (SqlConnection cn = new SqlConnection("context connection=true"))
        using (SqlCommand cm = new SqlCommand(cmdText, cn))
        using (SqlDataAdapter da = new SqlDataAdapter(cm))
        {                
            da.Fill(ds);
        }

        for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
        {
            yield return new primeIndex(ds.Tables[0].Rows[i][0].ToString());
        }
    }

    private static void FillRow(object source, out string UserGroupName)
    {
        primeIndex pi = (primeIndex)source;
        UserGroupName = pi.UserGroupName;
    }
};


ばた
会議室デビュー日: 2006/08/22
投稿数: 2
投稿日時: 2006-08-22 17:37
動くようになりました(>_<)ノ
まだ細かい原因ははっきりしませんが...

データアクセスの仕方が悪いのかと思っていたら、そうではないようです。
DataSetやDataTableを使っているメソッドでyield returnを記述しているのがエラー発生の原因?(曖昧です)のようです。

んで、下記のように修正したら期待通りの動きをしてくれました。


コード:
using System;
using System.Data;
using System.Data.Sql;
using System.Data.SqlTypes;
using System.Collections;
using System.Data.SqlClient;
using Microsoft.SqlServer.Server;

public partial class UserDefinedFunctions
{
    [SqlFunction(DataAccess = DataAccessKind.Read,
                 FillRowMethodName = "FillRow",
                 TableDefinition = "UserGroupName nvarchar(50)")]
    public static IEnumerable TableOfPrimes(string userName)
    {
        DataSet ds = new DataSet();
        string cmdText = "select UserGroupName from ProtoUserGroupMember";

        using (SqlConnection cn = new SqlConnection("context connection=true"))
        using (SqlCommand cm = new SqlCommand(cmdText, cn))
        using (SqlDataAdapter da = new SqlDataAdapter(cm))
        {
            da.Fill(ds);
        }

        return ds.Tables[0].Rows;
    }

    private static void FillRow(object source, out string UserGroupName)
    {
        UserGroupName = ((DataRow)source)[0].ToString();
    }
};


1

スキルアップ/キャリアアップ(JOB@IT)