Field order on #region IBinarySerialize

97 Views Asked by At

I created IBinarySerialize region in order to create my CLR for my user defined aggregate. I am trying to replicate my XIRR function in C# just to learn how to work with CLRs. I put Write and Read in the same order but when I tried to build I get Error:

Severity Code Description Project File Line Suppression State
Error CS1503 Argument 1: cannot convert from 'System.Data.SqlTypes.SqlDateTime' to 'bool' CustomAggregates D:\Transfer\CustomSqlAggregates\CustomAggregates\XIRR.cs 255 Active

The error is coming in from the write section.

I can't seem to find what I am missing in this arrangement following some examples that I have seen in examples. Here is the get/set for the struct

[Serializable]
[SqlUserDefinedAggregate(
    Format.Native,
    IsInvariantToDuplicates = false, // Receiving the same value again changes the result
    IsInvariantToNulls = false,      // Receiving a NULL value changes the result
    IsInvariantToOrder = true,      // The order of the values affects the result
    IsNullIfEmpty = true,            // If no values are given the result is null
    MaxByteSize = -1,                // Maximum size of the aggregate instance. -1 represents a value larger than 8000 bytes, up to 2 gigabytes
    Name = "XIRR"             // Name of the aggregate
    )]
public struct XIRR : IBinarySerialize
{

    /// <summary>
    /// Used to store the product
    /// </summary>
    public SqlDouble Result { get; private set; }
    public SqlDouble Cashflow { get; private set; }
    public SqlDateTime CashflowDateTime { get; private set; }
    public bool HasValue { get; private set; }
    public List<CashItem> CashFlows { get; private set;}

    ...

    #region IBinarySerialize
    /// <summary>
    /// Writes the values to the stream in order to be stored
    /// </summary>
    /// <param name="write">The BinaryWriter stream</param>
    public void Write(System.IO.BinaryWriter write)
    {
        write.Write(Result);
        write.Write(Cashflow); //Line - 255
        write.Write(CashflowDateTime);
        write.Write(HasValue);
    }
    /// <summary>
    /// Reads the values from the stream
    /// </summary>
    /// <param name="read">The BinaryReader stream</param>
    public void Read(System.IO.BinaryReader read)
    {
        Result = new SqlDouble(read.ReadDouble());
        Cashflow = new SqlDouble(read.ReadDouble());
        CashflowDateTime = new SqlDateTime(Convert.ToDateTime(read.ReadString()));
        HasValue = read.ReadBoolean();
    }
    #endregion IBinarySerialize
}

Thanks in advance.

Please let me know if you want me to provide further information.

1

There are 1 best solutions below

6
Solomon Rutzky On

The problem is most likely a mismatch in your types. What are the exact types of Result, Cashflow, and CashflowDateTime? According to the Read method they are Sql* types. Is that really how they are declared? Or are they declared as Double and DateTime?

At the very least I think you are handling the CashflowDateTime incorrectly in both directions. Assuming that CashflowDateTime is truly a SqlDateTime, then I am guessing that you might need to replace this line in the Write method:

write.Write(CashflowDateTime);

with the following two lines:

write.Write(CashflowDateTime.DayTicks);
write.Write(CashflowDateTime.TimeTicks);

And then, replace this line in the Read method:

CashflowDateTime = new SqlDateTime(Convert.ToDateTime(read.ReadString()));

with the following (which reconstructs the SqlDateTime from the "DayTicks" and "TimeTicks" values):

CashflowDateTime = new SqlDateTime(read.ReadInt32(), read.ReadInt32());

Also:

  1. The #region IBinarySerialize doesn't do anything functional here. Removing that would not affect the code.
  2. For more info on working with SQLCLR, please see: SQLCLR Info