Linq To SQLCE 可以对独立存储中的SQLCE进行基本的数据操作,但是,如何在已存在的数据库表中新建数据列,下文提供了非常优雅的解决方案。

In this article I am going to talk about how to update your database schema when updating your app. The problem is that if you change the database schema(for.ex: add new columns or tables) in a future version of your app, then when users that use the old version of your app update to the new one an exception occurs. So in practice if there is no additional code to change the database so that it is compatible with the latest version of the app the following exception occurs:(本文讨论如何升级app的数据库,问题的关键在于如果在未来版本的应用中更改了数据库,那么老版本的应用的用户升级到新版本是,那么新版应用在访问旧版数据库时,就要产生异常。)

So in this series of posts I will explain how to prevent this exception from happening. (本系列将讨论如何阻止异常出现。)

开始之前,首先新建一个wp应用程序,并按以下步骤操作。

Step1. Add a new class Person to the project with the following properties:(新建一个Person类)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
[Table(Name = "People")]
public class Person
{
    [Column(IsPrimaryKey = true, IsDbGenerated = true)]
    public int ID
    {
        get;
        set;
    }
    [Column(CanBeNull = false)]
    public string FirstName
    {
        get;
        set;
    }
    [Column(CanBeNull = true)]
    public string LastName
    {
        get;
        set;
    }
    [Column(CanBeNull = false)]
    public int Age
    {
        get;
        set;
    }
    public override string ToString()
    {
        return string.Format("{0} {1}, Age: {2}",
            this.FirstName, this.LastName, this.Age);
    }
}

Step2. Next add a new class PeopleDataContext to the project which will be our data context:(新建PeopleDataContext)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class PeopleDataContext : DataContext
{
    public PeopleDataContext(string connectionString)
        : base(connectionString)
    {
    }
    public Table<Person> People
    {
        get
        {
            return this.GetTable<Person>();
        }
    }
}

Step3. Next we will add a new button that will be used to initialize the database.(增加一个按钮来初始化数据库)

?
1
2
3
4
5
6
7
8
9
10
11
12
private void btnInitialize_Click(object sender, RoutedEventArgs e)
{
    using (PeopleDataContext context = new PeopleDataContext(ConnectionString))
    {
        if (!context.DatabaseExists())
        {
            // create database if it does not exist
            context.CreateDatabase();
            this.WritePeople(context);
        }
    }
}

Where WritePeople is the following method:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void WritePeople(PeopleDataContext context)
{
    for (int i = 0; i < 10; i++)
    {
        Person person = new Person()
        {
            FirstName = string.Format("FirstName#{0}", i),
            LastName = string.Format("LastName#{0}", i),
            Age = i
        };
        context.People.InsertOnSubmit(person);
    }
    context.SubmitChanges();
}

?
1
2
3
4
5
6
7
public void WritePeople()
{
    using (PeopleDataContext context = new PeopleDataContext(ConnectionString))
    {
        this.WritePeople(context);
    }
}

Step4. We will add one more button that we will use to read the data from the database(this is only for  testing purposes to prove that the database is functioning properly):(再添加一按钮,读取数据库)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void btnReadPeople_Click(object sender, RoutedEventArgs e)
{
    this.lbPeople.ItemsSource = this.ReadPeople();
}
public IEnumerable<Person> ReadPeople()
{
    IEnumerable<Person> people = null;
    using (PeopleDataContext context = new PeopleDataContext(ConnectionString))
    {
        people = context.People.ToList();
    }
    return people;
}

NOTE: All that the above code does is read the Person records from the database and show them in a ListBox.(上述代码仅是读取Person记录并显示在ListBox)

Step5. If we run the application now and press the initialize button and after that the read people button we should see the following screen.I.e. this is the first version of our database: (运行程序,依次点击initialize database、Read People,应该可以看到如下画面)

Step6. For the next version of our app we will update the Person class with two additional properties:(在Person类中,增添两个属性)

NOTE: It is important to notice that in the snippet below  the Address and the Email properties are added in the second version of the schema.(注意:Address & Email被添加了进来,友情提示,请注意预编译命令的使用。)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[Table(Name = "People")]
public class Person
{
   //...
#if DB_VERSION_1
    [Column(CanBeNull = true)]
    public string Address
    {
        get;
        set;
    }
    [Column(CanBeNull = true)]
    public string Email
    {
        get;
        set;
    }
#endif
    public override string ToString()
    {
#if DB_VERSION_1
        return string.Format("{0} {1}, Age: {2}, Email: {3}",
            this.FirstName, this.LastName, this.Age, this.Email);
#else
        return string.Format("{0} {1}, Age: {2}",
            this.FirstName, this.LastName, this.Age);
#endif
    }
}

NOTE: We will use the DB_VERSION_1 conditional compilation symbol in order to turn on code related to the second version of the database schema. (使用DB_VERSION_1条件编译符号来表明数据库的版本变化)

To turn the sections of the code marked with the DB_VERSION_1 symbol just add it to the conditional compilation symbols in the project`s Build properties:(DB_VERSION_1 的使用方法如下图所示)

Step7. If we were to run the application now without writing any additional code we will get the following exception:(工作未完,现在运行依然会得到如下异常)

To prevent this from happening we will add some code to update the database schema to include the Address andEmail columns. Here is how our initialize database method should look like now:(因此,我们必须在旧版的数据库中添加Address & Email 列)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private void btnInitialize_Click(object sender, RoutedEventArgs e)
{
    using (PeopleDataContext context = new PeopleDataContext(ConnectionString))
    {
        if (!context.DatabaseExists())
        {
            // create database if it does not exist
            context.CreateDatabase();
            this.WritePeople(context);
        }
        else
        {
            // create an instance of DatabaseSchemaUpdater
            DatabaseSchemaUpdater schemaUpdater = context.CreateDatabaseSchemaUpdater();
            // get current database schema version
            // if not changed the version is 0 by default
            int version = schemaUpdater.DatabaseSchemaVersion;
            // if current version of database schema is old
            if (version == 0)
            {
                // add Address column to the table corresponding to the Person class
                schemaUpdater.AddColumn<Person>("Address");
                // add Email column to the table corresponding to the Person class
                schemaUpdater.AddColumn<Person>("Email");
                // IMPORTANT: update database schema version before calling Execute
                schemaUpdater.DatabaseSchemaVersion = 1;
                // execute changes to database schema
                schemaUpdater.Execute();
            }
        }
    }
}

What will happen when the application is ran is the following:

  • for an updated application, since the database probably already exists the code in the else branch will execute. Here we create a new instance of the DatabaseSchemaUpdater class. Then we retrieve the current version of the database schema and if it is the older version we update the schema with the new columns, increase the schema version and execute the schema changes. (对于更新升级的应用,由于数据库已经存在,那么else分支将被执行,我们只用DatabaseSchemaUpdater的一个实例,来获取当前数据库版本,如果是旧版的数据库,添加相关数据列,并修改数据库版本号)
  • for a newly installed application a new database will be created (对于全新安装的应用,只需新建数据库即可)

Step8. To verify that the schema upgrade code works properly we will add a new button and will use the new properties added with the second version of the database schema:(验证数据库是否已更新)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void btnUpdatePeople_Click(object sender, RoutedEventArgs e)
{
#if DB_VERSION_1
    using (PeopleDataContext context = new PeopleDataContext(ConnectionString))
    {
        // for version 1 - update people records with email address
        List<Person> people = context.People.ToList();
        int count = people.Count;
        for (int i = 0; i < count; i++)
        {
            Person person = people[i];
            person.Email = string.Format("person{0}@domain.com", i);
        }
        context.SubmitChanges();
    }
#endif
}

Step9.Finally if we run the application and press the Initialize, Update and Read buttons we should see the following screen:

That`s it for now. In the next article we will discuss more complex changes to the database schema. Stay tuned.

You may also find helpful the following articles:

  • Windows Phone Mango Local Database(SQL CE)
  • Windows Phone Mango Local Database: mapping and database operations
  • Using SqlMetal to generate Windows Phone Mango Local Database classes

Here is the full source code:

WPLocalDBUpdateP1.zip

Hole the post was helpful.

You can also follow us on Twitter @winphonegeek

转载于:https://www.cnblogs.com/winkia/archive/2012/04/11/2442418.html

Windows Phone Local Database Schema Upgrade Part1 - Adding new columns相关推荐

  1. Windows Phone中使用Local DataBase与ISolateStorage—在MVVM模式下(—)

    像我们知道的一样,Windows Phone支持ISolateStorage,Mango中还新增了使用Linq的SQL CE作为本地数据库.下面我们就用MVVMLight来模拟个消息发送和查看消息历史 ...

  2. 一句话回复:关于'SqlMembershipProvider' requires a database schema compatible with schema version '1'...

    一个朋友说他建立好asp.net需要的membership-role关系后一直正常,后来运行了脚本,再运行时出现类似如下的错误 The 'System.Web.Security.SqlMembersh ...

  3. 如何在Windows Azure VM上的SQL Server和Windows Azure SQL Database两者中做出选择

    作者信息:本篇文章是由SQL Server Cloud Infrastructure Team的 Madhan Arumugam 和 Guy Bowerman共同著作. 简介 把SQL 数据托管在哪里 ...

  4. Android中在使用Room时提示:Cannot figure out how to save this field into database. You can consider adding a

    场景 在Android中使用Room进行存储数据库时提示: Cannot figure out how to save this field into database. You can consid ...

  5. 详解IDEA JPI持久化 import database schema 对话框

    https://www.jetbrains.com/help/idea/2016.2/import-database-schema-import-mappings.html 以上是官方描述IDEA的J ...

  6. Windows 下Oracle database 9i 64bit 仅仅有 Windows Itanium 64bit

    Windows 下Oracle database 9i 64bit 仅仅有 Windows Itanium 64bit,没有Windows x86-64bit的 详细请见例如以下的certificat ...

  7. Windows 下Oracle database 9i 64bit 只有 Windows Itanium 64bit

    Windows 下Oracle database 9i 64bit 只有 Windows Itanium 64bit,没有Windows x86-64bit的 Oracle does not plan ...

  8. 怎么实现一个分布式kv系统 #1 local database

    文章目录 摘要 环境配置 1. 远程服务器[可选择] 2. 配置VSCode 3. 设置go mod 编程实现 1. 导入boltdb 2. 设置flag 3. 创建HTTP API 4. DB模块 ...

  9. Windows 版Oracle Database 19c 下载安装步骤

    1.下载Oracle 19c数据库 Oracle官方下载链接: Oracle Software Downloads | Oracle Database Software Downloads | Ora ...

最新文章

  1. 【ACM】杭电OJ 2036(待更)
  2. 遗传算法c语言程序,遗传算法c语言代码.doc
  3. Respo 快速入门
  4. python对象编程例子-python(十二)面向对象编程、类
  5. update与merge
  6. 【NLP】Sentence-T5|谷歌提出文本表示新SOTA
  7. mysql-3 检索数据(1)
  8. POJ1260-Pearls
  9. mysql 多实例 独立配置文件_mysql 5.7 配置多实例 — 独立配置文件方式
  10. 解决mysql地区时间错误_mysql time zone时区的错误解决
  11. 《一个操作系统的实现》 ubuntu系统环境配置
  12. unittest 单元测试
  13. ListView控件简单用法
  14. 完整的元器件选型指南
  15. CleanMyMac XMac苹果电脑专属系统优化工具
  16. git 创建关联远程分支报错Did you intend to checkout ‘origin/branchName‘ which can not be resolved as commit?
  17. 《 C语言程序设计(第2版)》 读书笔记
  18. Creating a Circular Buffer in C and C++
  19. 2021年终总结:提高认知,摆脱传统工科桎梏
  20. 趣学算法NYOJ加勒比海盗船

热门文章

  1. C#之正则表达式、异常处理和委托与事件
  2. PDT + Xdebug 调试 PHP
  3. “3D几何与视觉技术”全球在线研讨会第四期~几何深度学习
  4. 年薪40W,如何高效准备大厂AI算法岗面试?
  5. 环境搭建、标注、训练、推断,超详细的目标检测开发流程
  6. TorchSeg—基于PyTorch的快速模块化语义分割开源库
  7. OpenCV 4.0 rc版本发布,扩展计算图Graph API
  8. 近期计算机视觉竞赛汇总—总奖池高达344万人民币
  9. 人生苦短,Python值得 这些Pandas隐藏小技巧你知道吗?
  10. 不懂Python装饰器?教程双手奉上!