Tải bản đầy đủ
Objective 2.5: Create an Entity Framework data model

Objective 2.5: Create an Entity Framework data model

Tải bản đầy đủ

■■
■■

Data is structured in third normal form so data integrity is improved.
A much simpler implementation. Adding or removing an entity can be accomplished
by simply adding or deleting the underlying table in the database.

There are downsides however and they include:
■■
■■

There is a performance decrease, particularly around CRUD operations.
Makes database administration more complicated because of all the additional tables
in the system.

Table-per-Hierarchy inheritance, on the other hand, is characterized by the use of one
database table for each item in the inheritance hierarchy. Table-per-Hierarchy has several
advantages and disadvantages as well. The benefits include:
■■
■■

Fewer database tables leading to a simplified database schema.
Notably faster CRUD operations in most cases. (This is because all of the data is stored
in one table.)

However with the benefits come costs and they are not inconsequential:
■■

There is necessary data redundancy, and because one of the main purposes of normalizing data is to remove redundancy, this is not a small issue.

■■

Data integrity issues are more likely because of data redundancy.

■■

Because of the data model, complexity is increased.

There’s no one best answer or a one-size-fits-all solution. For the exam, pay close attention
to the verbiage that will emphasize aspects that will lead you to choose one approach over
the other.

Choosing and implementing an approach to manage a
data model (code first vs. model first vs. database first)
Choosing a data model is an important concept but there’s little to learn here. You have a
specific set of options, and they aren’t complex.
You can create an empty model and then add entities to it. As you add these entities, you
can define relationships between them and control how they behave. After you define your
EDM, you can elect to generate a database from the EDM; and the EF handles the database
creation, the object/entity creation, and the mapping between them for you.
Or you can start with a database schema. From there, you can access any visible database
object and generate an entity set from it. Again, the EF handles the creation of the Entity
items and all the mapping that’s needed between them.

146

CHAPTER 2

Querying and manipulating data by using the Entity Framework

MORE INFO  MODEL-FIRST DEVELOPMENT

The two approaches mentioned previously include starting with the database schema
and using it as the basis of your model, or building a model and having the tools generate the database. The model-first approach was introduced in EF version 4.0 and Visual
Studio 2010. It is an extremely powerful and useful paradigm, although it is not always
feasible. Full coverage of the costs and benefits of model-first are beyond the scope of this
book (for example, Julia Lerman dedicated an entire book to the subject), but is definitely
something beneficial to learn. If you are not familiar with it, you might want to read the
MSDN discussion (available at this link: http://msdn.microsoft.com/en-us/data/ff830362.
aspx) or Julia’s book (available here: http://thedatafarm.com/blog/data-access/model-firstdatabase-first-or-code-first-ndash-update-to-data-points-column/ ).

You can take an existing model and change it as well. If the back end changes, you can regenerate the entities based on those changes, or you can visually edit the mappings between
the new items and existing entity properties so that no breaking changes occur. (It is not
always possible to fully avoid breaking changes, but they can be kept to a minimum through
proper planning and design.)
MORE INFO  MANAGING BREAKING CHANGES

Breaking changes are, as the name implies, changes made to a newer version of software
that necessitate changes by consuming applications. They are costly and force clients to
either postpone a software update or to immediately deal with addressing your changes.
Needless to say, although inevitable at times, breaking changes are costly and problematic,
so great care should be taken to avoid them. An entire book, or even a series of books, can
be written about managing and avoiding breaking changes, so a comprehensive discusssion is well outside this book and exam’s scope. However, being aware of how they happen
is the first step in minimizing breaking changes from being introduced. Brad Abrams has
an excellent discussion on MSDN that’s well worth the read: (http://blogs.msdn.com/b/
brada/archive/2005/03/22/400461.aspx).

The two approaches include starting with the database schema and using the designer as
a starting point.
Take a look at how this works. First, you need to add an ADO.NET EDM to your project or
open an existing one, as shown in Figure 2-2.



Objective 2.5: Create an Entity Framework data model

CHAPTER 2

147

FIGURE 2-2  Adding an ADO.NET EDM

Next, you need to choose which approach you want to use. You can generate a model
from a database or start with an empty model. Then build the entities and generate a
database from it (or map it to an existing one). For this instance, opt for the Generate From
Database option, as shown in Figure 2-3.

148

CHAPTER 2

Querying and manipulating data by using the Entity Framework

FIGURE 2-3  Generate from Database option

Next, specify connection information about the database. You have the option of including
or excluding sensitive information, and you can optionally save it in the application’s configuration file, as shown in Figure 2-4.



Objective 2.5: Create an Entity Framework data model

CHAPTER 2

149

FIGURE 2-4  Choosing database connection information

Next is where the metaphorical rubber hits the road with the model. You are presented
with all the database objects your connection permissions allow. Typically, you should choose
Tables, but you also have views, functions, and stored procedures available if they are present.
Select all of Tables, as shown in Figure 2-5.

150

CHAPTER 2

Querying and manipulating data by using the Entity Framework

FIGURE 2-5  Choosing your database objects and settings

After you select the items, select Finish and you’ll be presented with a canvas that shows
each entity and the relationship it has to the other entities. If done correctly, you should see a
designer surface that looks like Figure 2-6.

FIGURE 2-6  Entity diagram

The last thing you need to do is click inside the designer surface and then right-click and
select Properties. You’ll see the Properties grid, which has several options about the model
you’ll want to take note of (see Figure 2-7).



Objective 2.5: Create an Entity Framework data model

CHAPTER 2

151

FIGURE 2-7  Conceptual model properties window

The properties are self-evident, but there’s an XAML-based workflow generated, which is
used to generate a database from the conceptual model if you choose to do so. You can indicate whether to use lazy loading; choose the namespaces you want to use; indicate the container access levels; and a few others, such as whether to pluralize the names of new objects.
If you click around on any of the entities or their properties, you can see clues that you’re
dealing with .NET classes. The following is a list of class properties that can be changed (via
the Properties grid or by editing the underlying code file):
■■
■■

Whether or not the type is Nullable. Because the class property types can be Value
types, you need to set the Nullable value to true if you want to use nulls instead of
default values.

■■

Get and set accessor visibility levels via the Getter and Setter properties.

■■

An autogenerated value for the field via the Default Value property.

■■

152

The Base Class Library type, via the Type property in the Properties grid.

Ensuring that another user or process has not changed the value you’re referencing prior
to submitting a save with the Concurrency Mode property. To ensure that the value has
not changed, you need to set the Concurrency Mode property to Fixed. There are two
very noteworthy aspects of this property. First, there is currently no way to set this value
at the entity level; you have to set it individually on each property. (This may be changed
in a future update, but there's no hard documentation on it at the time of this writing.)
The second is that setting this property to Fixed has performance implications. When set,
prior to an attempt to save the record, the database must be queried to determine what
the current value of the field is. Fortunately, if multiple fields are set to Fixed, they are

CHAPTER 2

Querying and manipulating data by using the Entity Framework

consolidated into one query. So if you have 50 fields set to Fixed, one query determines
that a value has changed, not 50 individual ones.
Click any one of the entities generated and examine the Properties window. Notice that
you can select a Base type, and if you click in the grid to set a type, you will encounter a list
of other types currently defined in the model. This means exactly what you would expect it
would: One item can inherit from another, from another, from another (see Figure 2-8).

FIGURE 2-8  Designer canvas

As you can see, you can create new entity types, associations, inheritance definitions, and
complex types. After you finish, you can select the Generate Database from Model option,
and all the new items you added will appear there.

Implementing POCOs
You can (and frequently will) employ plain old common objects (POCOs) with your data
model. To use a POCO, you simply need to abide by a few guidelines:
■■

The name of the entity type must match the POCO name.

■■

Each entity property must map to a public POCO property.

■■

The names of the types and the actual property types themselves must map and be
equivalent (obviously there’s no magic that can map the name “Microsoft” to a GUID).

When you define an entity in the EF, the default behavior is for EF to write .NET classes
that match the definition you specify in the designer. Obviously, things can’t work both ways;
either your classes are generated for you, or you need to define them because the current
incarnation of the EF won’t build them for you. Because autogeneration is the default behavior, you need to disable it in order to build your POCOs. If you examine your model, you
can see a value specified for the Custom Tool property in the Properties grid. Removing this
value tells Visual Studio that it should not generate the corresponding classes. Examine the



Objective 2.5: Create an Entity Framework data model

CHAPTER 2

153

following code snippet, which is the autogenerated code that Visual Studio created for the
TransactionDetails entity definition specified earlier:
namespace ObjectiveOne
{
using System;
using System.Collections.Generic;
public partial class TransactionDetail
{
public System.Guid DetailId { get; set; }
public System.Guid TransactionId { get; set; }
public string Vendor { get; set; }
public string ItemId { get; set; }
public Nullable TransactionTime { get; set; }
public virtual Transaction Transaction { get; set; }
}
}

So what would the equivalent POCO look like? It would be virtually identical:
namespace ObjectiveOne
{
using System;
using System.Collections.Generic;
public partial class TransactionDetail
{
public System.Guid DetailId { get; set; }
public System.Guid TransactionId { get; set; }
public string Vendor { get; set; }
public string ItemId { get; set; }
public Nullable TransactionTime { get; set; }
}
}

As this example illustrates, other than the Transaction property, there is no real difference
in the scalar values defined. Now, this definition is virtually identical, but what if you were
building a POCO that contained a reference that was the “many” portion of a one-to-many
relationship? It is quite simple, really. You build out the scalar properties as shown here, but
add a property (defined as a generic type list using the “many” class definition).
You need to manually create each class that you want to employ as a POCO after instructing Visual Studio to refrain from autogenerating the items. The last step after doing this is
to effectively wire up the POCO(s) to the context. If this step isn’t done, then there’s no way
for the context (either the DbContext or ObjectContext, depending on the EF version you’re

154

CHAPTER 2

Querying and manipulating data by using the Entity Framework

using) to know these classes exist and therefore manipulate them. Fortunately, wiring these
classes up to the context is quite easy; simply do the following:
1. Define a property in the context corresponding to each POCO you created.
2. Define the property using the ObjectSet (if you’re using an ObjectContext) or DbSet

(if you’re using the DbContext) generic class, specifying your POCO as the target
definition.
3. Add code to the context’s constructor, initializing the property calling the

CreateObjectSet base class method (again, passing in the POCO class definition to the
method).
The approach to adding POCOs to a context is virtually identical whether you use the
DbContext or ObjectContext, but both are covered in this section. For the sake of simplicity,
assume that there is a POCO corresponding to each of the entity types shown in Figure 2-8.

DbContext
For each POCO, decorate the class definition with the Table attribute, specifying a name of
the underlying table (pluralizing in most cases):
[Table("Account")]
public class Account{}
[Table("Customers")]
public class Customers{}[Table("TransactionDetails")]
public class TransactionDetail{}Table("Transactions")]
public class Transaction{}

The previous examples assume that you have the ScalarProperty and NavigationProperty
items created. After they are built, though, you simply need to define them in the DbContext
and they are ready for use:
public partial class EntityFrameworkSamplesEntitiesDb : DbContext
{
public EntityFrameworkSamplesEntitiesDb(): base("name=EntityFrameworkSamples​
Entities1")
{}
public DbSet Accounts { get; set; }
public DbSet Customers { get; set; }
public DbSet TransactionDetails { get; set; }
public DbSet Transactions { get; set; }
}



Objective 2.5: Create an Entity Framework data model

CHAPTER 2

155

ObjectContext
If you use ObjectContext, the process is virtually identical, but has a few small differences. First, your context inherits from the ObjectContext base class instead of the DbContext class. Next, the properties inside the context are typed as DbSet types instead of
ObjectSet types. Finally, you need to initialize the properties in the constructor using the new
ObjectSet(); syntax:
public partial class EntityFrameworkSamplesEntitiesSample : ObjectContext
{
public EntityFrameworkSamplesEntitiesSample(): base("name=EntityFramework​
SamplesEntities1")
{
Accounts = new ObjectSet();
Customers = new ObjectSet();
TransactionDetails = new ObjectSet();
Transactions = new ObjectSet();
}
public ObjectSet Accounts { get; set; }
public ObjectSet Customers { get; set; }
public ObjectSet TransactionDetails { get; set; }
public ObjectSet Transactions { get; set; }
}

At this point, your POCOs are built and defined correctly, the properties in your context
are defined, and the properties have been wired up and are ready to use.

Describing a data model using conceptual schema
definitions, storage schema definitions, and mapping
language (CSDL, SSDL, & MSL)
The current version of the EF wraps each of the component elements in the .edmx file, but
this is more of a grouping difference than anything else. It is absolutely critical to understanding the role of each and why it matters. After you have that understanding, how they are
stored becomes little more than a matter of elegance and convenience.
MORE INFO  .EDMX FILE

In the original versions of the EF, an entity model comprised a CSDL file, an SSDL file, and
an MSL file. The current incarnation uses an .edmx file instead. The .edmx file is an XML file
that defines each of the elements that these previous three files contained (a conceptual
model, a storage model, and a mapping model). In addition to containing the necessary
information about each of these three components, it contains additional information that
is used by Visual Studio and the Entity Designer to facilitate design time support of the
model.

As a mnemonic cue, think of the following. The EF is an ORM. “Map” begins with “M,” so
it is easy to remember that the MSL (mapping specification language) is the last part of the
156

CHAPTER 2

Querying and manipulating data by using the Entity Framework