Храните данные кэша локально - PullRequest
4 голосов
/ 15 июня 2010

Я разрабатываю приложение C # Winform, это клиент и подключаюсь к веб-сервису для получения данных.Данные, возвращаемые веб-сервисом, являются DataTable.Клиент отобразит его в DataGridView.

Моя проблема в том, что: Клиенту потребуется больше времени для получения всех данных с сервера (веб-служба не является локальной для клиента).Поэтому я должен использовать поток для получения данных.Это моя модель:

Клиент создает поток для получения данных -> поток завершен и отправляет событие клиенту -> клиент отображает данные в datagridview на форме.

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

Итак, я думаю о кэшированных данных:

Клиент <--- get / add / edit / delete ---> Кэшированные данные ---get / add / edit / delete ---> Сервер (веб-сервис)

Пожалуйста, дайте мне несколько советов.Пример: кэшированные данные должны разрабатываться в другом приложении, которое является тем же хостом с клиентом?Или кэшированные данные запущены в клиенте.Пожалуйста, дайте мне несколько методов для реализации этого решения.

Если есть какие-либо примеры, пожалуйста, дайте мне.

Спасибо.

ОБНОВЛЕНИЕ: Привет всем,может быть, вы думаете, моя проблема до сих пор.Я хочу кэшировать данные только при жизни клиента.Я думаю, что данные кэша должны храниться в памяти.И когда клиент хочет получить данные, он будет проверять из кэша.

Ответы [ 6 ]

4 голосов
/ 15 июня 2010

Если вы используете C # 2.0 и , вы готовы отправить System.Web в качестве зависимости, тогда вы можете использовать кеш ASP.NET:

using System.Web;
using System.Web.Caching;

Cache webCache;

webCache = HttpContext.Current.Cache;

// See if there's a cached item already
cachedObject = webCache.Get("MyCacheItem");

if (cachedObject == null)
{
    // If there's nothing in the cache, call the web service to get a new item
    webServiceResult = new Object();

    // Cache the web service result for five minutes
    webCache.Add("MyCacheItem", webServiceResult, null, DateTime.Now.AddMinutes(5), Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, null);
}
else
{
    // Item already in the cache - cast it to the right type
    webServiceResult = (object)cachedObject;
}

Если вы не готовы к отправке System.Web, возможно, вы захотите взглянуть на блок Enterprise Library Caching .

Однако, если вы используете .NET 4.0, кэширование было помещено в пространство имен System.Runtime.Caching. Чтобы использовать это, вам нужно добавить ссылку на System.Runtime.Caching, и тогда ваш код будет выглядеть примерно так:

using System.Runtime.Caching;

MemoryCache cache;
object cachedObject;
object webServiceResult;

cache = new MemoryCache("StackOverflow");

cachedObject = cache.Get("MyCacheItem");

if (cachedObject == null)
{
    // Call the web service
    webServiceResult = new Object();

    cache.Add("MyCacheItem", webServiceResult, DateTime.Now.AddMinutes(5));
}
else
{
    webServiceResult = (object)cachedObject;
}

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

2 голосов
/ 15 июня 2010

У вас есть возможность вносить изменения / дополнения в веб-сервис?

Если вы можете, Sync Services может быть вариантом для вас. Вы можете определить, какие таблицы синхронизируются, и все функции синхронизации управляются за вас.

Выезд

http://msdn.microsoft.com/en-us/sync/default.aspx

и кричите, если вам нужна дополнительная информация.

1 голос
/ 16 июня 2010

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

Используйте EntLib 3.1, если вы застряли в .NET 2.0. В новых EntLibs нет ничего нового (по крайней мере для кэширования), кроме лучшей поддержки настройки.

1 голос
/ 15 июня 2010

Укажите, какие объекты вы хотите сериализовать, и поместите их в изолированное хранилище. Укажите необходимый уровень изоляции данных (уровень приложения, уровень пользователя и т. Д.).

Пример:

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

public class SampleDataSerializer
{
    public static void Deserialize<T>(out T data, Stream stm)
    {
        var xs = new XmlSerializer(typeof(T));
        data = (T)xs.Deserialize(stm);
    }

    public static void Serialize<T>(T data, Stream stm)
    {
        try
        {
            var xs = new XmlSerializer(typeof(T));
            xs.Serialize(stm, data);
        }
        catch (Exception e)
        {
            throw;
        }
    }
}

Обратите внимание, что вам, вероятно, следует добавить некоторые перегрузки в методы Serialize и Deserialize для размещения читателей или любых других типов, которые вы фактически используете в своем приложении (например, XmlDocuments и т. Д.).

Операция сохранения в IsolatedStorage может быть обработана служебным классом (пример ниже):

public class SampleIsolatedStorageManager : IDisposable
{
    private string filename;
    private string directoryname;
    IsolatedStorageFile isf;

    public SampleIsolatedStorageManager()
    {
        filename = string.Empty;
        directoryname = string.Empty;

        // create an ISF scoped to domain user...
        isf = IsolatedStorageFile.GetStore(IsolatedStorageScope.User |
            IsolatedStorageScope.Assembly | IsolatedStorageScope.Domain,
            typeof(System.Security.Policy.Url), typeof(System.Security.Policy.Url));
    }

    public void Save<T>(T parm)
    {
        using (IsolatedStorageFileStream stm = GetStreamByStoredType<T>(FileMode.Create))
        {
            SampleDataSerializer.Serialize<T>(parm, stm);
        }
    }

    public T Restore<T>() where T : new()
    {
        try
        {
            if (GetFileNameByType<T>().Length > 0)
            {
                T result = new T();

                using (IsolatedStorageFileStream stm = GetStreamByStoredType<T>(FileMode.Open))
                {
                    SampleDataSerializer.Deserialize<T>(out result, stm);
                }

                return result;
            }
            else
            {
                return default(T);
            }
        }
        catch
        {
            try
            {
                Clear<T>();
            }
            catch
            {
            }

            return default(T);
        }
    }

    public void Clear<T>()
    {
        if (isf.GetFileNames(GetFileNameByType<T>()).Length > 0)
        {
            isf.DeleteFile(GetFileNameByType<T>());
        }
    }

    private string GetFileNameByType<T>()
    {
        return typeof(T).Name + ".cache";
    }

    private IsolatedStorageFileStream GetStreamByStoredType<T>(FileMode mode)
    {
        var stm = new IsolatedStorageFileStream(GetFileNameByType<T>(), mode, isf);
        return stm;
    }

    #region IDisposable Members

    public void Dispose()
    {
        isf.Close();
    }
}

Наконец, не забудьте добавить следующее с помощью предложений:

using System.IO;
using System.IO.IsolatedStorage;
using System.Xml.Serialization;

Фактический код для использования классов выше может выглядеть следующим образом:

var myClass = new MyClass();
myClass.name = "something";
using (var mgr = new SampleIsolatedStorageManager())
{
    mgr.Save<MyClass>(myClass);
}

Это сохранит указанный вами экземпляр для сохранения в изолированном хранилище. Чтобы получить экземпляр, просто позвоните:

using (var mgr = new SampleIsolatedStorageManager())
{
    mgr.Restore<MyClass>();
}

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

НТН!

0 голосов
/ 15 июня 2010

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

0 голосов
/ 15 июня 2010

Вы можете сериализовать DataTable в файл: http://forums.asp.net/t/1441971.aspx

Ваша единственная задача - решить, когда кэш устарел.Возможно отметка времени файла?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...