Я использую XmlDictionaryWriter для сериализации объектов в базе данных с помощью сериализатора контрактов данных. Он отлично работает, размер и скорость в 2 раза лучше, чем при использовании text / xml.
Однако мне придется иметь дело с огромным количеством записей в моей базе данных, где любые лишние байты напрямую переводятся в гигабайты Размер БД. Вот почему я хотел бы еще больше уменьшить размер, используя словарь XML.
Как мне это сделать?
Я вижу, что статический метод XmlDictionaryWriter.CreateBinaryWriter принимает 2-й параметр типа IXmlDictionary. В MSDN говорится: «Словарь XmlDictionary для использования в качестве общего словаря».
Сначала я попытался использовать реализацию, поставляемую системой:
XmlDictionary dict = new XmlDictionary();
string[] dictEntries = new string[]
{
"http://schemas.datacontract.org/2004/07/MyContracts",
"http://www.w3.org/2001/XMLSchema-instance",
"MyElementName1",
"MyElementName2",
"MyElementName3",
};
foreach ( string s in dictEntries )
dict.Add( s );
В результате .NET framework полностью игнорирует словарь и по-прежнему вставляет указанные выше строки как простой текст, а не просто ссылка на соответствующую запись словаря.
Затем я создал свою собственную реализацию IXmlDictionary:
class MyDictionary : IXmlDictionary
{
Dictionary<int, string> values = new Dictionary<int, string>();
Dictionary<string, int> keys = new Dictionary<string, int>();
MyDictionary()
{
string[] dictEntries = new string[]
{
"http://schemas.datacontract.org/2004/07/MyContracts",
"http://www.w3.org/2001/XMLSchema-instance",
"MyElementName1",
"MyElementName2",
"MyElementName3",
};
foreach ( var s in dictEntries )
this.Add( s );
}
static IXmlDictionary s_instance = new MyDictionary();
public static IXmlDictionary instance { get { return s_instance; } }
void Add( string val )
{
if ( keys.ContainsKey( val ) )
return;
int id = values.Count + 1;
values.Add( id, val );
keys.Add( val, id );
}
bool IXmlDictionary.TryLookup( XmlDictionaryString value, out XmlDictionaryString result )
{
if ( value.Dictionary == this )
{
result = value;
return true;
}
return this.TryLookup( value.Value, out result );
}
bool IXmlDictionary.TryLookup( int key, out XmlDictionaryString result )
{
string res;
if ( !values.TryGetValue( key, out res ) )
{
result = null;
return false;
}
result = new XmlDictionaryString( this, res, key );
return true;
}
public bool /* IXmlDictionary. */ TryLookup( string value, out XmlDictionaryString result )
{
int key;
if ( !keys.TryGetValue( value, out key ) )
{
result = null;
return false;
}
result = new XmlDictionaryString( this, value, key );
return true;
}
}
В результате - мои методы TryLookup вызываются ОК, однако DataContractSerializer.WriteObject создает пустой документ.
Как мне использовать общий словарь?
Заранее спасибо!
PS Я не Я не хочу возиться с XmlBinaryReaderSession / XmlBinaryWriterSession: у меня нет «сеансов», вместо этого у меня есть база данных размером 10 ГБ, к которой одновременно обращаются многие потоки. Я хочу только статический предопределенный словарь.
Обновление: Хорошо, я понял, что мне просто нужно вызвать «XmlDictionaryWriter.Flush». Остается только один вопрос - почему реализация IXmlDictionary, поставляемая системой, не работает должным образом?