Soci (Soczó Zsolt) szakmai blogja

2010.01.27.

SQLCLR deplyment hiba

Filed under: .NET,Adatbázisok,ADO.NET,SQL Server 2005,SQL Server 2008,Szakmai élet — Soczó Zsolt @ 10:24

Error: Incorrect syntax near valami.
Akkor jön elő, ha az SQLCLR assemblyt és benne a függvényeket akarja az VS deployolni. Több oka lehet, most az volt, hogy egy .NET oldalon double-t visszaadó függvény véletlenül így lett deklarálva:

[SqlFunction(…, TableDefinition = “Datum datetime, Szazalek double”)]

Mi a hiba benne? SQL Serverben nincs double, csak real és float. Ráadásul a C# float az az SQL real és a C# double az SQL Server float (kb.). :)

Az előbbi helyesen:

[SqlFunction(…, TableDefinition = “Datum datetime, Szazalek float”)]

Miért kellett SQLCLR függvényt írni? A futó aggregálások (én legalábbis nem tudok jobbat kurzor nélkül) o(n2)-es algoritmusok, ezt CLR-ben könnyen meg lehet írni o(n)-re. Pl:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public class UserDefinedFunctions
{
internal class Result
{
public long RowId;
public double CumDollarGain;
public double TopDollarGain;
public double DollarDrawDown;
}

//Input table: create table #trades(RowId long, DollarGain money, other columns possible)
[SqlFunction(FillRowMethodName = “FillRow”, DataAccess = DataAccessKind.Read,
TableDefinition = “RowId bigint, CumDollarGain float, TopDollarGain float, DollarDrawDown float”)]
public static IEnumerable Cumul()
{
using (var conn = new SqlConnection(“Context connection=true”))
{
using (var cmd = new SqlCommand(“select RowID, DollarGain from #trades”, conn))
{
var res = new List();
conn.Open();
double cumulPrice = 0, topPrice = 0, drawDawn = 0;

using (SqlDataReader r = cmd.ExecuteReader())
{
int idCol = r.GetOrdinal(“RowID”);
int gainCol = r.GetOrdinal(“DollarGain”);

while (r.Read())
{
var price = r.GetDouble(gainCol);

cumulPrice += price;
topPrice = Math.Max(price, topPrice);

drawDawn += price;
drawDawn = Math.Min(drawDawn, 0);

res.Add(new Result
{
RowId = r.GetInt64(idCol),
CumDollarGain = cumulPrice,
TopDollarGain = topPrice,
DollarDrawDown = drawDawn
});
}
return res;
}
}
}
}
public static void FillRow(object obj,
out long id,
out double cumDollarGain,
out double topDollarGain,
out double dollarDrawDown)
{
var r = (Result)obj;
id = r.RowId;
cumDollarGain = r.CumDollarGain;
topDollarGain = r.TopDollarGain;
dollarDrawDown = r.DollarDrawDown;
}
};

Sajnos nem lehet átpasszolni a megnyitott SqlDataReadert a két metódus között, ezért kénytelen az ember letárolni az eredményhalmazt. Persze pár ezer sornál ez nem gond.

3 Comments

  1. Ezt nem ertem. Elvben ugye a SQL2k8 majdnem teljesen dotnetbe irodott. A SQLCLR mint olyan szinten dotnet. Ket dotnet alkalmazas kozt miert nem lehet egyutasan deployolni a kulonbozo szamabrazolasi tipusokat? Biztos megint en nem ertek valamit.

    Comment by hrongyorgy — 2010.01.27. @ 20:59

  2. Az attributumos leírásban sql típusokat kell használni. Attól, hogy .net integrált az sql server a belső típusaik, amiket táblákban használunk még nem változtak.
    Az SQL 2008 nem .netben íródott, csak a kliens eszközök. A szerve maga csuma natív, kivéve a .net illesztést.

    Comment by Soczó Zsolt — 2010.01.27. @ 22:26

  3. Hat ja, attributumban stringkent meg azt a keves pszeudo-tipusossagot is elvesziti az ember, amit a stored procedure nyujt.

    Comment by Szindbad — 2010.01.28. @ 21:48

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

Powered by WordPress