C# 在Windows 8和Windows Phone 8中使用数据库的正确方法
我目前正在开发一个Windows 8应用程序,它需要存储一些表。目前,我正在使用XML文件和XDocument类来解决这个问题。它使用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编写另一个应用程序(可
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数据库,堆栈上有一个问题:
我偶然发现了这条线索,因为我基本上有完全相同的问题。
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];
}
}