winforms 本地存储该高速缓存数据

balp4ylt  于 2023-01-09  发布在  其他
关注(0)|答案(6)|浏览(234)

我开发了一个C#Winform应用程序,它是一个客户端,连接到Web服务获取数据,Web服务返回的数据是一个DataTable,客户端将它显示在一个DataGridView上。
我的问题是:客户端将花费更多的时间从服务器获取所有数据(Web服务不是客户端本地的)。所以我必须使用一个线程来获取数据。这是我的模型:
客户端创建一个线程来获取数据-〉线程完成并向客户端发送事件-〉客户端在表单上的DataGridView上显示数据。
但是,当用户关闭表单时,用户可以在其他时间打开此表单,客户端必须重新获取数据,此解决方案将导致客户端速度变慢。
所以,我想到了缓存数据:
客户端〈---获取/添加/编辑/删除---〉缓存数据---获取/添加/编辑/删除---〉服务器(Web服务)
请给我一些建议。例如:缓存的数据应该在另一个应用程序中开发,这个应用程序和客户端在同一个主机上?2或者缓存的数据正在客户端运行。3请给我一些实现这个解决方案的技术。
如果有任何例子,请给我。
谢谢。

    • 更新:**大家好,也许到目前为止你认为我的问题。我只想在客户端的生命周期内缓存数据。我认为缓存数据应该存储在内存中。当客户端想要获取数据时,它会从缓存中检查。
ruarlubt

ruarlubt1#

如果您使用的是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 block
然而,如果你使用的是.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;
}

所有这些缓存都在客户端的进程内运行,因为你的数据来自一个Web服务,正如Adam所说,你很难确定数据的新鲜度--你必须判断数据的变化频率和缓存数据的时间。

vs91vp4v

vs91vp4v2#

您是否能够对Web服务进行更改/添加?
如果可以的话,同步服务可能是你的一个选择。你可以定义哪些表要同步,所有的同步东西都会为你管理。
结账
http://msdn.microsoft.com/en-us/sync/default.aspx
如果需要更多信息就大声喊。

gc0ot86w

gc0ot86w3#

你可以试试Enterprise LibraryCaching Application Block,它很容易使用,存储在内存中,如果你以后需要的话,它支持添加一个备份位置,以便在应用程序的生命周期之外持久保存(比如到数据库、独立存储、文件等),甚至还支持加密。
如果您坚持使用.NET 2.0,请使用EntLib 3.1。除了更好的自定义支持之外,较新的EntLib没有太多新功能(至少在缓存方面)。

7kjnsjlb

7kjnsjlb4#

标识要序列化并缓存到独立存储的对象。指定所需的数据隔离级别(应用程序级别、用户级别等)。
示例:
您可以创建一个通用序列化程序,一个非常基本的示例如下所示:

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子句:

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>();
}

注意:我提供的示例只支持每种类型一个序列化示例。我不确定你是否需要更多的示例。做你需要的任何修改以支持更多的功能。
啊!

xu3bshqb

xu3bshqb5#

您可以将DataTable序列化为文件:http://forums.asp.net/t/1441971.aspx
你唯一关心的就是确定该高速缓存什么时候失效了。也许给文件加上时间戳?

kx7yvsdv

kx7yvsdv6#

在我们的实现中,数据库中的每一行都有一个最后更新的时间戳,每次客户端应用程序访问一个表时,我们该高速缓存中选择最新的最后更新的时间戳,并将该值发送给服务器,服务器以具有较新时间戳的所有行作为响应。

相关问题