65.9K
CodeProject 正在变化。 阅读更多。
Home

Code First 和 SQL CE

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.69/5 (22投票s)

2013年11月8日

CPOL

3分钟阅读

viewsIcon

110702

downloadIcon

8166

使用 SQL CE 4.0 数据库的 Code First 示例项目

引言

在本文中,我将介绍一个使用 Entity Framework 6 和 Code First 的示例项目。该项目是 DVD 收藏应用程序的一部分,使用 SQL CE 数据库。我认为 Code First 方法对于项目开发和原型设计非常有效。

整个项目使用 C# 编写,在 Windows 7 上使用 Visual Studio 2010 开发。

SQL CE

Microsoft SQL Server Compact (SQL CE) 是由 Microsoft 生产的一个紧凑、免费的单文件 关系数据库,适用于在移动设备和桌面计算机上运行的应用程序。在引入桌面平台之前,它被称为 SQL Server for Windows CE 和 SQL Server Mobile Edition。最新版本是 SQL Server Compact 4.0  ,支持 .NET Framework 4.0

更多信息。 

构建 

该解决方案分为三个项目 - 它们都基于 .NET 4.0。

  • Model: Model - 包含用于数据持久化和业务逻辑的实体类的项目
  • Dal: 数据访问层 - 包含 `DbContext` 类的项目,该类负责访问数据库
  • Test: 用于测试解决方案的控制台程序

模型

我们从这个项目开始构建解决方案 - 因为这个项目定义了我们的数据库模型。

使用 NuGet,我们下载并引用 Entity Framework。我们还添加了 .NET `System.ComponentModel.DataAnnotations` 的引用。现在我们可以开始编写模型代码了。我们只需定义我们的实体:

  • Role.cs
  • FilmGenere.cs
  • FilmTitle.cs
  • Actor.cs
  • Producer.cs
  • FilmActorRole.cs

我们使用注解来帮助数据库生成。

  • [Key] - 定义主键属性 - Id
  • [Required] - 定义必需的,例如 非空
  • [StringLength(LEN)] - 定义最大字符长度

对于关系,我们包含 `ForeignKey` 字段和类字段,并用注解标记:

  • [ForeignKey(ForeignKeyField)]

例如 `FilmTitle` 类

public class FilmTitle
{
    [Key]
    public int Id { get; set; }
    [Required]
    [StringLength(100)]
    public String Title { get; set; }
    [Required]
    [StringLength(1000)]
    public String Story { get; set; }
    [Required]
    public DateTime ReleaseDate { get; set; }
    [Required]
    public int Duration { get; set; }
    [StringLength(1000)]
    public String Notes { get; set; }

    [Required]
    public int FilmGenereId { get; set; }
    [ForeignKey("FilmGenereId")]
    public FilmGenere FilmGenere { get; set; }

    public List<Producer> Producers { get; set; }

    public List<FilmActorRole> FilmActorRoles { get; set; }
} 

添加完所有模型类后,我们开始新项目。

Dal

首先,我们必须使用 NuGet 添加对 Entity framework 的引用,以及对 Model 项目的引用。

此项目中的主类是 `DvdContext`,它继承自 `DbContext`。在此类中,我们添加我们实体类的 `DBSet`。

我们的 `DvdContext` 现在看起来像这样:

public class DvdContext : DbContext
{
    public DbSet<Actor> Actors { get; set; }
    public DbSet<FilmActorRole> FilmActorRoles { get; set; }
    public DbSet<FilmGenere> FilmGeneres { get; set; }
    public DbSet<FilmTitle> FilmTitles { get; set; }
    public DbSet<Producer> Producers { get; set; }
    public DbSet<Role> Roles { get; set; }
} 

测试

我们已经完成了。只需添加一个控制台程序,并引用 DalModel 项目以及 Entity Framework

由于我们使用的是 SqlCe,我们还必须使用 NuGet 添加对 `EntityFramework.SqlServerCompact ` 的引用。

现在我们可以开始使用我们的数据库了。让我们编写一个简单的查询到我们的 `DvdContext`。

static void Main(string[] args)
{
    using (Dal.DvdContext db = new Dal.DvdContext())
    {
        db.Actors.ToList();
    }
} 

运行应用程序后,会在项目的 Build 文件夹中创建一个数据库文件:CFSqlCe.Dal.DvdContext.sdf。如果我们使用 Visual Studio 服务器资源管理器连接数据库文件,我们可以看到所有必需的表都已创建。

Customizing

数据库文件

数据库文件的命名方式与我们的 `DvdContext` 的完整类名相同。我们可以通过写入 App.config 文件中的连接字符串来覆盖此名称。

<connectionStrings>
    <add name="CFSqlCe.Dal.DvdContext" 
    providerName="System.Data.SqlServerCe.4.0" 
    connectionString="Data Source=D:\DvdDatabase.sdf" />
</connectionStrings> 

上面的连接 string 将我们的 DvdContext 映射到我们系统上的 DvdDatabase.sdf 文件。运行应用程序后,会创建 DvdDatabase.sdf

初始化

Code First 的默认数据库初始化是“如果不存在则创建”。我们可以使用自定义数据库初始化类来控制这一点。

数据库初始化程序是通过我们 `DvdContext` 的 static 构造函数设置的。

static DvdContext()
{
    // Database initialize
    Database.SetInitializer<DvdContext>(new DbInitializer());
    using (DvdContext db = new DvdContext())
        db.Database.Initialize(false);
}

class DbInitializer : DropCreateDatabaseAlways<DvdContext>
{
} 

有了这个初始化程序,我们的数据库将在每次运行应用程序时被重新创建。这对于开发来说非常方便。

种子

数据库初始化程序的另一个优点是可以在创建后填充数据。我们只需重写我们 `DbInitializer` 的 Seed 方法即可完成此操作。

class DbInitializer : DropCreateDatabaseAlways<DvdContext>
{
protected override void Seed(DvdContext context)
{
    // insert some file generes
    context.FilmGeneres.Add(new FilmGenere()
    {
        Name = "Action"
    });
    context.FilmGeneres.Add(new FilmGenere()
    {
        Name = "SciFi"
    });
    context.FilmGeneres.Add(new FilmGenere()
    {
        Name = "Comedy"
    });
    context.FilmGeneres.Add(new FilmGenere()
    {
        Name = "Romance"
    });
    // some roles
    context.Roles.Add(new Role()
    {
        Name = "Lead"
    });
    context.Roles.Add(new Role()
    {
        Name = "Supporting"
    });
    context.Roles.Add(new Role()
    {
        Name = "Background"
    });
    // some actors
    context.Actors.Add(new Actor()
    {
        Name ="Chris",
        Surname ="Pine",
        Note = "Born in Los Angeles, California"
    });
    context.Actors.Add(new Actor()
    {
        Name = "Zachary",
        Surname = "Quinto",
        Note = "Zachary Quinto graduated from 
        Central Catholic High School in Pittsburgh"
    });
    context.Actors.Add(new Actor()
    {
        Name = "Tom",
        Surname = "Cruise"
    });
    // producers
    context.Producers.Add(new Producer()
    {
        FullName = "J.J. Abrams",
        Email = "jj.adams@producer.com",
        Note = "Born: Jeffrey Jacob Abrams"
    });
    base.Seed(context);
} 

查询和录入数据

现在,是时候尝试添加一些数据并查询我们刚刚创建的数据库了。在我们的测试项目中,我添加了两个 `FilmTitles`。

using (Dal.DvdContext db = new Dal.DvdContext())
{
    // film generes
    Model.FilmGenere actionGenere = db.FilmGeneres.Where
    (g => g.Name == "Action").SingleOrDefault();
    Model.FilmGenere scifiGenere = db.FilmGeneres.Where
    (g => g.Name == "SciFi").SingleOrDefault();
    // find the producer
    Model.Producer jjAbrams = db.Producers.Where
    (p => p.FullName == "J.J. Abrams").SingleOrDefault();
    // we found the producer
    if (jjAbrams != null)
    {
        // add some films to that producer
        Model.FilmTitle film1 = new Model.FilmTitle()
        {
            Title = "Mission: Impossible III",
            ReleaseYear = 2006,
            Duration = 126,
            Story = "Ethan Hunt comes face to face with a dangerous and ...",
            FilmGenere = actionGenere
        };
        film1.Producers = new List<Model.Producer>();
        film1.Producers.Add(jjAbrams);
        db.FilmTitles.Add(film1);
        Model.FilmTitle film2 = new Model.FilmTitle()
        {
            Title = "Star Trek Into Darkness",
            ReleaseYear = 2013,
            Duration = 132,
            Story = "After the crew of the 
            Enterprise find an unstoppable force  ...",
            FilmGenere = scifiGenere
        };
        film2.Producers = new List<Model.Producer>();
        film2.Producers.Add(jjAbrams);
        db.FilmTitles.Add(film2);
        // add some film roles
        Model.Role leadRole = db.Roles.Where(r => 
        r.Name == "Lead").SingleOrDefault();
        Model.Role supportingRole = db.Roles.Where(r => 
        r.Name == "Supporting").SingleOrDefault();
        // load the actors
        Model.Actor tom = db.Actors.Where(a => 
        a.Surname == "Cruise").SingleOrDefault();
        Model.Actor quinto = db.Actors.Where(a => 
        a.Surname == "Quinto").SingleOrDefault();
        Model.Actor pine = db.Actors.Where(a => 
        a.Surname == "Pine").SingleOrDefault();
        // add filmroles
        db.FilmActorRoles.Add(new Model.FilmActorRole()
        {
            Actor = tom,
            Role = leadRole,
            FilmTitle = film1,
            Character = "Ethan",
            Description = "Ethan Hunt comes face to face with 
            a dangerous and sadistic arms dealer while trying to 
            keep his identity secret in order to protect his girlfriend."
        });
        db.FilmActorRoles.Add(new Model.FilmActorRole()
        {
            Actor = pine,
            Role = leadRole,
            FilmTitle = film2,
            Character = "Kirk",
            Description = "Captain Kirk"
        });
        db.FilmActorRoles.Add(new Model.FilmActorRole()
        {
            Actor = quinto,
            Role = supportingRole,
            FilmTitle = film2,
            Character = "Spock",
            Description = "Spock was born in 2230, 
            n the city of Shi'Kahr on the planet Vulcan"
        });
    }
    // save data to db
    db.SaveChanges();
} 

结论

SQL CE 伴随 Code First 使我们能够使用简单的本地数据库引擎快速原型化项目。通过数据库初始化程序,我们可以快速删除和重新创建更改的实体以及示例数据。当我们频繁更改模型时,这种方法非常有用。

迁移到生产 SQL Server 数据库非常简单。

如需进一步阅读,建议您参考

历史

  • 2013 年 11 月 - 文章初版。
© . All rights reserved.