在可移植类库中使用SQLite

15

最近我们开始着手一个新项目,其中包括Windows 8 Metro、Windows Phone和桌面应用的客户端。我们决定使用MVVM模式作为主要架构,因为在各个项目之间共享ViewModels是更为可接受的解决方案。

为了达到这个目的,我们决定使用可移植类库,但问题是,在从Visualstudio 2012扩展库下载并安装了Windows运行时的SQLite后,当我们试图添加引用到相应的库时,根本就找不到那些库。这使我们认为,在可移植类库项目中使用SQLite是不可能的。

也许有些人已经做过这个,并知道我们可以实现这个功能的方法?请为我们提供正确的开发方法,因为在这个阶段使用SQLite和具有可重用代码非常重要。


1
SQLite 无法在可移植类库项目中使用。 - Marco Minerva
这是可以请您再解释一下吗?肯定有办法可以使用它。例如,一个人可以编写包装器接口并使用IoC或DI来提供它。 还有其他StackOverflow用户的建议吗? - Rati_Ge
2
我认为你不能从可移植类库引用“本地”DLL,例如SQLite。但是,请查看SQLite的C#端口[csharp-sqlite](http://code.google.com/p/csharp-sqlite/)。没有PCL项目,但有专门针对所有感兴趣的平台的项目。您可以引用特定平台的*csharp-sqlite* DLL,或者您可以检查创建csharp-sqlite PCL所需的工作量。 - Anders Gustafsson
1
Csharo-sqlite似乎是我们任务的某种解决方案,但您不认为在PCL项目内创建IRepositori<T>接口并在不同项目中实现它会更好吗?然后使用构造函数注入,我们将通过SQLite传递具体实现到可移植类库服务类。这样行得通吗?我认为这将是更清晰和可维护的方式。我是对的吗? - Rati_Ge
4个回答

20
在MvvmCross中,我们采用了不同的方法来解决这个问题。我们希望利用SQLite的本地端口,并使用https://github.com/praeclarum/sqlite-net/的SQLite-net ORM包装器。因此,我们不仅使用PCL,而是:
在代码层面上,客户端应用可以像这样使用插件:
在业务逻辑库(PCL或特定平台)中,代码可以定义一个模型对象:
public class ListItem
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }
    public string Name { get; set; }
    public string WhenCreated { get; set; }
}

在启动期间,应用程序可以调用:

  Cirrious.MvvmCross.Plugins.Sqlite.PluginLoader.Instance.EnsureLoaded();
  var factory = this.GetService<ISQLiteConnectionFactory>();
  var connection = factory.Create("SimpleList");
  connection.CreateTable<ListItem>();

然后在操作过程中,代码可以执行以下操作:

  connection.Insert(new ListItem() { Name = TextToAdd, WhenCreated = DateTime.Now.ToString("HH:mm:ss ddd MMM yyyy") });

或者

 public ListItem this[int index]
 {
     get { return _connection.Table<ListItem>().OrderBy(_sortOrder).Skip(index).FirstOrDefault(); }
 }

虽然UI特定的代码必须引用插件的平台特定扩展,并将该平台特定实现注入到IoC/DI系统中。在Droid上这非常简单(因为MonoDroid在运行时支持Assembly.Load),但在其他平台上,这涉及到一些“样板”代码,例如:

    protected override void AddPluginsLoaders(Cirrious.MvvmCross.Platform.MvxLoaderPluginRegistry loaders)
    {
        loaders.AddConventionalPlugin<Cirrious.MvvmCross.Plugins.Sqlite.WinRT.Plugin>();
        base.AddPluginsLoaders(loaders);
    }

注:

  • 当前的MvvmCross仓库只包括WinRT和MonoDroid SQLite包装器 - 但其他平台(WP *和MonoTouch)应该很容易构建(我知道其他人已经构建了它们,但尚未将它们贡献回来)

  • 当前的MvvmCross仓库只包括WinRT的同步(非异步)接口 - 但我知道有人告诉我他们在私人项目中扩展了这个接口。

  • 我目前正在将此插件结构从MvvmCross中分离出来,以便可以更广泛地使用插件。希望在圣诞节之前发布有关此事的公告。

  • 有关MvvmCross插件的更多信息,请参见https://speakerdeck.com/cirrious/mvvmcross-going-portable


这种方法非常接近我们想要实现的方式,但非常感谢您提供这些链接,因为这些将在我们的开发过程中非常有帮助。我认为这真的是解决我们问题的完美方案。这是一个单独的问题,但您知道是否可以在PCL中使用Task<T>吗?我没有成功让它工作。 - Rati_Ge
这是一个非常好的问题 - 把它作为一个新问题提出来,你就会得到答案! - Stuart
如果你的目标平台已经有了Task<T>,那么它应该在你的PCL中可用。可能你的目标是Windows Phone 7.5,它不支持Task。但是,我们发布了一个支持各种平台上的Task和async/await的包。请参阅此博客文章:http://blogs.msdn.com/b/bclteam/archive/2012/10/22/using-async-await-without-net-framework-4-5.aspx - Daniel Plaisted
@DanielPlaisted谢谢您的回答,我们发现我们的目标是Silverlight 4,这就是问题所在。在更改了我们的目标选项后,Task<T>现在可用了,但知道WP 7.5也有解决方案是很好的。 - Rati_Ge
我本来想采用同样的方法,但是似乎无法在我的PCL中安装sqlite-net,这意味着我无法使用像[PrimaryKey]这样的属性来装饰我的模型。仅在我的存储库具体实现中使用这些属性并没有帮助,因为模型应该在PCL中。你是怎么解决这个问题的? - Adrian Grigore
我们将pcl分割 - 在http://slodge.blogspot.co.uk/2013/05/n10-sqlite-persistent-data-storage-n1.html观看n = 10的视频。 - Stuart

5

Stuart提供了一个非常好的关于如何使用SQLite创建PCL的解释,但是今天我发现了这个方法,希望它可以更好地解决其他问题。

SQLite的新开源便携式类库


链接返回404。我尝试在以下网址中寻找等价物:https://opensource.microsoft.com/?sort=Awesomeness&keyword=sqlite&tag=但没有成功。 - riverswb

2

经过数周的寻找,我终于发现您需要使用以下方法进行连接:

var factory = new MvxWpfSqLiteConnectionFactory();

我已经安装了。
using Cirrious.MvvmCross.Community.Plugins.Sqlite;
using Cirrious.MvvmCross.Community.Plugins.Sqlite.Wpf;
using Cirrious.CrossCore;

对于所有的MVVMcross天才和Sqlite天才,这可能是显而易见的。

没有人在任何地方提到这一点,MVVMcross的示例都无法编译或使用 Sqlite.NET 进行连接,这也与 MVVM 和 PCL 不兼容。

哦,这在 Winforms、PCL 等中都可以工作(我甚至不使用 Wpf)。


我仍然无法使用索引或插入来获取“get { return _connection.Table<ListItem>(); }”。有人能帮助我吗? - user2959284
我的错,它可以工作。你需要多个条目才能使跳过起作用,插入是可以的。 - user2959284

2

值得一提的是,AutoIncrement和PrimaryKey属性来自以下命名空间:

using Cirrious.MvvmCross.Plugins.Sqlite;

  public class Reference : IBusinessEntity

    {

      public string Key { get; set; }

      public string Value { get; set; }



     [PrimaryKey, AutoIncrement]

      public long Id { get; set; }

  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接