|
适用于: Windows Phone 8 | Windows Phone OS 7.1
从 Windows Phone OS 7.1 开始,可以将关系数据存储在驻留在应用本地文件夹的本地数据库中。Windows Phone 应用使用 LINQ to SQL 执行所有数据库操作;LINQ to SQL 用于定义数据库架构、选择数据,并将更改保存到驻留在本地文件夹中的基础数据库文件。本主题提供了在 Windows Phone 应用中使用本地数据库的概述。有关创建使用本地数据库的应用的分步演练,请参见如何为 Windows Phone 创建基本的本地数据库应用。
本主题包含以下各节。
[url=]体系结构概述[/url]
为了存储和检索本地数据库中的数据,Windows Phone 应用使用 LINQ to SQL。LINQ to SQL 为处理数据提供了一种面向对象的方法,它由一个对象模型和运行时组成。
LINQ to SQL 对象模型主要是由 System.Data.Linq.DataContext 对象构成,可充当本地数据库的代理。LINQ to SQL 运行时负责桥接对象部分(DataContext 对象)和数据部分(本地数据库)。下图概括了这一关系。

[url=]数据上下文[/url]
数据上下文是一种代理,一个代表数据库的对象。数据上下文包含若干 Table 对象,其中的每一个对象都表示数据库中的一个表。每一个 Table 对象由对应数据库中数据行的实体所组成。每个实体都是一个具有属性的“简单传统 CLR 对象”(POCO)。每个实体上的属性决定数据库表结构,并定义数据对象模型与数据库架构之间的映射。例如,具有 Name 和 PhoneNumber 属性的实体将生成具有 Name 和 PhoneNumber 列的数据库表。
[url=]LINQ to SQL 运行时[/url]
LINQ to SQL 提供了一些对象关系映射功能,托管应用可通过这些功能使用语言集成查询 (LINQ) 与关系数据库(仅指 Transact-SQL)进行通信。LINQ to SQL 将对象模型(通过 .NET Framework 托管代码表示)映射到关系数据库。当您的应用运行时,LINQ to SQL 将语言集成查询转换为 Transact-SQL,然后将查询发送至数据库进行执行。当数据库返回结果时,LINQ to SQL 将结果转换回可通过您自己的编程语言进行处理的对象。有关更多信息,请参见 LINQ to SQL。
注意: | Windows Phone 上的 LINQ to SQL 不能直接支持执行 Transact-SQL,包括数据定义语言 (DDL) 或数据模型语言 (DML) 语句。此外,Windows Phone 应用无法使用 LINQ to SQL 直接访问 ADO.NET 对象。有关更多信息,请参阅 Windows Phone 的 LINQ to SQL 支持。
|
[url=]异同点[/url]
与使用 SQL Server 关系数据库的桌面应用类似,Windows Phone 应用可以通过 LINQ to SQL 使用本地数据库选择、插入、更新和删除数据。这样,您的 Windows Phone 应用就可以从 LINQ 的强大查询功能和关系数据库的存储效率中获益。由于手机所具有的资源少于 PC,因此本地数据库和典型数据库在某些方面存在差异。这些差异包括:
- 本地数据库将会在 Windows Phone 应用的进程中运行。和客户端服务器数据库不同(如 Microsoft SQL Server),它不会作为后台服务持续运行。
- 本地数据库仅可由对应的 Windows Phone 应用访问。由于数据库文件驻留在本地文件夹中,因此其他应用无法访问该数据。
- 本地数据库仅可通过 LINQ to SQL 访问;Transact-SQL 不受支持。
[url=]应用开发[/url]
在标准应用部署中,会于该应用首次运行时在本地文件夹中创建本地数据库。然后在使用应用时,将应用数据添加到数据库。若要对应用预填充一组引用数据,请向应用添一个本地数据库文件。有关分步说明,请参见如何使用 Windows Phone 应用部署参考数据库。
若要通过应用部署引用数据,您需要执行以下步骤:
- 创建帮助器应用程序:帮助器应用在您的开发计算机上运行、在本地文件夹中创建本地数据库,并为数据库加载所需的引用数据。
- 从帮助器应用程序中提取本地数据库:使用独立存储资源管理器 (ISETool.exe) 将数据库从帮助器应用复制到计算机上的文件夹。有关独立存储资源管理器的更多信息,请参见如何使用 Windows Phone 的独立存储资源管理器工具。
- 创建主应用程序:创建将使用引用数据的应用。
- 将引用数据添加到主应用程序:使用 Visual Studio 将本地数据库文件从计算机上保存该文件的文件夹添加到主应用。若要最大程度地减少应用程序集大小,请将文件存储为“内容”。
在本地数据库随应用部署后,它将驻留在安装文件夹中,并处于只读状态。安装文件夹不同于本地文件夹。若要处理位于此位置的数据库文件,请使用 appdata: 前缀。关于对数据库连接字符串使用前缀的示例,请参阅 Windows Phone 的本地数据库连接字符串。
重要说明: | 如果您将从安装文件夹以独占方式访问参考数据库文件,则不建议对其进行加密。如果加密,会在首次连接时阻止系统执行例行的数据库维护操作,例如重新建立索引。要使用加密的参考数据库,可在使用前将其复制到本地文件夹,然后使用读写连接来连接到它。有关如何复制它的更多信息,请参见如何使用 Windows Phone 应用部署参考数据库。
|
若要修改包含引用数据的数据库,请首先将其移出安装文件夹并保存在本地文件夹中,然后再尝试进行数据库更改。若要移动数据库文件,可以通过 Application.GetResourceStream 方法执行基于流的复制操作来从安装文件夹创建一个流,并通过 IsolatedStorageFileStream.Write 方法将流写入本地文件夹。以下示例演示在您创建流对象时如何处理安装文件夹中的数据库文件。
[url=]C#[/url]
Stream str = Application.GetResourceStream(new Uri("appdata:/MyReferenceDB.sdf", UriKind.Relative)).Stream;
[url=]定义数据上下文[/url]
若要创建本地数据库,必须首先定义数据上下文和实体。这些类定义数据对象模型和数据库架构之间的映射。LINQ to SQL 的对象关系功能根据这些映射详细信息来创建映射到对应数据上下文的关系数据库。
对于每个实体,使用 LINQ to SQL 映射属性指定映射详细信息。这些属性指定特定于数据库的功能,例如表、列、主键和索引。有关更多信息,请参阅基于属性的映射 (LINQ to SQL)。例如,以下代码显示名为 ToDoDataContext 的数据上下文以及名为 ToDoItem 的实体类的开头。
[url=]C#[/url]
public class ToDoDataContext : DataContext{ // Specify the connection string as a static, used in main page and app.xaml. public static string DBConnectionString = "Data Source=isostore:/ToDo.sdf"; // Pass the connection string to the base class. public ToDoDataContext(string connectionString): base(connectionString) { } // Specify a single table for the to-do items. public Table<ToDoItem> ToDoItems;}// Define the to-do items database table.public class ToDoItem : INotifyPropertyChanged, INotifyPropertyChanging{ // Define ID: private field, public property, and database column. private int _toDoItemId; [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)] public int ToDoItemId { get { return _toDoItemId; } set { if (_toDoItemId != value) { NotifyPropertyChanging("ToDoItemId"); _toDoItemId = value; NotifyPropertyChanged("ToDoItemId"); } } } . . . . . . . . .
[table]
注意:
这只是数据上下文代码的一部分。有关创建使用本地数据库的应用的分步演练,请参见如何为 Windows Phone 创建基本的本地数据库应用。
若要在代码中使用本地数据库功能,您需要在代码文件顶部添加以下指令。
[url=]C#[/url]
using System.Data.Linq;using System.Data.Linq.Mapping;using Microsoft.Phone.Data.Linq;using Microsoft.Phone.Data.Linq.Mapping;
下表显示了某些常见 LINQ to SQL 映射属性。若要获得完整列表,请参见 System.Data.Linq.Mapping。
特性
| 示例
| 说明
| TableAttribute
| [Table]
| 将某个类指定为与数据库表关联的实体类。
| ColumnAttribute
| [Column(IsPrimaryKey = true)]
| 将某个类与数据库表中的列关联。IsPrimaryKey 指定主键,默认情况下会为其创建一个索引。
| IndexAttribute
| [Index(Columns="Column1,Column2 DESC", IsUnique=true, Name="MultiColumnIndex")]
| 在表级别写入,指定表上的其他索引。每个索引都可涵盖一个或多个列。
| AssociationAttribute
| [Association(Storage="ThisEntityRefName", ThisKey="ThisEntityID", OtherKey="TargetEntityID")]
| 指定用于表示关联的属性,例如表示主键关联的外键。
|
[url=]创建数据库[/url]
在创建 DataContext 对象之后,可以创建本地数据库并执行一些其他数据库操作。以下代码示例演示如何创建基于 ToDoDataContext 类数据上下文的数据库。
[url=]C#[/url]
// Create the database if it does not yet exist.using (ToDoDataContext db = new ToDoDataContext("isostore:/ToDo.sdf")){ if (db.DatabaseExists() == false) { // Create the database. db.CreateDatabase(); }}
如该示例中所示,若要创建数据上下文,必须首先指定数据上下文和数据库文件的文件位置。DataContext 构造函数值指定数据库文件名称为 ToDo.sdf。该值的 isostore:/ 部分指定该文件位于本地文件夹中。接下来,在 DatabaseExists 方法确认数据库尚不存在之后,使用 CreateDatabase 方法创建数据库。
注意: | 在创建数据库时,它会自动分配一个为 0 的版本。若要确定数据库版本,请使用 DatabaseSchemaUpdater 类,如本主题后文更改数据库架构中所示。
|
[url=]使用数据库[/url]
在本地数据库创建之后,您可以使用 LINQ 和数据上下文来处理本地数据库。以下小节介绍了如何在数据库中选择、插入、更新和删除数据。有关创建执行这些操作的分步演练,请参见如何为 Windows Phone 创建基本的本地数据库应用。
选择数据(数据库查询)在 Windows Phone 中,使用语言集成查询 (LINQ) 查询数据库。LINQ 可弥补对象部分和数据部分之间的间隙。LINQ to SQL 中查询使用的语法与 LINQ 中的查询相同。有关 LINQ 查询的更多信息,请参阅 LINQ 查询简介 (C#)。
由于 LINQ to SQL 查询中引用的对象被映射到数据库中的记录,因此 LINQ to SQL 在查询的执行方式上与其他 LINQ 技术有所不同。典型的 LINQ 查询在应用层的内存中执行。通过 LINQ to SQL 使用运行时的对象关系功能,每一个 LINQ 查询都被转换为 Transact-SQL,然后在数据库中直接执行。这可以提高查询的性能,例如从一个较大的数据库中挑选几个记录。
在以下示例中,将使用 LINQ to SQL 查询名为 toDoDB 的 DataContext 对象,然后其结果被放置在名为 ToDoItems 的 ToDoItem 对象的 ObservableCollection 中。由于延迟执行,数据库查询直到实例化 ToDoItems 集合之后才会实际执行。
[url=]C#[/url]
// Define query to gather all of the to-do items.var toDoItemsInDB = from ToDoItem todo in toDoDB.ToDoItems select todo;// Execute query and place results into a collection.ToDoItems = new ObservableCollection<ToDoItem>(toDoItemsInDB);
插入数据将数据插入数据库的过程分为两个步骤。首先在数据上下文中添加一个对象,然后调用数据上下文 SubmitChanges 方法将数据保存为数据库中的一行。有关更多信息,请参见如何:将行插入数据库 (LINQ to SQL)。
在以下示例中,创建了一个 ToDoItem 对象,并将其添加到 ToDoItems 可观察集合以及名为 toDoDB 的数据上下文中对应的数据库表。
[url=]C#[/url]
// Create a new to-do item based on text box.ToDoItem newToDo = new ToDoItem { ItemName = newToDoTextBox.Text };// Add the to-do item to the observable collection.ToDoItems.Add(newToDo); // Add the to-do item to the local database.toDoDB.ToDoItems.InsertOnSubmit(newToDo);
重要说明: | 数据直到调用 SubmitChanges 方法之后才保存到数据库。
|
更新数据更新本地数据库中的数据分为三个步骤。首先,在数据库中查询要更新的对象。然后,按需要修改对象。最后,调用 SubmitChanges 方法将更改保存到本地数据库。有关更多信息,请参见如何:更新数据库 (LINQ to SQL) 中的行。
如果将数据上下文中的对象绑定到页面上的控件,则数据上下文会根据用户交互自动进行更新。然后,所需的唯一步骤是在需要时调用 SubmitChanges 方法。此方法的示例可在本地数据库示例应用程序中找到,如如何为 Windows Phone 创建基本的本地数据库应用中所述。以下代码示例显示了在用户导航离开页面时调用 SubmitChanges 方法的示例。
[url=]C#[/url]
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e){ //Call base method base.OnNavigatedFrom(e); //Save changes to the database toDoDB.SubmitChanges();}
重要说明: | 数据直到调用 SubmitChanges 方法之后才更新到数据库。
|
删除数据删除数据库中的数据也包含三个步骤:首先,在数据库中查询要删除的对象。然后,根据您需要删除一个还是多个对象,分别调用 DeleteOnSubmit 或 DeleteAllOnSubmit 方法,以将这些对象置于挂起删除状态。最后,调用 SubmitChanges 方法将更改保存到本地数据库。有关更多信息,请参见如何:从数据库 (LINQ to SQL) 删除行。
在以下示例中,从名为 toDoDB 的数据库中删除了一个 ToDoItem 对象。由于只删除一个对象,因此在 SubmitChanges 之前调用 DeleteOnSubmit 方法。
[url=]C#[/url]
//Get a handle for the to-do item bound to the buttonToDoItem toDoForDelete = button.DataContext as ToDoItem;//Remove the to-do item from the observable collectionToDoItems.Remove(toDoForDelete);//Remove the to-do item from the local databasetoDoDB.ToDoItems.DeleteOnSubmit(toDoForDelete);//Save changes to the databasetoDoDB.SubmitChanges();
重要说明: | 数据直到调用 SubmitChanges 方法之后才会从数据库中删除。
|
[url=]更改数据库架构[/url]
对 Windows Phone 应用的更改可能需要更改您的本地数据库架构。对本地数据库架构所做的任何更改都从更改对应数据上下文的对象模型开始。Microsoft.Phone.Data.Linq 命名空间提供了 DatabaseSchemaUpdater 类以帮助对数据库架构进行更改。有关如何使用此类的示例,请参见演练:更新 Windows Phone 本地数据库应用。
DatabaseSchemaUpdater 类可执行对数据库的累积更改,例如添加表、列、索引或关联。对于更复杂的更改,需要在适当情况下创建新的数据库,并将数据复制到新架构。DatabaseSchemaUpdater 类提供了一个 DatabaseSchemaVersion 属性,它可用于以编程方式区分数据库的不同版本。
重要说明: | 数据库在调用 Execute 方法之后才会进行更改,以反映 DatabaseSchemaUpdater 对象中的更改。当调用该方法时,所有更改(包括版本更新)都将作为单个事务提交到本地数据库。使用单个事务有助于数据库保持完整性,例如在用户于升级过程中退出应用的情况下。
|
以下示例演示如何使用 DatabaseSchemaUpdater 类来基于 DatabaseSchemaVersion 属性修改数据库。
[url=]C#[/url]
using (ToDoDataContext db = new ToDoDataContext(("isostore:/ToDo.sdf"))){ //Create the database schema updater DatabaseSchemaUpdater dbUpdate = db.CreateDatabaseSchemaUpdater(); //Get database version int dbVersion = dbUpdate.DatabaseSchemaVersion; //Update database as applicable if (dbVersion < 5) { //Copy data from existing database to new database MigrateDatabaseToLatestVersion(); } else if (dbVersion == 5) { //Add column to existing database to match the data context dbUpdate.AddColumn<ToDoItem>("TaskURL"); dbUpdate.DatabaseSchemaVersion = 6; dbUpdate.Execute(); }}
注意: | 在应用更新过程中,本地文件夹中保存的任何文件(包括本地数据库文件)都不会发生修改。
|
[url=]数据库安全性[/url]
本地数据库提供了密码保护和加密功能来确保数据库的安全。在对数据库使用密码功能时,整个数据库都会被加密。若要加密数据库,请在创建数据库之前在数据库连接字符串(数据上下文构造函数)中提供密码。每次访问数据库时都需要提供密码。在数据库创建之后便无法对其加密。数据库是使用 AES-128 加密的,而密码是使用 SHA-256 进行哈希处理的。
以下示例演示如何通过在数据库连接字符串中指定密码来创建加密数据库。
[url=]C#[/url]
// Create the data context, specify the database file location and passwordToDoDataContext db = new ToDoDataContext ("Data Source=’isostore:/ToDo.sdf’ assword=’securepassword’");// Create an encrypted database after confirming that it does not existif (!db.DatabaseExists()) db.CreateDatabase();
有关对本地数据库使用连接字符串的更多信息,请参阅 Windows Phone 的本地数据库连接字符串。
本文摘自:http://msdn.microsoft.com/zh-cn/library/hh202860
|
|