Поиск простой автономной персистентной реализации словаря в [закрытом] C#

Исключение нулевого указателя - это индикатор того, что вы используете объект, не инициализируя его.

Например, ниже - класс ученика, который будет использовать его в нашем коде.

public class Student {

    private int id;

    public int getId() {
        return this.id;
    }

    public setId(int newId) {
        this.id = newId;
    }
}

Приведенный ниже код дает вам исключение с нулевым указателем.

public class School {

    Student obj_Student;

    public School() {
        try {
            obj_Student.getId();
        }
        catch(Exception e) {
            System.out.println("Null Pointer ");
        }
    }
}

Поскольку вы используете Obj_Student, но вы забыли инициализировать его, как в правильном коде, показанном ниже:

public class School {

    Student obj_Student;

    public School() {
        try {
            obj_Student = new Student();
            obj_Student.setId(12);
            obj_Student.getId();
        }
        catch(Exception e) {
            System.out.println("Null Pointer ");
        }
    }
}
25
задан Community 23 May 2017 в 10:30
поделиться

17 ответов

  • bplustreedotnet

    bplusdotnet пакет является библиотекой перекрестных совместимых реализаций структуры данных в C#, Java и Python, которые полезны для приложений, которые должны сохранить и получить персистентную информацию. bplusdotnet структуры данных помогают [1 119] строковые ключи хранилища, связанные со значениями постоянно .

  • ESENT Управляемый Интерфейс

    Не 100%-й управляемый код, но стоит упомянуть, что это как сама неуправляемая библиотека уже - часть каждого поля

    окон XP/2003/Vista/7 ESENT, встраиваемый механизм устройства хранения данных базы данных (ISAM), который является частью Windows. Это предоставляет надежному, проведенному, параллельному, высокоэффективному хранению данных блокировку уровня строки, запишите вперед вход и создайте снимки изоляцию. Это - управляемая оболочка для Win32 ESENT API.

  • Akavache

    *Akavache является асинхронным, персистентным кэшем значения ключа, созданным для записи собственных настольных и мобильных приложений в C#. Думайте о нем как memcached для настольных приложений.

<забастовка> - Библиотека Универсального набора C5

C5 обеспечивает функциональность и структуры данных, не обеспеченные стандартным .NET System.Collections.Generic пространство имен, такой как [1 123] персистентные древовидные структуры данных , основанные на "куче" приоритетные очереди, списки индексного массива хеша и связанные списки и события на изменениях набора.

23
ответ дан Sam Saffron 28 November 2019 в 20:36
поделиться

Я рекомендовал бы SQL Server Express или другая база данных.

  • Это свободно.
  • Это интегрируется очень хорошо с C#, включая LINQ.
  • Это быстрее, чем самодельное решение.
  • Это более надежно, чем самодельное решение.
  • Это - путь, более мощный, чем простая находящаяся на диске структура данных, таким образом, будет легко сделать больше в будущем.
  • SQL является промышленным стандартом, таким образом, другие разработчики поймут Вашу программу более легко, и у Вас будет навык, который полезен в будущем.
0
ответ дан Jay Bazuzi 28 November 2019 в 20:36
поделиться

Я не большая часть программиста, но не был бы, создавая действительно простой формат XML, чтобы хранить Ваши данные, добиваются цели?

<dico> 
   <dicEntry index="x">
     <key>MyKey</key>
     <val type="string">My val</val>
   </dicEntry>
   ...
</dico>

Оттуда, Вы загружаете XML-файл DOM и заполняете Ваш словарь как Вам угодно

XmlDocument xdocDico = new XmlDocument();
string sXMLfile;
public loadDico(string sXMLfile, [other args...])
{
   xdocDico.load(sXMLfile);
   // Gather whatever you need and load it into your dico
}
public flushDicInXML(string sXMLfile, dictionary dicWhatever)
{
   // Dump the dic in the XML doc & save
}
public updateXMLDOM(index, key, value)
{
   // Update a specific value of the XML DOM based on index or key
}

Затем каждый раз, когда Вы хотите, можно обновить DOM и сохранить его на диске.

xdocDico.save(sXMLfile);

, Если можно позволить себе сохранить DOM в памяти мудрым производительностью, довольно легко иметь дело с. В зависимости от Ваших требований Вам даже, возможно, не понадобится словарь вообще.

-1
ответ дан 28 November 2019 в 20:36
поделиться

Рассмотрите файл с отображенной памятью. Я не уверен, существует ли прямая поддержка в.NET, но Вы могли pinvoke вызовы Win32.

0
ответ дан kenny 28 November 2019 в 20:36
поделиться

Я на самом деле не использовал его, но этот проект, по-видимому, обеспечивает mmap () - как реализация в C#

Mmap

0
ответ дан axel_c 28 November 2019 в 20:36
поделиться

Как сказанный Douglas, необходимо знать фиксированный размер типов (и T и V). Кроме того, отсутствуют экземпляры переменной длины в объектной сетке, на которую ссылается любой из тех экземпляров.

однако, реализовывая словарь, поддержанный файлом, довольно просто, и можно использовать BinaryWriter класс записи типы к диску после наследования или инкапсуляции Dictionary<TKey, TValue> класс.

0
ответ дан Omer van Kloeten 28 November 2019 в 20:36
поделиться

Я не знаю ни о чем для решения проблемы. Это должна будет быть структура фиксированного размера, так, чтобы можно было отвечать требованиям способности переписать записи, не переписывая весь файл.

Это означает, что нормальные строки отсутствуют.

0
ответ дан Douglas Leeder 28 November 2019 в 20:36
поделиться

Просто используйте сериализацию. Посмотрите на класс BinaryFormatter.

0
ответ дан leppie 28 November 2019 в 20:36
поделиться

Проверьте этот блог:

http://ayende.com/Blog/archive/2009/01/17/rhino.dht-ndash-persistent-amp-distributed-storage.aspx

Надеется быть точно, что Вы ищете.

1
ответ дан PiotrWolkowski 28 November 2019 в 20:36
поделиться

Я думаю, что Ваша проблема, вероятно, будет то, которые в последний раз указывают:

При установке или очистке значения это не должно переписывать весь базовый файл, вместо этого это должно искать на положение в файле и обновить значение.

Это точно, что делает DB - Вы в основном описываете простую основанную на файле структуру таблицы.

Мы можем проиллюстрировать проблему путем рассмотрения строк.

Строки в памяти являются гибкими вещами - Вы не должны знать длину строки в C#, когда Вы объявляете его тип.

В строках хранения данных и все остальное - фиксированные размеры. Ваш сохраненный словарь по диску является просто набором байтов в порядке.

, Если Вы заменяете значение в середине это или должны быть точно тем же размером или Вы будете иметь к , переписывают каждый байт, который прибывает после него .

Поэтому большинство баз данных ограничивает текст и поля блоба к фиксированным размерам. Новыми возможностями как varchar(max) / varbinary(max) в Sql 2005 + являются на самом деле умные упрощения в строке только на самом деле хранение указателя на реальные данные.

Вы не можете использовать фиксированные размеры со своим примером, потому что это универсально - Вы не знаете то, что вводит, Вы собираетесь быть хранением, таким образом, Вы не можете увеличить значения к максимальному размеру.

Вы могли сделать:

class PersistantDictionary<T,V> : Dictionary<T,V>
    where V:struct

..., поскольку типы значения не варьируются по размеру ресурса хранения, хотя необходимо было бы быть осторожными с реализацией для сохранения правильной суммы устройства хранения данных для каждого типа.

Однако Ваша модель не была бы очень производительна - если Вы смотрите на то, как SQL-сервер и Oracle имеют дело с изменениями таблицы, они не изменяют значения как это. Вместо этого они отмечают старую запись как фантом и добавляют новую запись с новым значением. Старые повторенные записи очищены позже, когда DB менее занят.

я думаю, что Вы пытаетесь изобрести велосипед:

  • , Если Вы имеете дело с большими объемами данных затем, действительно необходимо проверить использование полноценного DB. MySql или SqlLite оба хороши, но Вы не собираетесь находить хорошую, простую, и облегченную реализацию с открытым исходным кодом.

  • , Если бы Вы не имеете дело с загрузками данных затем, я пошел бы для целой сериализации файла, и уже существует много хороших предложений здесь о том, как сделать это.

1
ответ дан Keith 28 November 2019 в 20:36
поделиться

Я нашел эту ссылку, и походите на то, что Вы ищете. Это программируется в Java, но не должно случаться так что трудно портировать его на C#:

http://www.javaworld.com/javaworld/jw-01-1999/jw-01-step.html

1
ответ дан Igor Zelaya 28 November 2019 в 20:36
поделиться

Прохладные звуки, но как Вы обойдете изменения в хранимой сумме (если это был ссылочный тип), сам? Если его неизменное тогда, которое все хорошо, но если не Вы отчасти наполнены:-)

, Если бы Вы не имеете дело с неизменными значениями, я подозревал бы, что лучший подход должен был бы обработать персистентность на уровне значения и просто восстановить словарь по мере необходимости.

(отредактированный для добавления разъяснения)

1
ответ дан chrisb 28 November 2019 в 20:36
поделиться

Я работал над портированием EHCache к.NET. Смотрите на проект

http://sourceforge.net/projects/thecache/

, Персистентное кэширование является базовой функциональностью, которая уже реализована. Все основные Модульные тесты являются передающими. Я вовлек немного на распределенном кэшировании, но Вам не нужна та часть.

2
ответ дан Timur Fanshteyn 28 November 2019 в 20:36
поделиться

один путь состоит в том, чтобы использовать Расширяемый Механизм устройства хранения данных встроенный в окна для хранения материала. Это - собственная база данных победы, которая поддерживает индексацию, транзакции и т.д.

6
ответ дан Mladen Prajdic 28 November 2019 в 20:36
поделиться

Позвольте мне проанализировать это:

  1. Получают информацию ключом
  2. , устройство хранения данных Persistant
  3. не хочет записывать целый файл обратно, когда 1 значение изменяется
  4. , Должен пережить катастрофические отказы

, я думаю, что Вы хотите базу данных.

Редактирование: Я думаю, что Вы ищете неправильную вещь. Ищите базу данных, которая соответствует Вашим требованиям. И измените некоторые свои требования, потому что я думаю, что будет трудно встретить их всех.

13
ответ дан GvS 28 November 2019 в 20:36
поделиться

Я описал реализацию сам на основе очень похожего (я думаю идентичный), требование, которое я имел на другом проекте только что. Когда я сделал это, одна вещь, которую я понял, состояла в том, что большую часть времени Вы будете делать записи, Вы только делаете чтение редко, когда программа отказывает или когда это закрывается. Таким образом, идея состоит в том, чтобы сделать записи максимально быстро. То, что я сделал, было, делают очень простой класс, который просто записал бы журнал всех операций (дополнения и удаления) к словарю, поскольку вещи произошли. Так через некоторое время Вы получаете большое повторение между ключами. Из-за этого, после того как объект обнаруживает определенное количество повторения, он очистит журнал и перепишет его так, каждый ключ и его значение только появляются однажды.

, К сожалению, Вы не можете разделить Словарь на подклассы, потому что Вы ничего не можете переопределить в нем. Это - моя простая реализация, я не протестировал ее, хотя я сожалею, я думал, что Вы могли бы хотеть идею все же. Не стесняйтесь использовать его и изменять его так, как Вам нравится.

class PersistentDictManager {
    const int SaveAllThreshold = 1000;

    PersistentDictManager(string logpath) {
        this.LogPath = logpath;
        this.mydictionary = new Dictionary<string, string>();
        this.LoadData();
    }

    public string LogPath { get; private set; }

    public string this[string key] {
        get{ return this.mydictionary[key]; }
        set{
            string existingvalue;
            if(!this.mydictionary.TryGetValue(key, out existingvalue)) { existingvalue = null; }
            if(string.Equals(value, existingvalue)) { return; }
            this[key] = value;

            // store in log
            if(existingvalue != null) { // was an update (not a create)
                if(this.IncrementSaveAll()) { return; } // because we're going to repeat a key the log
            }
            this.LogStore(key, value);
        }
    }

    public void Remove(string key) {
        if(!this.mydictionary.Remove(key)) { return; }
        if(this.IncrementSaveAll()) { return; } // because we're going to repeat a key in the log
        this.LogDelete(key);
    }

    private void CreateWriter() {
        if(this.writer == null) {
            this.writer = new BinaryWriter(File.Open(this.LogPath, FileMode.Open)); 
        }
    }

    private bool IncrementSaveAll() {
        ++this.saveallcount;
        if(this.saveallcount >= PersistentDictManager.SaveAllThreshold) {
            this.SaveAllData();
            return true;
        }
        else { return false; }
    }

    private void LoadData() {
        try{
            using(BinaryReader reader = new BinaryReader(File.Open(LogPath, FileMode.Open))) {
                while(reader.PeekChar() != -1) {
                    string key = reader.ReadString();
                    bool isdeleted = reader.ReadBoolean();
                    if(isdeleted) { this.mydictionary.Remove(key); }
                    else {
                        string value = reader.ReadString();
                        this.mydictionary[key] = value;
                    }
                }
            }
        }
        catch(FileNotFoundException) { }
    }

    private void LogDelete(string key) {
        this.CreateWriter();
        this.writer.Write(key);
        this.writer.Write(true); // yes, key was deleted
    }

    private void LogStore(string key, string value) {
        this.CreateWriter();
        this.writer.Write(key);
        this.writer.Write(false); // no, key was not deleted
        this.writer.Write(value);
    }

    private void SaveAllData() {
        if(this.writer != null) {
            this.writer.Close();
            this.writer = null;
        }
        using(BinaryWriter writer = new BinaryWriter(File.Open(this.LogPath, FileMode.Create))) {
            foreach(KeyValuePair<string, string> kv in this.mydictionary) {
                writer.Write(kv.Key);
                writer.Write(false); // is not deleted flag
                writer.Write(kv.Value);
            }
        }
    }

    private readonly Dictionary<string, string> mydictionary;
    private int saveallcount = 0;
    private BinaryWriter writer = null;
}
1
ответ дан Ray Hidayat 28 November 2019 в 20:36
поделиться

Я реализовал тот тип PersistedDictionary, который вы ищете. Базовое хранилище - это механизм базы данных ESENT, встроенный в Windows. Код доступен здесь:

http://managedesent.codeplex.com/

8
ответ дан 28 November 2019 в 20:36
поделиться