Code First :使用Entity. Framework编程(1)

CHAPTER 1 Welcome to Code First

第一章:欢迎来到Code First

(译者注:为方便起见,不再直译Code First)

Microsoft's ADO.NET Entity Framework, known widely as EF, introduced out-of-the- box Object Relational Mapping to .NET and Visual Studio. Central to Entity Frame- work was the Entity Data Model, a conceptual model of your application domain that maps back to the schema of your database. This conceptual model describes the core classes in your application. Entity Framework uses this conceptual model while querying from the database, creating objects from that data and then persisting changes back to the database.

微软ADO NET的实体框架,被称为EF,是一种框对象关系映射(ORM)模型,运行在NETVisual Studio上。实体框架的核心是实体数据模型(Entity Data Model,),也就您的应用程序域的概念模型映射到您的数据库架构描述。这种概念模型描述了您的应用程充中的核心类。而实体框架(EF)则使用这种概念模型从数据库中查询数据,根据数据创建对象并且将更改保存回数据库。

Modeling with EF Before Code First

在编写代码前构建EF模型

The first iteration of Entity Framework, which came as part of .NET 3.5 and Visual Studio 2008, gave developers the ability to create this conceptual model by reverse engineering an existing database into an XML file. This XML file used the EDMX extension, and you could use a designer to view and customize the model to better suit your domain. Visual Studio 2010 and .NET 4 brought the second version of Entity Framework, named Entity Framework 4 (EF4), to align with the .NET version. On the modeling side, a new capability called Model First was added. Here you could design your conceptual model in the visual designer and then create the database based on the model.

在使用.Net 3.5Visual Studio 2008构建的第一代EF中,给予了开发者通过将现存数据库转化为XML文件的形式来创建概念模型的能力。这种XML文件使用EDMX扩展名,可以保用设计器来查看和定制模型以便更好适应程序域。Visual Studio 2010 and .NET 4带来了EF新版本:称之为Entity Framework 4 (EF4),配合了.Net的版本。在模型创建时,引入了一种称为Model First功能,通过此功能可以先创建概念模型然后根据此模型再创建数据库。

Model First allows developers working on new projects that do not have legacy databases to benefit from the Entity Framework as well. Developers can start with a focus on their application domain by designing the conceptual model and let the database creation flow from that process.

Model First 允许开发者在没有传统数据库时就可以开始一个新的项目,这是EF框架带来的好处。开发者可以通过设计概念模型而首先关注应用程序域,从而让数据库的创建工作水到渠成。

Whether designing the EDMX by the database-first or model-first way, the next step for creating your domain is to let automatic code generation build classes based on the entities and their relationships that it finds in the model. From here, developers have strongly typed classes representing their domain objects—whether those are customers, baseball cards, or fairy-tale characters—and can go on their merry way developing their software applications around these classes.

无论是通过database-first还是通过model-first设计EDMX,下一步都是为了创建您的域以便让自动代码生成器基于实体以及找到的各种关系来创建类。通过这种方式,开发人员拥有强类型的类来指向域对象,无论它们是客户,棒球卡,还是童话人物,都可以围绕着这些类来欢快地开发软件应用。

Another critical change came in EF4. In .NET 3.5, the only way Entity Framework was able to manage in-memory objects was by requiring classes to inherit from Entity Framework's EntityObject. The EntityObject communicates its changes to Entity Framework, which in turns keeps track of changes and eventually is able to persist them back to the database. In addition to this functionality, .NET 4 introduced POCO (Plain Old CLR Object) support to enable the Entity Framework to track changes to simpler classes without needing the EntityObject to be involved. This freed up developers to use their own classes, independent of Entity Framework. The EF runtime had a way of being aware of the classes and keeping track of them while in memory.

另一个关键的变化在EF4。在.NET 3 5,唯一方式的实体框架是能够管理处于内存中的对象。这些对象的必须类都继承自实体框架的EntityObject对象。EntityObject对象向实体框架通知变化,并由实体框架跟踪这些变化并最终持久化到数据库中。除了此功能,NET 4中推出了 POCOPlain Old CLR Object,简单传统CLR对象),支持实体框架跟踪简化类的变化而不需要的EntityObject的参与,这使开发者可以自由使用自己的类,从而独立于实体框架。EF在运行时可以通过监视对象在内存中的行为保持对这些类的响应和跟踪。

Inception of Code First

Code First的发起

Building upon the pieces that were introduced in EF4, Microsoft was able to create one more path to modeling, which many developers have been requesting since EF's inception. This new type of modeling is called Code First. Code First lets you define your domain model with code rather than using an XML-based EDMX file. Even though Model First and Database First use code generation to provide classes for you to work with, many developers simply did not want to work with a designer nor have their classes generated for them. They just wanted to write code. In Code First you begin by defining your domain model using POCO classes, which have no dependency on Entity Framework. Code First can infer a lot of information about your model purely from the shape of your classes. You can also provide additional configuration to further describe your model or override what Code First inferred. This configuration is also defined in code: no XML files or designers.

基于前面介绍的有关EF4的片断,微软已经提供了多路径的建模方式,其中有一种新的方式是在EF发布之初,开发人员就所期待的。这种新型的建模方法就是所谓的Code First. Code first 首先让您定义域模型,而不是使用基于XMLedmx文件。即使采用Model FirstDatabase First来生成代码,开发者也无需使用设计器或类生成器来辅助工作。因为他们只想书写代码。使用Code First您可以通过使用POCO类来定义域模型来开始工作,而无需依赖于EF框架。Code First可以通过构建的类模型推断出大量信息。你也可以提供额外的配置,进一步描述有关模型的信息或者是重载Code Firstr推断的信息。这种配置也可以用代码来定义,无需XML文件或设计器。

EF4 also has support for POCO classes when working with the designer. The EF team provided a POCO template that would allow POCO classes to be generated for you. These generated classes would be automatically updated as you made changes in the designer. You could also use your own POCO classes rather than having them generated for you. But if you decided to take this approach, you were responsible for keeping your classes and the EDMX file in sync. This meant that any changes had to be made in two places—once in the designer and again in your classes. One of the big advantages of Code First is that your classes become the model. This means any changes to the model only need to be made in one place—your POCO classes.

使用设计器工作的EF4也支持POCO技术EF开发团队提供了一种POCO模板来生成POCO类。这些生成的类可以随着设计器的更改而自动更新。也也可以使用你自己创建的POCO类。但如果你决定这样做,就需要负责保持您的类与EDMX文件的同步。这意味着任何变更都必须在两个位置进行。Code First的一个最大好处就是让你的类变成了模型。这意味着改变模型就只需要在一处(你自已的POCO类)中作出更改即可。(指出最好不要用设计器来进行POCO设计译者注)。

Code First, Database First, and Model First are all just ways of building an Entity Data Model that can be used with Entity Framework to perform data access. Once the model has been built, the Entity Framework runtime behaves the same, regardless of how you created the model. Whether you choose to go with a designer or to use the code-based modeling is entirely your decision. Figure 1-1 lays out the different options you have for modeling with Entity Framework.

Code First, Database First,  Model First都只是一种建立可用于EF框架中以进行数据访问的实体数据模型的方式。一旦模型构建,EF框架在运行时的表现是相同的,与如何构建模型无关。选择从设计器开始还从代码开始完全取决于您的选择。图1-1列出了不同的可选项。

Microsoft refers to the Database First, Model First, and Code First options as workflows (e.g., the Code First workflow). That's because each of those options is really a set of steps, whether you execute the steps yourself or the steps happen automatically. For example, with the Database First workflow, you reverse engineer from a database and then let a code generator create the classes. The Code First workflow begins with you coding your classes and then optionally letting Code First create a database for you.

微软将Database First, Model First, Code First分别形成了可选的工作流程。这是因为每种选项都是一系列步骤,无论这些步骤是你自已实施还是自动进行。例如,使用Database First工作流,你需要将数据库转化为工程,然后让代码生成器创建类。而Code First工作流则开始于类的代码构建,然后选择用代码生成所用的数据库。

Getting Code First to Developers in Between .NET Releases

Code First was not ready in time to be released in .NET 4. Rather than waiting for the .NET 5 release to bring Code First to developers, Microsoft made Code First available in an out-of-band release, referred to as Entity Framework 4.1, in April 2011. The version number will increment as subsequent updates are released. Entity Framework 4.2 was released in October 2011 and replaces Entity Framework 4.1 as the release that included Code First. The core Entity Framework API, System.Data.Entity.dll, is still part of the .NET Framework and was untouched by Entity Framework 4.1 and 4.2. The Entity Framework 4.1 release also included another important feature, called the DbContext API. DbContext is the core of this API, which also contains other dependent classes. DbContext is a lighter-weight version of the Entity Framework's ObjectContext. It is a wrapper over ObjectContext, and it exposes only those features that Microsoft found were most commonly used by developers working with Entity Framework. The DbContext also provides simpler access to coding patterns that are more complex to achieve with the ObjectContext. DbContext also takes care of a lot of common tasks for you, so that you write less code to achieve the same tasks; this is particularly true when working with Code First. Because Microsoft recommends that you use DbContext with Code First, you will see it used throughout this book. However, a separate book, called Programming Entity Framework: DbContext, will delve more deeply into DbContext, DbSet, Validation API, and other features that arrived alongside the DbContext.

Code First .Net4发布时尚未准备好。微软不想将其在.Net5发布时才带给开发者,就在20114月推出了"号外"版,称为EF4.1.版本号随后在更新时顺延。201110月,EF4.2推出 ,替代了EF4.1,作为包含Code first的最新版本。核心APISystem.Data.Entity.dll,仍然是.Net Framework的一部分,没有与EF4.14.2紧连接。EF4.2还包含了另一个重要的功能,称之为DbContext API.DbContext是这个API的核心,除此之外还包含其他支持类。DbContext是一个轻量级的EF ObjectContext.这是一个包装过的ObjectContext,只暴露了那些微软认为大多数开发人员最常用EF功能。DbContext也支持通过代码模式访问由ObjectContext所提供的复杂功能。DbContext也提供了大量的通用任务,可以使开发者用较少的代码达到相同的目的,这在使用Code First时尤其明显。由于微软推荐使用DbContext来进行Code First操作,您会看到本书将贯穿始终介绍此方法。但是,另一本书,叫做Programming Entity Framework: DbContext,将为深入探讨DbContextDbSet验证API以及DbContext带来的其他特征。

Figure 1-2 helps you to visualize how Code First and DbContext add functionality by building on the core Entity Framework 4 API, rather than modifying it.

1-2帮助你查看如何通过构建EF4API核心添加Code FirstDbContext功能。

Flexible Release Schedule

灵活的发布日程

Microsoft will continue to release new features on top of Entity Framework using Visual Studio's Library Package Management distribution (aka NuGet) mechanism that is used for Entity Framework 4.2. The core EF libraries that are in .NET will evolve with .NET releases. But features such as Code First and DbContext that rely on the core will be distributed when they are ready by way of updates to the Entity Framework NuGet package.

微软将继续通过VS提供的NuGet工具发布基于EF4.2框架的新功能EF的核心库将会随着.Net的新版本的发布而内置在其中。但是诸如CodeFirst DbContext等核心功能会在EFNuGet包中不断得到更新。

Writing the Code…First

输入代码。。。

Code First is aptly named: the code comes first, the rest follows. Let's take a look at the basic default functionality without worrying about all of the possible scenarios you might need to support. The rest of the book is dedicated to that.

We don't expect you to recreate the sample code shown in this first chapter. The code samples are presented as part of an overview, not as a walkthrough. Beginning with Chapter 2, you will find many walkthroughs. They are described in a way that you can follow along in Visual Studio and try things out yourself if you'd like.

Of course, the first thing you'll need is some code—classes to describe a business domain. In this case a very small one, patients and patient visits for a veterinarian.

Code First 是个好听的名字:先写代码,然后向下来。让我们先看看一些基本的默认功能,不要管各种你可能会遇到的场景(余下的内容我们会专注于此)。

我们并不期望你重建本章的代码案例。这些案例只是作一概览,并不会深入。在第2章,你将会逐步深入。你将会跟随我们在VS中的操作进行,然后尝试你想实现的功能。

当然,首先需要一些代码,以便足以描述业务域。本案例是关于一个兽医院收治患畜的业务模型。

Example 1-1 Domain classes

using System;

using System.Collections.Generic;

namespace ChapterOneProject

{

class Patient

{

public Patient()

{

Visits = new List<Visit>();

}

public int Id { get; set; }

public string Name { get; set; }

public DateTime BirthDate { get; set; }

public AnimalType AnimalType { get; set; }

public DateTime FirstVisit { get; set; }

public List<Visit> Visits { get; set; }

}

class Visit

{

public int Id { get; set; }

public DateTime Date { get; set; }

public String ReasonForVisit { get; set; }

public String Outcome { get; set; }

public Decimal Weight { get; set; }

public int PatientId { get; set; }

}

class AnimalType

{

public int Id { get; set; }

public string TypeName { get; set; }

}

}

Core to Code First is the concept of conventions—default rules that Code First will use to build a model based on your classes. For example, Entity Framework requires that a class that it will manage has a key property. Code First has a convention that if it finds a property named Id or a property with the combined name of the type name and Id (e.g., PatientId), that property will be automatically configured as the key. If it can't find a property that matches this convention, it will throw an exception at runtime telling you that there is no key. Other types of conventions determine the default length of a string, or the default table structure that Entity Framework should expect in the database when you have classes that inherit from each other.

Code First 的核心是约定,这些默认的规则使我们可以用我们自己的类来创建模型。EF框架要求一个类必须有一个键属性。规则约定如果一个属性名为Id或者是类名+Id的形式(如PatientId),这一属性就被自动配置为键。如果无法找到满足这一规则的属性,将会在运行时抛出一个异常告诉你没有找到Key.其他约定包括确定字符串的默认长度,或者默认表结构,以及当类相互继承时如何在数据库内建表等等。

This could be very limiting if Code First relied solely on convention to work with your classes. But Code First is not determined to force you to design your classes to meet its needs. Instead, the conventions exist to enable Code First to automatically handle some common scenarios. If your classes happen to follow convention, Code First doesn't need any more information from you. Entity Framework will be able to work directly with your classes. If they don't follow convention, you can provide additional information through Code First's many configuration options to nsure that your classes are interpreted properly by Code First.

如果Code First完全依赖于这些规则去创建自己的类,需要做的工作是很有限的。但是Code First并不强制你按此要求设计类,这些规则的设计是为了Code First能够自动处理一些通用的场景。如果你的类遵从这些规则,Code First不会需要更多信息。EF框架会以你的类直接工作。如果不遵从这些规则,你就必须通过Code First的一些配置选项来提供一些附加信息以确保你的类能够与Code First 理解

In the case of the three classes in Example 1-1, the Id properties in each class meet the convention for keys. We'll let Code First work with these classes as they are without any additional configurations.

1-1的三个类,Id属性均符合键属性的规则要求。使用这三个类按Code First工作不需要增加任何配置。

Managing Objects with DbContext

使用DbContext管理对象

The domain classes described above have nothing to do with the Entity Framework. They have no knowledge of it. That's the beauty of working with Code First. You get to use your own classes. This is especially beneficial if you have existing domain classes from another project.

前述的域与EF框架无关。从代码开始很美好,你可以开始使用你自己的类。如果你从其他项目中现存的域类开始将获得特别的好处。

To use Code First, you start by defining a class that inherits from DbContext. One of the roles of this class, which we'll refer to as a context, is to let Code First know about the classes that make up your model. That's how Entity Framework will be aware of them and be able to keep track of them. This is done by exposing the domain classes through another new class introduced along with DbContext—the DbSet. Just as DbContext is a simpler wrapper around the ObjectContext, DbSet is a wrapper around Entity Framework 4's ObjectSet, which simplifies coding tasks for which we normally use the ObjectSet.

使用Code First,您应该定义一个继承自DbContext的类。此类的其中一个角色,应被指作为context,以便让Code First知道有关类需要用于创建模型。这就是EF框架如何感知类以及如何保持跟踪这些类的原因。这需要引入另一个新类:DbSet。正如DbContext是一个简单包装的ObjectContext, DbSet是一个包装过的EF4ObjectSet对象,同样简化了正常使用ObjectSet的编码任务量。

Example 1-2 shows what this context class might look like. Notice that there are DbSet properties for Patients and Visits. The DbSets will allow you to query against the types. But we don't anticipate doing a direct query of AnimalTypes, so there's no need for a DbSet of AnimalTypes. Code First is smart enough to know that Patient makes use of the AnimalType class and will therefore include it in the model.

1-2展示了这种context类的基本样式注意到其中有一个用于Patients VisitsDbSet属性。DbSets允许你查询类型。但我们不能指望直接查询AnimalTypes,因此不需要一个AnmialTypeDbSet.Code First 足够聪明知道Patient使用AnimalType类,因此会包含在模型内。

Example 1-2. VetContext class which derives from DbContext

using System.Data.Entity;

namespace ChapterOneProject

{

class VetContext:DbContext

{

public DbSet<Patient> Patients { get; set; }

public DbSet<Visit> Visits { get; set; }

}

}

Using the Data Layer and Domain Classes

使用数据层和域类

Now here comes what may seem a little surprising. This is all you need for a data layer—that is based on the assumption that you're going to rely 100 percent on Code First convention to do the rest of the work.

现在你可能会有一些惊讶。数据层是你所需要全部,这基于你100%按照Code First的假设继续后面的工作。

There's no database connection string. There is not even a database yet. But still, you are ready to use this data layer. Example 1-3 shows a method that will create a new dog PatientType along with our first Patient. The method also creates the Patient's first Visit record and adds it to the Patient.Visits property.

这里没有数据库连接字符串,甚至连数据库也没有。但你仍然需要使用数据层。例1-2显示了一个创建新病患对象的方法。这个方法也创建了该病患的信息以及第一次治疗记录;

Then we instantiate the context, add the patient to the DbSet<Patient> (Patients) that is defined in the context, and finally call SaveChanges, which is a method of DbContext.

然后我们将此实例装入context,添加到DbSet<Patient>(Patinets)中(前已定义为context,最后调用DbContextSaveChanges方法保存数据。

private static void CreateNewPatient()

{

var dog = new AnimalType { TypeName = "Dog" };

var patient = new Patient

{

Name = "Sampson",

BirthDate = new DateTime(2008, 1, 28),

AnimalType = dog,

Visits = new List<Visit>

{

new Visit

{

Date = new DateTime(2011, 9, 1)

}

}

};

using(var context = new VetContext())

{

context.Patients.Add(patient);

context.SaveChanges();

}

}

Remember that there's no connection string anywhere and no known database. Yet after running this code, we can look in the local SQL Server Express instance and see a new database whose name matches the fully qualified name of the context class,ChapterOneProject.VetContext.

记住目前还没有任何连接字符串,也没有任何数据库。然后运行这些代码后,我们会在本地的SQL Server Express找到名字与context类完全匹配新的数据库:ChapterOneProject.VetContext

You can see the details of this database's schema in Figure 1-3.

有关此数据的结构图示见图1-3.

Compare the database schema to the classes defined in Example 1-1. They match almost exactly, table to class and field to property. The only difference is that a foreign key, Patients.AnimalType_Id, was created, even though there was no foreign key property in the Patient class. Code First worked out that because of the relationship expressed in the class (Patient has a reference to AnimalType), a foreign key would be needed in the database to persist that relationship. This is one of many conventions that Code First uses when it's dealing with relationships. There are many ways to express relationships between classes. Code First conventions are able to interpret many of them. Notice, for example, that the PatientId field, which has an explicit property in the Visit class, is not null, whereas the AnimalType_Id field that Code First inferred from a navigation property is nullable. Again, convention determined the nullability of the foreign keys, but if you want to modify how Code First interprets your classes, you can do so using additional configuration.

将数据库构架与例1中定的类相对比,表与类,字段与属性几乎完全匹配,唯一的区别是外键,尽管在Patient类中并没有外键属性,但Patients.AnimalType_Id外键依然创建了。Code First得到此外键是根据类中表现出的关系确定的。(注意到PatientAnimalType有一个引用),在数据库中外键用来维持表间的关系。在这种处理关系的方面Code First提供了很多便利。在类中有很多方式来表达类间的关系。Code First能够方便地识别这些关系。注意,PatientId字段,在类中本来是明确指向Visit类的属性,是非空的,而来自于导航属性的AnimalType_Id字段是可空的。约定再一欠确定了外键的可空性,如果想要修改这些字段,让Code First按照您想法来表达,就需要使用附加的配置。

Getting from Classes to a Database

从类到数据库

If you have worked with Entity Framework, you are familiar with the model that is expressed in an EDMX file that you work with in a visual designer. You may also be aware of the fact that the EDMX file is in fact an XML file, but the designer makes it much easier to work with. The XML used to describe the model has a very specific schema and working with the raw XML would be mind-boggling without the designer.

如果您在EF框架下工作过,一定会熟悉采用EDMX文件表达的可视化模型。你也可以意识到EDMX文件实际上就是一个XML文件,但是设计器使其工作更加容易。使用XML来描述模型需要专门的构架元素,没有设计器处理XML源文件是相当耗费脑筋的。

What is not as obvious in the designer is that the XML contains more than just the description of the conceptual model that is displayed in the designer. It also has a description of database schema that the classes map to and one last bit of XML that describes how to get from the classes and properties to the tables and columns in the Figure 1-3. The new database created by Code First database. The combination of the model XML, the database schema XML, and the mapping XML are referred to as metadata.

很显然显示在设计器上的内容并非XML文件内容的全部。这一文件中还有一些数据库构架的描述,以使类能够映射到类似图1-3中相应的表和列中。模型XML,数据库构架XML和映射XML都被引用为元数据。

At runtime, the Entity Framework reads the XML that describes all three parts of the XML and creates an in-memory representation of the metadata. But the in-memory metadata is not the XML; it is strongly typed objects such as EntityType, EdmProperty, and AssociationType. Entity Framework interacts with this in-memory representation of the model and schema every time it needs to interact with the database.

在运行时,EF框架读取前述三部分的XML文件并在内存中创建元数据的代理。但是在内存中的元数据不是XML,而是强类型的对象,如EntityType, EdmProperty AssociationType.EF框架与这种在内存中的模型代理进行交互,需要时与数据库进行交互操作。

Because there is no XML file with Code First, it creates the in-memory metadata from what it can discover in your domain classes. This is where convention and configuration come into play. Code First has a class called the DbModelBuilder. It is the DbModel Builder that reads the classes and builds the in-memory model to the best of its ability. Since it is also building the portion of the metadata that represents the database schema, it is able to use that to create the database. If you add configurations to help the model builder determine what the model and database schema should look like, it will read those just after it inspects the classes and incorporate that information into its understanding of what the model and database schema should look like.

由于Code First并没有XML文件,其内存中元数据是根据您的域类集合生成的。这里是约定与配置在起作用Code First有一个称为DbMOdelBuilder的类。这个类读取域中的类集合,然后构建内存模型。由于其也可以构建代表数据库构架的元数据,因此可以用来创建数据库。如果增加配置信息帮助模型构建器确定哪一个模型和数据库构架应该看起来一致,模型构建器就会检查这些类,并将有关信息集成进模型中,使数据库构架与设想的一致。

Figure 1-4 shows how Entity Framework can build the in-memory model from code or from an XML file maintained through the designer. Once the in-memory model is created, Entity Framework doesn't need to know how the model was created. It can use the in-memory model to determine what the database schema should look like, build queries to access data, translate the results of queries into your objects, and persist changes to those objects back to the database.

1-4显示了EF框架如何从代码或XML文件(由设计器维护和操作)中创建内存模型。一旦内存模型得以构建,EF框架不再需要知道模型是如何创建的。也可使用内存的模型来确定数据库架构是怎样的,可以构建查询访问数据,将查询结果返回对象,将对象的变化更新回数据库。

Working with Configuration

使用配置

In those cases where Code First needs some help understanding your intent, you have two options for performing configuration: Data Annotations and Code First's Fluent API. Which option you choose is most often based on personal preference and your coding style. There is some advanced configuration that is only possible via the Fluent API.

在某些场合下需要协助Code First理解你的意图时,你有两个选择来实施配置:Data Annotations(数据注解)和Code FirstFluent API.根据个人喜好可以任选其一。有一些高级配置只有在使用Fluent API时才能实现。

Code First allows you to configure a great variety of property attributes, relationships, inheritance hierarchies, and database mappings. You'll get a sneak peek at configuration now, but the bulk of this book is dedicated to explaining the convention and configuration options that are available to you.

Code First允许您配置各种属性,关系,继承,级别和数据库映射。现在我们给出一个示例,先睹为快。本书将把精力和时间放在解释约定和对你有用的配置属性上去。

Configuring with Data Annotations

使用Data Annotations配置

One way to apply configuration, which many developers like because it is so simple, is to use Data Annotations. Data Annotations are attributes that you apply directly to the class or properties that you want to affect. These can be found in the System.ComponentModel.DataAnnotations namespace.

很多开发者喜欢使用Data Annotations配置方式,因为其非常简单。Data Annotations将一些特性直接应用于想要影响的类或属性上。这些特性可以在System.ComponentModel.DataAnnotations命名空间里找到。

For example, if you want to ensure that a property should always have a value, you can use the Required annotation. In Example 1-4, this annotation has been applied to the AnimalType's TypeName property.

例如,如果你想确保一个属性应总是有一个值,你就可以使用Required特性。例1-4AnimalType类的TypeName属性上应用了这一特性。

Example 1-4. Using an annotation to mark a property as required

class AnimalType

{

public int Id { get; set; }

[Required]

public string TypeName { get; set; }

}

This will have two effects. The first is that the TypeName field in the database will become not null. The second is that it will be validated by Entity Framework, thanks to the Validation API that was also introduced in Entity Framework 4.1. By default, when it's time to SaveChanges, Entity Framework will check to be sure that the property you have flagged as Required is not empty. If it is empty, Entity Framework will throw an exception.

这会有两个效果。第一个是数据库中的TypeName字段将会设置为非空。第二个将会实现由EF框架提供的验证,得益于EF4.1框架引入的验证API。默认情况下,当保存更改时,EF框架将检查确保被标记为Required的属性是非空的。如果为空,将会抛出异常。

The Required annotation affects the database column facets and property validation. Some annotations are specific only to database mappings. For example, the Table annotation tells Code First that the class maps to a table of a certain name. The data that you refer to as AnimalType in your application might be stored in a table called Species. The Table annotation allows you to specify this mapping.

Required特性影响数据库列的各个方面和属性验证。许多特性以用于数据库映射。例如,Table特性告诉Code First该类映射到一个具有某个名子的表中。应用程序中的AnimailType数据完全可以存储在称为Species的表中。Table特性允许指定这种映射。

Example 1-5. Specifying a table name to map to

[Table("Species")]

class AnimalType

{

public int Id { get; set; }

[Required]

public string TypeName { get; set; }

}

Configuring with the Fluent API

使用Fluent API配置

While applying configurations with Data Annotations is quite simple to do, specifying metadata within a domain class may not align with your style of development. There is an alternative way to add configurations that uses Code First's Fluent API. With configuration applied via the Fluent API, your domain classes remain "clean." Rather than modify the classes, you provide the configuration information to Code First's model builder in a method exposed by the DbContext. The method is called OnModelCreating. Example 1-6 demonstrates the same configurations that were used above, but now applied using the Fluent API. In each configuration, the code specifies that the model builder should configure the AnimalType.

使用Data Annotations非常简单,在域中的类中指定元数据可能不适应你的开发风格。有一个替代的方法来添加配置,就是使用Code First's Fluent API.使用Fluent API,你的域类始终保持"清洁"。你的配置信息通过重写DbContext暴露的方法OnModelCreating来进行。例1-6展示了与前述相同的配置,这个示例使用的是Fluent APIn。在每个配置中,代码指出了model bulider如何配置AnimalType.

Example 1-6. Configuring the model using the Fluent API

class VetContext:DbContext

{

public DbSet<Patient> Patients { get; set; }

public DbSet<Visit> Visits { get; set; }

protected override void OnModelCreating

(DbModelBuilder modelBuilder)

{

modelBuilder.Entity<AnimalType>()

.ToTable("Species");

modelBuilder.Entity<AnimalType>()

.Property(p => p.TypeName).IsRequired();

}

}

The first configuration uses the Fluent API equivalent of the Table Data Annotation, which is the ToTable method, and passes in the name of the table to which the AnimalType class should be mapped. The second configuration uses a lambda expression to identify one of the properties of AnimalType and then appends the IsRequired method to that property.

第一个使用Fluent API的配置等价于Data Annotation Table特性,现在是ToTable方法,传递了一个表名指定了AnimalType类应该生成为该表;第二个配置使用了一个Lambda表达式指定AnimalType的一个属性应用IsRequired方法。

This is just one way to build fluent configurations. You will learn much more about using both Data Annotations and the Fluent API to configure property attributes, relationships, inheritance hierarchies, and database mappings in the following chapters.

这只是一个建立配置的方法。你将会在后续的章节中学到更多有关使用Data Annotations Fluent API的知识,用于配置属性、关系,继承,层级和数据库映射等。

Creating or Pointing to a Database

创建或指向数据库

Earlier in this chapter, you saw that by default Code First created a SQL Server Express database. Code First's database connection handling ranges from this completely automated behavior to creating a database for you at a location designated in a connection string. There are a lot of variations to being able to drop and recreate a database when your model changes during development.

前面,你已经看到默认代码创建了一个SQL Server Express数据库。Code First完全自动调用了内置的连接字符串生成了数据库。

You'll find that Chapter 6 is dedicated entirely to how Code First interacts with your database.

你将在第6章完全了解Code First是如何与你的数据库进行交互的。

The examples in this book will walk you through how to configure database mappings. These concepts apply equally to generating a database or mapping to an existing database. When generating a database, they affect the schema that is generated for you. When mapping to an existing database, they define the schema that Entity Framework will expect to be there at runtime.

本书中的示例将逐步介绍如何配置数据库映射。这些概念同样适用于生成数据库和映射到一个已经存在的数据库。当生成数据库时,其影响生成的构架。当影响到存在的数据库时,其定义的构架必须与EF框架希望在运行时生成的一致。

As we explore Code First conventions and configuration in this book, we will be allowing Code First to create a database. This allows you to run the application after each step and observe how the database schema has changed. If you are mapping to an existing database, the only difference is to point Code First at that database. The easiest way to do that is described in "Controlling Database Location with a Configuration File" on page 130 (Chapter 6). You will also want to take a look at "Reverse Engineer Code First" on page 173 (Chapter 8).

在我们探索Code First的约定和配置时,我们也会允许Code First创建数据库。这就使得运行应用程序的每个步骤都可以看到数据库构架的变化。如果映射到一个已经存在的数据库,唯一的区别是为数据库point Code First.(暂时不知如何译,回头改进,译者注)。最容易的办法在本书第130面中的"使用配置文件控制数据库位置"(第6章),也可以看看173页的"逆向工程Code First"(8)

What Code First Does Not Support

Code First 不支持的情况

Code First is a relatively new addition to Entity Framework and there are a few features that it currently does not support. The EF team has indicated that they plan to add support for most of these in future releases.

Code First 是新加入到EF框架中的技术,有几个特性目前尚不支持。EF开发团队指出他们正在计划在未来版本中加入这些特性。

Database migrations

数据迁移

At the time of writing this book, Code First does not yet support database migrations, or in other words, modifying a database to reflect changes to the model. But work on this feature is well under way and will likely be available shortly after publication. You can read about an early preview of the Migrations support on the team's blog.

在写这本书的时候,Code First尚不支持数据迁移,换句话说,修改数据反映在模型的变化上。但是这一特性在不久的将来就可能发布。也可以在该团队的blog获取有关数据迁移的早期预览版。

Mapping to views

映射到视图

Code First currently only supports mapping to tables. This unfortunately means that you can't map Code First directly to stored procedures, views, or other database objects. If you are letting Code First generate a database, there is no way to create these artifacts in the database, other than manually adding them once Code First has created the database. If you are mapping to an existing database, there are some techniques you can use to get data from non-table database artifacts.

Code First目前只支持映射到表。这一不幸意味着不能将Code First直接映射到存储过程,视图或其他数据库对象。如果你正使用Code First来生成数据库,没有办法直接将这些特性加到数据库,必须手工添加在Code First已经创建的数据里。如果映射到一个现存的数据库,有一些其他的技术可以用来获取数据库中非表格数据。

These techniques are described in "Mapping to Nontable Database Objects" on page 153 (Chapter 7).

这些技术描述为"映射到非表格数据库对象"153页,第7章。

Schema definition defining queries

架构定义查询

Entity Framework includes a Defining Query feature that allows you to specify a database query directly in the XML metadata. There is also a Query View feature that allows you to use the conceptual model to define a query that is used to load entities. This allows the query you specify to be database provider–independent. Code First does not support either of these features yet.

EF框架包含一个定义查询特性使得您可以指定数据库直接查询XML元数据中的数据。同时也有一个查询视图特性允许使用概念模型定义 查询用于载入实体。这些都允许你指定数据库Provider-independent.Code First尚不支持这些特性。

Multiple Entity Sets per Type (MEST)

每类型多重实体

Code First does not support the Multiple Entity Sets per Type (MEST) feature. MEST allows you to use the same class in two different sets that map to two different tables. This is a more obscure Entity Framework feature that is rarely used. The EF team has said that, in an effort to keep the Code First API simpler, they do not plan to add support for MEST.

Code First尚不支持MESTMESR允许使用同一个类在两个不同的数据集中映射到不同的表中。这是EF构架的一个隐含特性,很少用到。EF团队表示,为了确保Code First API的简化,他们不打算加入对MEST的支持。

Conditional column mapping

条件列映射

When working with inheritance hierarchies, Code First also requires that a property is always mapped to a column with the same name. This is referred to as conditional column mapping. For example, you may have a Person base class with a NationalIdentifier property. American and Australian classes that derive from the Person base class are mapped to separate Australians and Americans tables in the database. When using the designer, you could map the NationalIdentifier property to an SSN column in the Americans table and PassportNumber in the Australians table. Code First does not support this scenario. The column that NationalIdentifier maps to must have the same name in every table.

继承层次结构时,Code First还需要一个属性始终具有相同的名称映射到列,这称作条件列映射。例如,有一个Person基类具有一个NationalIdentifier属性。AmericanAustralian类都是派生自Person基类分别映射到数据库中单独的AmericansAustralians表中。当使用设计器时,你可映射NationalIdentifier属性到Americans表中的SSN列,映射到Australians表中的PassportNumber列。Code First 并不支持这种情况。映射到各个表中的NationalIdentifier必须具有同一名称。

Choosing Code First

选择Code First

Now that you know what Code First is, you may be wondering whether it's the right modeling workflow for your application development. The good news is that the decision is almost entirely dependent on what development style you, or your team, prefer.

现在你已经知道什么是Code First,你可能还在犹豫是否这是一种正确的应用程序开发模型工作流。好消息是这完全取决于你和你团队的开发风格。

If writing your own POCO classes and then using code to define how they map to a database appeals to you, then Code First is what you are after. As mentioned earlier, Code First can generate a database for you or be used to map to an existing database.

如果你喜欢书写自己的POCO类然后使用代码定义如何映射到数据库,Code First是你要选择的。正如前面提到的,Code First可以为你生成数据库或者映射到已存在的数据库;

If you prefer to use a designer to define the shape of your classes and how they map to the database, you probably don't want to use Code First. If you are mapping to an existing database, you will want to use Database First to reverse engineer a model from the database. This entails using Visual Studio's Entity Data Model Wizard to generate an EDMX based on that database. You can then view and edit the generated model using the designer. If you don't have a database but want to use a designer, you should consider using Model First to define your model with the designer. You can then create the database based on the model you define. These approaches work well, provided you are happy for EF to generate your classes for you based on the model you create in the designer.

如果你更喜欢用设计器定义你的类,并且用可视化的方式映射到数据库,你可能不能使用Code First.如果你需要映射到一个现存的数据库,你可能会想用Database Firstdatabase逆向工程为模型。这种实体使用VS的实体数据模型向导生成基于数据库EDMX文件。你可以使用设计器查看和编辑生成的模型。如果尚没有数据库而仍然要使用设计器,你应该使用设计器以Model First定义你的模型。根据创建的模型再创建数据库。这些方法工作良好,在设计器中你会很好地应用你的类。

Finally, if you have existing classes that you want to use with EF, you probably want to go with Code First even if your first preference would be for designer-based modeling. If you choose to use the designer, you will need to make any model changes in the designer and in your classes. This is inefficient and error-prone, so you will probably be happier in the long run if you use Code First. In Code First, your classes are your model, so model changes only need to be made in one place and there is no opportunity for things to get out of sync.

最后,如果你想针对现存的类使用EF框架,你可能会选择Code First,即便你第一选择可能是基于模型的设计器。如果选择了设计器,你需要在设计器对模型和类作出调整。这种方式低效易出错,而使用Code First可能会获得长久。在Code First中,你的类就是模型,因此模型变更只需要在一处,不需要所谓的同步操作。

A designer tool that the Entity Framework team is working on will provide an additional option—reverse engineering a database into Code First classes and fluent configurations. This tool was created for developers who have an existing database but prefer using Code First to using a designer. You'll learn more about this tool in Chapter 8.

EF团队正在对设计器进行改进以加入附加功能:将数据库逆向工程到支持Code FirstFluent配置的 类。这一工具将为已经拥有数据库但是更想使用Code First的开发者提供。你可以在第8章获取更多信息。

The decision process for which EF workflow to use can be summarized in the decision tree shown in Figure 1-5.

EF工作流的选择总结如图1-5.

Learning from This Book

从本书中学到

This book will focus on building and configuring a model with Code First. It is an extension to Programming Entity Framework (second edition) and you'll find many references back to that book, rather than duplicating here the nearly 900 pages of detailed information about how Entity Framework functions; how to query and update;using it in a variety of application types and automated tests; and how to handle exceptions, security, database connections and transactions. Creating a model with Code First is just one more feature of the Entity Framework.In fact, as you move forward to Chapter 2, you'll find that the domain model changes from the veterinarian sample used in Chapter 1 to the business model of Programming Entity Framework, software applications built for a company called Break Away Geek Adventures.Look for a second short book titled Programming Entity Framework: DbContext, which will focus on DbContext, DbSet, Validation API, and using the features that are also part of the Entity Framework NuGet package.

本书关注采用Code First构建和配置模型。这是一种采用EF框架编程的扩展,在本书背后你会找到很多参考,不在这复制近900页的有关EF框架的详细信息,而是关注于如何实现查询,更新;如何在各种应用类型中使用;如何自动测试;如何处理异常,安全,数据库连接和事务。采用Code First 创建模型只是EF框架中诸多特性中的一个。事实上,当进入第二章,你会发现案例兽医医院的域模型将会变为可编为应用程序的业务模型,称之Break Away Geek Adventures.第二本书名为《编程实体框架:DbContext》,将集中于DbContextDbSet,验证API,并使用NuGet包装的Enfity Framework的一部分的功能。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值