在Windows 8和Windows Phone 8中使用数据库的正确方法

aks*_*000 4 c# azure microsoft-metro windows-phone-8

我目前正在开发一个需要存储一些表的Windows 8应用程序.目前,我正在使用带有XDocument类的XML文件来解决目的.它采用saveload使用方法GetFileAsyncCreateFileAsync等.此外,还有saveload方法由不同的事件称为.但是,每当有重复调用时,都会抛出异常,告诉我文件访问被拒绝.预期的行为 - 更多细节在这里!虽然有肮脏的方法来避免这种情况(比如使用锁等),但我对结果并不满意.我更喜欢数据库.此外,我打算为Windows Phone 8编写另一个应用程序(可能还有一个Web版本),它将使用这些数据.

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

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

Eil*_*aee 7

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

这很酷,允许您将自定义javascript添加到您的web api逻辑,并生成json web apis.有适用于Windows 8,Windows Phone和iOS的客户端库.您可以轻松地为任何支持http的前端推送自己的内容.

但请注意,采用云路线意味着您的应用无法脱机工作(如果您不对缓存系统进行编码.缓存将需要本地数据库.)

关于本地数据库 您真的有可能:1)您的应用程序中的真正数据库,如SQLite.它可以作为Nuget包使用,但是现在ARM支持不是开箱即用的,也不是由团队保证的.如果你不需要手臂,去试试吧:)

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

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

锁本身,现在.我想你正在使用异步等待.我也喜欢这个甜蜜的东西.但是经典的C#锁(lock例如使用关键字)不能与async await一起使用.(即使它起作用,阻塞也不会很酷).

这就是奇妙的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);

    }
}
Run Code Online (Sandbox Code Playgroud)

你可以这样使用它(我想你有一个名为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;
                    }
                }
            }
Run Code Online (Sandbox Code Playgroud)