4

我目前正在开发一个需要存储一些表的 Windows 8 应用程序。目前,我正在使用带有 XDocument 类的 XML 文件来解决这个问题。它使用save和使用的load方法GetFileAsync等等CreateFileAsync。此外,这些saveload方法被不同的事件调用。但是,只要有重复调用,就会抛出异常,告诉我文件访问被拒绝。预期的行为 -更多细节在这里!虽然有一些肮脏的方法可以避免这种情况(比如使用锁等),但我对结果不是很满意。我更喜欢数据库。此外,我计划为 Windows Phone 8(可能还有网络版本)编写另一个应用程序,它将利用这些数据。

他们一再表示 Windows 8 是基于云的。现在的问题是:存储数据的正确方法是什么?XML 似乎是正确的,但存在我上面提到的问题。什么是理想的基于云的解决方案,包括 Windows 8、Windows Phone 8 和可能的 Azure?我想要的只是存储表格并使其可访问。

对不起,如果问题似乎不清楚。如果需要,我会提供信息。

4

5 回答 5

7

如果您想使用 Azure,最简单的方法是Windows Azure 移动服务。它允许您在几分钟内使用 Web 界面设置数据库和 Web 服务。

它非常酷,允许您将自定义 javascript 添加到您的 web api 逻辑,并生成 json web api。有适用于 Windows 8、Windows Phone 和 iOS 的客户端库。您可以轻松地为任何启用 http 的前端推出自己的。

但是请注意,采用云路由意味着您的应用程序将无法离线工作,(如果您不编写缓存系统代码。缓存将需要本地数据库。)

关于本地数据库 您确实有以下可能性: 1)您的应用程序中的真实数据库,例如 SQLite。它以Nuget 包的形式提供,但目前 ARM 支持不是开箱即用的,团队也不能保证。如果你不需要手臂,去试试吧:)

2)普通的旧文件存储,就像你以前做的那样。我个人经常这样做。但是,当您从不同的线程访问它时会遇到问题(访问被拒绝错误)。

当您将内容存储在本地文件中时,不要忘记锁定关键部分(即当您读取或写入文件时)以防止访问被拒绝异常。可以肯定的是,将您的写入/读取逻辑封装在您的应用程序中唯一的服务类实例中。(例如使用单例模式,或任何等效的)。

锁本身,现在。我想你正在使用异步等待。我也喜欢这种甜蜜的东西。但是经典的 C# 锁(lock例如使用关键字)不适用于异步等待。(即使它有效,阻塞也不会很酷)。

这就是奇妙的 AsyncLock 发挥作用的原因。这是一个锁,但它 - 大约 - 不会阻塞(你等待它)。

public class AsyncLock
{
    private readonly AsyncSemaphore m_semaphore;
    private readonly Task<Releaser> m_releaser;

    public AsyncLock()
    {
        m_semaphore = new AsyncSemaphore(1);
        m_releaser = Task.FromResult(new Releaser(this));
    }

    public Task<Releaser> LockAsync()
    {
        var wait = m_semaphore.WaitAsync();
        return wait.IsCompleted ?
            m_releaser :
            wait.ContinueWith((_, state) => new Releaser((AsyncLock)state),
                this, CancellationToken.None,
                TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
    }

    public struct Releaser : IDisposable
    {
        private readonly AsyncLock m_toRelease;

        internal Releaser(AsyncLock toRelease) { m_toRelease = toRelease; }

        public void Dispose()
        {
            if (m_toRelease != null)
                m_toRelease.m_semaphore.Release();
        }
    }
}

public class AsyncSemaphore
{
    private readonly static Task s_completed = Task.FromResult(true);
    private readonly Queue<TaskCompletionSource<bool>> m_waiters = new Queue<TaskCompletionSource<bool>>();
    private int m_currentCount;

    public AsyncSemaphore(int initialCount)
    {
        if (initialCount < 0) throw new ArgumentOutOfRangeException("initialCount");
        m_currentCount = initialCount;

    }
    public Task WaitAsync()
    {
        lock (m_waiters)
        {
            if (m_currentCount > 0)
            {
                --m_currentCount;
                return s_completed;
            }
            else
            {
                var waiter = new TaskCompletionSource<bool>();
                m_waiters.Enqueue(waiter);
                return waiter.Task;
            }
        }

    }
    public void Release()
    {
        TaskCompletionSource<bool> toRelease = null;
        lock (m_waiters)
        {
            if (m_waiters.Count > 0)
                toRelease = m_waiters.Dequeue();
            else
                ++m_currentCount;
        }
        if (toRelease != null)
            toRelease.SetResult(true);

    }
}

你可以这样使用它(我想你有一个名为 blogLock 的 AsyncLock 字段(取自我自己的一个项目):

            using (await blogLock.LockAsync())
            {
                using (var stream = await folder.OpenStreamForReadAsync(_blogFileName))
                {
                    using (var reader = new StreamReader(stream))
                    {
                        var json = await reader.ReadToEndAsync();
                        var blog = await JsonConvert.DeserializeObjectAsync<Blog>(json);

                        return blog;
                    }
                }
            }
于 2012-12-01T14:33:48.050 回答
2

我偶然发现了这个线程,因为我基本上有完全相同的问题。令我震惊的是,微软自己制造了企业级数据库产品(SQL Server),它已经有几个轻量级、可嵌入的版本,但这些似乎无法与 Windows 8/Windows Phone 8 应用程序一起使用提供本地数据库。然而 MySQL 可以!

我曾尝试过几次尝试编写 Windows Phone 8 应用程序,使用我的 ASP.NET/VB/NET/SQL 经验,但我总是陷入困境,试图学习一种不同的方式来执行我可以执行的数据操作在网络环境中做梦而失去兴趣。为什么他们不能让 W8/WP8 应用程序轻松使用 SQL?

于 2013-08-16T15:57:00.237 回答
0

如果数据与设备用户有关,请查看使用 SQLlite ... Stack 上有一个关于 SQLlite 和本地 winRT 数据库的问题:WinRT/Metro 应用程序的本地数据库存储

于 2012-12-01T15:04:47.570 回答
0
  1. SQL 数据库
  2. Windows 8 和 JavaScript 开发中的 IndexedDB
于 2012-12-01T15:08:56.980 回答
0

我知道这是一个已经有公认答案的老问题,但我还是会拿出我的肥皂盒并回答它,因为我认为与其解决技术问题,不如使用不依赖于的架构在本地数据库设施上。

根据我的经验,很少有数据需要设备本地数据库服务。

大多数需要本地存储的用户生成数据是非漫游的(即特定于设备的)用户偏好和配置(例如使用可移动存储设置)。游戏结果属于这一类。产生大量用户数据的应用程序通常在桌面上实现,并且几乎可以肯定与本地网络有快速可靠的连接,这使得基于服务器的存储非常适合 Office 文档等“胖”数据。

参考数据当然应该是基于服务器的,但您可以选择缓存它。Windows Phone 8 上的诺基亚地图是基于服务器的缓存数据的一个很好的例子。缓存甚至可以显式预加载以供离线使用。

我刚才阐述的世界观对于本地 SQL Server 几乎没有用处。如果您需要查询引擎,请使用 LINQ。将您的应用程序设置和用户数据表达为对象图并(反)序列化 XML。如果您不想维护 ORM 类,您甚至可以直接在 XML 上使用 Linq2Xml。

应该在所有用户的设备上都可用的任何类型的数据实际上都需要进行云存储。


为了解决 akshay 的一些评论,

地图数据

地理空间数据通常被组织成称为四叉树的结构,原因有多种,主要是为了提供随缩放而变化的详细程度。访问和操作这些数据的方式从它们作为对象图的表示中获得了相当大的优势,并且它们不会由用户更新,因此虽然这些数据当然可以存储在关系数据库中,而且可能是在编译时,但它肯定不是'不是那样存储或交付的。

LINQ 非常适合这种情况,因为它可以直接应用于四叉树。

数据当然在文件中。但我想你的意思是直接文件访问,而不是通过另一个进程间接访问。可能您的想法是,一次性彻底解决并发和查询处理问题并在客户端应用程序之间共享解决方案是一个好主意。但这是一个非常重量级的解决方案,查询处理方面已经被 LINQ 很好地处理(这就是我一直提到它的原因)。

您的 XML 问题

只读不需要加锁,所以通过缓存和使用单例模式避免文件系统锁定问题...

public static class XManager 
{
  static Dictionary<string, XDocument> __cache = new Dictionary<string, XDocument>();
  public static XDocument GetXDoc(string filepath)
  {
    if (!__cache.Contains(filepath)
    {
      __cache[filepath] = new XDocument();
      __cache[filepath].Load(filepath);
    }
    return _cache[filepath];
  }
}
于 2014-09-25T08:20:53.070 回答