CLR:多参数聚合,参数不是最终输出?

OMG*_*ies 5 .net c# clr sql-server-2008

为什么我的分隔符没有出现在最终输出中?它被初始化为一个逗号,但我只在每个属性之间获得~5个空格:

  SELECT [article_id]
         , dbo.GROUP_CONCAT(0, t.tag_name, ',') AS col
    FROM [AdventureWorks].[dbo].[ARTICLE_TAG_XREF] atx
    JOIN [AdventureWorks].[dbo].[TAGS] t ON t.tag_id = atx.tag_id
GROUP BY article_id
Run Code Online (Sandbox Code Playgroud)

DISTINCT的位工作正常,但它在Accumulate范围内运行...

输出:

article_id  |  col
-------------------------------------------------
1           |  a         a         b         c         
Run Code Online (Sandbox Code Playgroud)

更新:值之间的空间过大是因为列定义为NCHAR(10),因此输出中将出现10个字符.愚蠢的错误在我身上......


有了Martin Smith对使用该Write(BinaryWriter w)方法的帮助,这个更新对我有用:

public void Write(BinaryWriter w)
{
    w.Write(list.Count);
    for (int i = 0; i < list.Count; i++ )
    {
        if (i < list.Count - 1)
        {
            w.Write(list[i].ToString() + delimiter);
        }
        else 
        {
            w.Write(list[i].ToString());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

问题:


为什么以上解决了我的问题?为什么它不允许我w.write在FOR循环中使用多个调用?

C#代码:


using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Xml.Serialization;
using System.Xml;
using System.IO;
using System.Collections;
using System.Text;

[Serializable]
[SqlUserDefinedAggregate(Format.UserDefined, MaxByteSize = 8000)]
public struct GROUP_CONCAT : IBinarySerialize
{
    ArrayList list;
    string delimiter;

    public void Init()
    {
        list = new ArrayList();
        delimiter = ",";
    }

    public void Accumulate(SqlBoolean isDistinct, SqlString Value, SqlString separator)
    {
        delimiter = (separator.IsNull) ? "," : separator.Value ;

        if (!Value.IsNull)
        {
            if (isDistinct)
            {
                if (!list.Contains(Value.Value))
                {
                    list.Add(Value.Value);
                }
            }
            else
            {
                list.Add(Value.Value);
            }            
        }
    }

    public void Merge(GROUP_CONCAT Group)
    {
        list.AddRange(Group.list);
    }

    public SqlString Terminate()
    {
        string[] strings = new string[list.Count];

        for (int i = 0; i < list.Count; i++)
        {
            strings[i] = list[i].ToString();
        }

        return new SqlString(string.Join(delimiter, strings));
    }

    #region IBinarySerialize Members

    public void Read(BinaryReader r)
    {
        int itemCount = r.ReadInt32();
        list = new ArrayList(itemCount);

        for (int i = 0; i < itemCount; i++)
        {
            this.list.Add(r.ReadString());
        }
    }

    public void Write(BinaryWriter w)
    {
        w.Write(list.Count);
        foreach (string s in list)
        {
            w.Write(s);
        }
    }
    #endregion
}
Run Code Online (Sandbox Code Playgroud)

ags*_*mek 5

这里的问题是你没有序列化分隔符.加:

w.Write(delimiter)
Run Code Online (Sandbox Code Playgroud)

作为Write方法的第一行和

delimiter = r.ReadString();
Run Code Online (Sandbox Code Playgroud)

作为Read方法的第一行.

关于建议解决方案的问题:

为什么以上解决了我的问题?

它不是.它只适用于您的测试场景.

为什么它不允许我在FOR循环中使用多个w.write调用?

Write方法需要与Read方法兼容.如果你写两个字符串并且只读一个字符串那么它就不会起作用.这里的想法是你的对象可能会从内存中删除然后加载.这就是Write和Read应该做的事情.在你的情况下 - 这确实发生了,你无法保持对象的价值.