Почему мой разделитель не появляется в окончательном результате? Это инициализируется, чтобы быть запятой, но я только получаю ~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
Бит для ОТЛИЧНОГО хорошо работает, но он работает в Накапливать объеме...
Вывод:
article_id | col
-------------------------------------------------
1 | a a b c
Обновление: избыточное пространство между значениями - то, потому что столбец столь же определил как 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());
}
}
}
Почему вышеупомянутое решает мою проблему? И почему это не позволило бы мне использовать больше чем один w.write
призвать в К циклу?
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
}
Проблема в том, что вы не сериализуете разделитель. Добавьте:
w.Write(delimiter)
в качестве первой строки в методе записи и
delimiter = r.ReadString();
в качестве первой строки в методе чтения.
Относительно ваших вопросов к предлагаемому обходному пути:
Почему это решает мою проблему?
Нет. Он просто работал с вашим тестовым сценарием.
И почему бы мне не использовать более одного вызова w.write внутри цикла FOR?
Метод записи должен быть совместим с методом чтения. Если вы напишете две строки и прочитаете только одну, это не сработает. Идея здесь в том, что ваш объект может быть удален из памяти, а затем загружен. Это то, что должны делать Write и Read. В вашем случае - это действительно происходило, и вы не смогли сохранить значение объекта.