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

C# 在Windows 8和Windows Phone 8中使用数据库的正确方法,c#,azure,microsoft-metro,windows-phone-8,C#,Azure,Microsoft Metro,Windows Phone 8,我目前正在开发一个Windows 8应用程序,它需要存储一些表。目前,我正在使用XML文件和XDocument类来解决这个问题。它使用GetFileAsync和CreateFileAsync等save和load方法。此外,有save和load方法由不同的事件调用。但是,每当有重复调用时,就会抛出一个异常,告诉我文件访问被拒绝。预期行为-!虽然有一些肮脏的方法可以避免这种情况(比如使用锁之类的),但我对结果不是很满意。我更喜欢数据库。此外,我正计划为WindowsPhone8编写另一个应用程序(可

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

他们一再表示Windows8是基于云的。现在的问题是:存储数据的正确方法是什么?XML似乎是正确的,但它有我上面提到的问题。什么是最理想的基于云的解决方案,包括Windows 8、Windows Phone 8和Azure?我想做的就是储存桌子,并让它们便于使用


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

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

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

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

关于本地数据库的信息 你真的必须: 1) 在你的应用程序中有一个真正的DB,比如SQLite。它可以作为一个组件提供,但目前手臂支撑既不能开箱即用,也不能由团队保证。如果你不需要手臂,试试看:)

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

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

锁本身,现在。我猜想您正在使用async Wait。我也喜欢这个甜东西。但是经典的C#锁(例如使用
lock
关键字)不适用于异步等待。(即使成功了,阻塞也不会很酷)

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

公共类异步锁
{
私有只读异步信号量m_信号量;
专用只读任务m_释放器;
公共异步锁()
{
m_信号量=新的异步信号量(1);
m_releaser=Task.FromResult(新releaser(this));
}
公共任务LockAsync()
{
var wait=m_信号量.WaitAsync();
返回等待。是否完成?
m_释放器:
wait.ContinueWith((_,state)=>newreleaser((异步锁)状态),
这是CancellationToken。无,
TaskContinuationOptions.ExecuteSynchronously,TaskScheduler.Default);
}
公共结构释放器:IDisposable
{
私有只读异步锁m_toRelease;
内部释放器(AsyncLock-toRelease){m_-toRelease=toRelease;}
公共空间处置()
{
if(m_toRelease!=null)
m_toRelease.m_semaphore.Release();
}
}
}
公共类异步信号量
{
private readonly static Task s_completed=Task.FromResult(true);
私有只读队列m_waiters=新队列();
私有整数m_currentCount;
公共异步信号量(int initialCount)
{
如果(initialCount<0)抛出新ArgumentOutOfRangeException(“initialCount”);
m_currentCount=初始计数;
}
公共任务WaitAsync()
{
锁(男服务员)
{
如果(m_currentCount>0)
{
--m_电流计数;
返回s_已完成;
}
其他的
{
var water=new TaskCompletionSource();
服务员排队(服务员);
返回服务员。任务;
}
}
}
公开无效释放()
{
TaskCompletionSource toRelease=null;
锁(男服务员)
{
如果(m_waiters.Count>0)
toRelease=m_waiters.Dequeue();
其他的
++m_电流计数;
}
if(toRelease!=null)
toRelease.SetResult(true);
}
}
您可以这样使用它(我假设您有一个名为blogLock的AsyncLock字段(取自我自己的一个项目):

使用(等待blogLock.LockAsync())
{
使用(var stream=await folder.OpenStreamForReadAsync(_blogFileName))
{
使用(变量读取器=新的流读取器(流))
{
var json=await reader.ReadToEndAsync();
var blog=await JsonConvert.DeserializeObjectAsync(json);
返回博客;
}
}
}

如果数据属于设备用户,请查看使用SQLlite的情况……关于SQLlite和本地winRT数据库,堆栈上有一个问题:

  • SQL数据库
  • IndexedDB在windows8和JavaScript开发中的应用

  • 我偶然发现了这条线索,因为我基本上有完全相同的问题。
    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);
    
        }
    }
    
                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;
                        }
                    }
                }
    
    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];
      }
    }