Code First 和 SQL CE






4.69/5 (22投票s)
使用 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; }
}
测试
我们已经完成了。只需添加一个控制台程序,并引用 Dal 和 Model 项目以及 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 月 - 文章初版。