Я предполагаю, что вы используете SQL Server 2008. Как упомянул сотрудник Microsoft на на этой странице , 2008 требует, чтобы методы отмечались с помощью DataAccessKind. Читать намного чаще, чем в 2005 году. Один из такихвремя, когда TVF участвует в транзакции (что, казалось, всегда имело место, когда я тестировал).Решение состоит в том, чтобы указать enlist=false
в строке подключения, которая, увы, не может быть объединена с context connection=true
.Это означает, что ваша строка соединения должна быть в типичном клиентском формате: Data Source=.;Initial Catalog=MyDb;Integrated Security=sspi;Enlist=false
, а ваша сборка должна быть создана как минимум с permission_set=external_access
.Следующие работы:
using System;
using System.Collections;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
namespace SqlClrTest {
public static class Test {
[SqlFunction(
DataAccess = DataAccessKind.Read,
SystemDataAccess = SystemDataAccessKind.Read,
TableDefinition = "RowNumber int",
FillRowMethodName = "FillRow"
)]
public static IEnumerable MyTest(SqlInt32 databaseID) {
using (var con = new SqlConnection("data source=.;initial catalog=TEST;integrated security=sspi;enlist=false")) {
con.Open();
using (var cmd = new SqlCommand("select top (100) RowNumber from SSP1 where DatabaseID = @DatabaseID", con)) {
cmd.Parameters.AddWithValue("@DatabaseID", databaseID.IsNull ? (object)DBNull.Value : databaseID.Value);
using (var reader = cmd.ExecuteReader()) {
while (reader.Read())
yield return reader.GetInt32(0);
}
}
}
}
public static void FillRow(object obj, out SqlInt32 rowNumber) {
rowNumber = (int)obj;
}
}
}
Вот то же самое в F #:
namespace SqlClrTest
module Test =
open System
open System.Data
open System.Data.SqlClient
open System.Data.SqlTypes
open Microsoft.SqlServer.Server
[<SqlFunction(
DataAccess = DataAccessKind.Read,
SystemDataAccess = SystemDataAccessKind.Read,
TableDefinition = "RowNumber int",
FillRowMethodName = "FillRow"
)>]
let MyTest (databaseID:SqlInt32) =
seq {
use con = new SqlConnection("data source=.;initial catalog=TEST;integrated security=sspi;enlist=false")
con.Open()
use cmd = new SqlCommand("select top (100) RowNumber from SSP1 where DatabaseID = @DatabaseID", con)
cmd.Parameters.AddWithValue("@DatabaseID", if databaseID.IsNull then box DBNull.Value else box databaseID.Value) |> ignore
use reader = cmd.ExecuteReader()
while reader.Read() do
yield reader.GetInt32(0)
} :> System.Collections.IEnumerable
let FillRow (obj:obj) (rowNumber:SqlInt32 byref) =
rowNumber <- SqlInt32(unbox obj)
Хорошая новость: Microsoft считает это ошибкой .