Ошибка округления с расширением SQL CLR (определяемый пользователем агрегат) - PullRequest
0 голосов
/ 27 февраля 2011

Я пишу несколько пользовательских расширений .Net для SQL Server 2008. Одним из них является пользовательский агрегат, который должен агрегировать набор десятичных чисел в десятичное значение.

Чтобы сузить мою проблемуЯ использую простой Const агрегат, который просто возвращает постоянное десятичное значение.При добавлении этого в качестве пользовательского агрегата в SQL Server возвращаемые значения всегда округляются:

SELECT dbo.Const(n, 2.5) from (select 1 n) x -- returns 3, not 2.5

Что мне не хватает?

Вот код:

using System;
using System.Data.SqlTypes;
using System.IO;
using Microsoft.SqlServer.Server;
using SqlServer.Clr.Extensions.Aggregates.Implementation;

[Serializable]
[SqlUserDefinedAggregate(Format.UserDefined,MaxByteSize = -1)]
public class Const : IBinarySerialize
{
    private decimal _constValue;

    public void Init() {}

    public void Accumulate(SqlDecimal value, SqlDecimal constValue)
    {
        _constValue = constValue.Value;
    }

    public void Merge(Const value) {}

    public SqlDecimal Terminate()
    {
        return new SqlDecimal(_constValue);
    }

    public void Read(BinaryReader r)
    {
        _constValue = r.ReadDecimal();
    }

    public void Write(BinaryWriter w)
    {
        w.Write(_constValue);
    }
}

Скомпилируйте этот код в сборку с именем SqlServer.Clr.Extensions.dll.Следующий скрипт можно использовать для добавления его в SQL Server и проверки непредвиденного поведения:

use [MyDb] -- replace with your db name
go

-- drop the Const aggregate if it exists
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[Const]'))
    DROP AGGREGATE [Const]
GO
-- drop the assembly if it exists
IF  EXISTS (SELECT * FROM sys.assemblies asms WHERE asms.name = N'SqlServer.Clr.Extensions' and is_user_defined = 1)
    DROP ASSEMBLY [SqlServer.Clr.Extensions]
GO

-- import the assembly
CREATE ASSEMBLY [SqlServer.Clr.Extensions]
AUTHORIZATION [dbo]
    FROM 'C:\Path\To\SqlServer.Clr.Extensions.dll'
WITH PERMISSION_SET = SAFE
GO

CREATE AGGREGATE [Const](@input decimal, @constValue decimal)
    RETURNS decimal
    EXTERNAL NAME [SqlServer.Clr.Extensions].[Const] -- put the Const class is in the global namespace
GO

SELECT dbo.Const(n, 2) from (select 1 n) x
SELECT dbo.Const(n, 2.5) from (select 1 n) x

1 Ответ

1 голос
/ 27 февраля 2011

Вы должны изменить @constvalue decimal на @constvalue decimal(13,2) в

Create aggregate [const](@input decimal, @constvalue decimal)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...