Entity Framework-Full
Entity Framework-Full
Applications can work in terms of a more application-centric conceptual model, including types with
Applications are freed from hard-coded dependencies on a particular data engine or storage schema.
Mappings between the conceptual model and the storage-specific schema can change without changing
Developers can work with a consistent application object model that can be mapped to various storage
Language-integrated query support provides compile-time syntax validation for queries against a
conceptual model.
In This Section
The Entity Framework enables developers to work with data in the form of domain-specific objects and properties,
such as customers and customer addresses, without having to concern themselves with the underlying database
tables and columns where this data is stored. This is enabled by elevating the level of abstraction at which
developers can work when they deal with data and reducing the code that is required to create and maintain data-
oriented applications. Because the Entity Framework is a component of the .NET Framework, Entity Framework
applications can run on any computer on which the .NET Framework 3.5 Service Pack 1 (SP1) is installed.
A longstanding and common design pattern for data modeling is the division of the data model into three parts: a
conceptual model, a logical model, and a physical model. The conceptual model defines the entities and
relationships in the system that is being modeled. The logical model for a relational database normalizes the
entities and relationships into tables with foreign key constraints. The physical model addresses the capabilities of
a particular data engine by specifying storage details such as partitioning and indexing.
The physical model is refined by database administrators to improve performance, but programmers writing
application code primarily confine themselves to working with the logical model by writing SQL queries and calling
stored procedures. Conceptual models are generally used as a tool for capturing and communicating the
requirements of an application, frequently as inert diagrams that are viewed and discussed in the early stages of a
project and then abandoned. Many development teams skip creating a conceptual model and begin by specifying
tables, columns, and keys in a relational database.
The Entity Framework gives life to conceptual models by enabling developers to query entities and relationships in
the conceptual model while relying on the Entity Framework to translate those operations to data source-specific
commands. This frees applications from hard-coded dependencies on a particular data source. The conceptual
model, the storage model, and the mapping between the two are expressed in an external specification, known as
the Entity Data Model (EDM).The storage model and mappings can change as needed without requiring changes to
the conceptual model, data classes, or application code. Because storage models are provider-specific, you can
work with a consistent conceptual model across various data sources.
An EDM is defined by the following three model and mapping files that have corresponding file name extensions:
Conceptual schema definition language file (.csdl) - defines the conceptual model.
Store schema definition language file (.ssdl) - defines the storage model, which is also called the logical
model.
Mapping specification language file (.msl) - defines the mapping between the storage and conceptual
models.
The Entity Framework uses these XML-based model and mapping files to transform create, read, update, and
delete operations against entities and relationships in the conceptual model to equivalent operations in the data
source. The EDM even supports mapping entities in the conceptual model to stored procedures in the data source.
For more information, see Data Modeling in the Entity Framework.
Existing solutions have tried to bridge this gap, which is frequently called an "impedance mismatch", by only
mapping object-oriented classes and properties to relational tables and columns. Instead of taking this traditional
approach, the Entity Framework maps relational tables, columns, and foreign key constraints in logical models to
entities and relationships in conceptual models. This enables greater flexibility both in defining objects and
optimizing the logical model. The Entity Data Model tools generate extensible data classes based on the conceptual
model. These classes are partial classes that can be extended with additional members that the developer adds.
The classes that are generated for a particular conceptual model derive from base classes that provide Object
Services for materializing entities as objects and for tracking and saving changes. Developers can use these classes
to work with the entities and relationships as objects related by navigation properties. For more information about
Object Services, see Object Services Overview (Entity Framework).
More than just another object-relational mapping solution, the Entity Framework is fundamentally about enabling
applications to access and change data that is represented as entities and relationships in the conceptual model.
Object Services uses the EDM to translate object queries against entity types that are represented in the
conceptual model into data source-specific queries. Query results are materialized into objects that Object Services
manages. The Entity Framework provides the following ways to query an EDM and return objects:
LINQ to Entities - provides Language-Integrated Query (LINQ) support for querying entity types that are
defined in a conceptual model. For more information, see LINQ to Entities Overview.
Entity SQL - a storage-independent dialect of SQL that works directly with entities in the conceptual model
and that supports EDM features such as inheritance and relationships. Entity SQL is used both with object
queries and queries that are executed by using the EntityClient provider. For more information, see Entity
SQL Overview.
Query builder methods - enables you to construct Entity SQL queries using LINQ-style query methods. For
The Entity Framework includes the EntityClient data provider. This provider manages connections, translates entity
queries into data source-specific queries, and returns a data reader that Object Services uses to materialize entity
data into objects. When object materialization is not required, the EntityClient provider can also be used like a
standard ADO.NET data provider by enabling applications to execute Entity SQL queries and consume the returned
read-only data reader. For more information, see EntityClient Provider for the Entity Framework.
The following diagram illustrates the Entity Framework architecture for accessing data:
The Entity Framework generates a class derived from ObjectContext that represents the entity container in the
conceptual model. This object context provides the facilities for tracking changes and managing identities,
concurrency, and relationships. This class also exposes a SaveChanges method that writes inserts, updates, and
deletes to the data source. Like queries, these changes are either made by commands automatically generated by
the system or by stored procedures that are specified by the developer. For more information, see Adding,
Modifying, and Deleting Objects (Entity Framework).
Together with the Entity Framework runtime, the .NET Framework 3.5 SP1 includes EDM Generator (EdmGen.exe).
This command prompt utility connects to a data source and generates an EDM based on a one-to-one mapping
between entities and tables. It also uses a conceptual model file (.csdl) to generate an object layer file that
contains classes that represent entity types and the ObjectContext. For more information, see EDM Generator
(EdmGen.exe).
Visual Studio 2008 includes rich tool support for generating and maintaining an EDM in a Visual Studio application.
The Entity Data Model Designer supports creating advanced mapping scenarios, such as table-per-type and table-
per-hierarchy inheritance and split entities that map to multiple tables. For more information, see ADO.NET Entity
Data Model Designer Overview.
Learning More
The following topics enable you to learn more about the Entity Framework:
Getting Started (Entity Framework)
Provide information about how to get up and running quickly using the Quickstart (Entity Framework),
which shows how to create a simple Entity Framework application.
Shows you how to use the Entity Data Model tools with Visual Studio 2008 to quickly create your first
Entity Framework application.
Provides task-based links to topics that match specific application scenarios, such as writing queries, binding
objects to data controls, or implementing business logic.
In This Section
Links to topics that describe how to create an EDM, generate an EDM by using tools, define an EDM for
custom objects, and find the sample models discussed in the documentation.
Links to topics that describe how to write object queries, LINQ queries, and Entity SQL.
Links to topics that describe working with objects, transactions, and stored procedure support.
Links to topics that describe how to use stored procedures with an EDM.
Links to topics that describe how to implement your own business logic into an Entity Framework
application.
Describes the mapping scenarios that are supported by the Entity Framework.
The following Entity Data Model (EDM) mapping scenarios are currently supported by the Entity Framework.
Simple mapping In this mapping scenario, each entity in the conceptual model is mapped to a
single table in the storage model. This is the default mapping generated by
Entity Data Model tools. For more information, see the Quickstart (Entity
Framework).
Entity splitting In this mapping scenario, properties from a single entity in the conceptual model
are mapped to columns in two or more underlying tables. In this scenario, the
tables must share a common primary key. For more information, see How to:
Define a Model with Single Entity Mapped to Two Tables.
Horizontal In this mapping scenario, a single entity type in the conceptual model is mapped
partitioning in the to two or more tables with the same schema. The entity is mapped into the
storage model tables based on a condition defined in the mapping specification. For more
information, see How to: Define a Model with Horizontal Partition in Storage
Model. For more information on condition mapping, see Condition Element
(MappingFragment).
Horizontal In this mapping scenario, multiple entity types in the conceptual model that
partitioning in the have the same properties are mapped to a single table. A condition clause is
conceptual model used to specify which data in the table belongs to which entity type. This
mapping is similar to table-per-hierarchy inheritance mapping. For more
information, see How to: Define a Model with Table-per-Hierarchy Inheritance.
Table-per-hierarchy In this mapping scenario, all types in an inheritance hierarchy are mapped to a
inheritance single table. A condition clause is used to define the entity types. For more
information, see How to: Define a Model with Table-per-Hierarchy Inheritance
(Entity Framework).
Table-per-type In this mapping scenario, all types are all mapped to individual tables.
inheritance Properties that belong solely to a base type or derived type are stored in a table
that maps to that type. For more information, see How to: Define a Model with
Table-per-Type Inheritance (Entity Framework).
Table-per-concrete- In this mapping scenario, non-abstract types are each mapped to an individual
type inheritance table. Each of these tables must have columns that map to all of the properties
of the derived type, including the properties inherited from the base type.
Multiple entity sets In this mapping scenario, a single entity type is expressed in two or more
per type separate entity sets in the conceptual model. Each entity set is mapped to a
separate table in the storage model. For more information, see How to: Define a
Model with Multiple Entity Sets per Type (Entity Framework).
Complex types A complex type is a non-scalar property of an entity type that does not have a
key property. A complex type can contain other nested complex types. Complex
types are mapped to tables in the storage model. For more information, see
How to: Define a Model with Complex Type (Entity Framework).
Function import In this scenario, a stored procedure in the storage model is mapped to a
mapping FunctionImport element in the conceptual model. This function is executed to
return entity data using the mapped stored procedure. For more information,
see How to: Define a Model with a Stored Procedure (Entity Framework).
Modification In this scenario, stored procedures are defined in the storage model that insert,
function mapping update, and delete data. These functions are defined for an entity type to
provide the update functionality for a specific entity type. For more information,
see Stored Procedure Support (Entity Framework).
Defining query In this scenario, a query is defined in the storage model that represents a table
mapping in the data source. The query is expressed in the native query language of the
data source, such as Transact-SQL, when mapping to a SQL Server database.
This DefiningQuery element is mapped to an entity type in the conceptual
model. The query is defined in the store-specific query language. For more
information, see DefiningQuery Element (EntityContainer SSDL). When you use
a defining query, updates cannot be persisted to the data source using the
standard update process. Updates can be made by defining modification function
mappings. For more information, see Stored Procedure Support (Entity
Framework).
Query view mapping In this scenario, a read-only mapping is defined between entity types in the
conceptual model and relational tables in the storage model. This mapping is
defined based on an Entity SQL query against the storage model that returns
entities in the conceptual model. For more information, see QueryView Element
(EntitySetMapping). When you use a query view, updates cannot be persisted to
the data source using the standard update process. Updates can be made by
defining modification function mappings. For more information, see Stored
Procedure Support (Entity Framework).
For information about the mapping scenarios that are supported by Entity Data Model tools, see ADO.NET Entity
Data Model Designer Overview.
Describes considerations for creating Web services or Windows Communication Foundation (WCF) services that use
the Entity Framework.
ADO.NET Data Services also enables you to provide dynamic access to EDM data in an XML format that can be
used by applications. This entity data is accessed by using standard Representational State Transfer (REST) HTTP
actions, such as GET, PUT, and POST. For more information, see ADO.NET Data Services Framework.
The following should be considered when creating Web services or WCF services that use the Entity Framework:
Full-graph serialization is supported for binary serialization and DataContract serialization. XML
Objects are always deserialized in the Detached state. You may need to attach or add the object to an
ObjectContext, or you may just want to apply property changes to the original object. For more
information, see Attaching Objects (Entity Framework).
Stateless services are recommended. Services should be designed such that an object context is only
maintained for the duration of a request or a response. The message exchange pattern should include
enough information so that changes can be applied without having to persist objects or re-query the data
source to retrieve the original object. For example, a service that allows a client to update objects should
require that the updated object be returned along with the original object. This enables changes to be
applied to the original object by the Web service using the ApplyPropertyChanges method without having
to retrieve the original object from the database or persist it in memory. For more information, see How
to: Apply Changes Made to a Detached Object (Entity Framework).
Provides more detailed information on the features that compose the Entity Framework and links to topics
that discuss those features.
Defines many of the terms that are introduced by the EDM and the Entity Framework and that are used in
Entity Framework documentation.
Provides links to conceptual topics and links to external topics and resources for building Entity Framework
applications.
The Entity Framework supports an Entity Data Model (EDM) for defining data at both the storage and conceptual
level and a mapping between the two. It also enables developers to program directly against the data types
defined at the conceptual level as common language runtime (CLR) objects. The Entity Framework provides tools
to generate an EDM and the related CLR objects based on an existing database. This reduces much of the data
access code that used to be required to create object-based data application and services, and makes it faster to
create object-oriented data applications and services from an existing database.
The topics in this section are designed to help you understand using the Entity Framework quickly by explaining the
underlying technologies in the context of the Quickstart (Entity Framework) tutorial.
In This Section
To meet the needs of developers who want to derive an Entity Data Model from an existing database, the Entity
Framework provides a set of tools that generate an EDM, validate an EDM, and create programmable classes based
on the conceptual model. The EDM Generator (EdmGen.exe) command prompt utility enables you to generate a
simple model with a one-to-one mapping between entities and tables in a data source. You can also use
EdmGen.exe to generate the data classes that are based on entity types and to validate an EDM. EdmGen.exe is
part of the Entity Framework runtime components in the .NET Framework 3.5 Service Pack 1(SP1).
Visual Studio 2008 SP1 includes an integrated set of Entity Data Model tools that generates a model that includes
selected objects from a data source. You can then modify the conceptual model and mapping using the Entity Data
Model Designer to achieve the conceptual model that is required by the application. For more information, see
Entity Data Model Tools.
Considerations
All entities are required to have keys. If the database has a table without a primary key, the EDM tools try
to infer a key for the corresponding entity. In addition, the EDM tools generate a DefiningQuery element in
the store schema that makes the data for this entity read-only. To make the entity data updatable, you
must verify that the generated key is a valid key and then remove the DefiningQuery element.
A table that represents a many-to-many relationship between two tables in the database may not have an
equivalent entity in the conceptual schema. When the EDM tools encounter such a table with no columns
other than the two that are foreign keys, the mapping table is represented in the conceptual schema as a
many-to-many association instead of an entity. The CourseInstructor association in the School model is
an example of this behavior. For more information, see Generating the School Entity Data Model (Entity
Framework Quickstart).
In this release, the Entity Data Model tools only support automatic generation of an EDM based on an
existing data source. You cannot automatically generate a data source, such as a relational database,
based on the conceptual model.
The topics in this Getting Started section refer to a sample database named School. See Creating the School
Sample Database (Entity Framework Quickstart) for the script that generates the School database on SQL Server.
Course
CourseGrade
CourseInstructor
Department
OfficeAssignment
OnlineCourse
OnsiteCourse
Person
This example database highlights many of the complex modeling scenarios supported by the Entity Data Model
tools. The script creates the relationships between the tables and inserts sample data so that you can run the
samples to see how they work. The following shows the School EDM displayed in the ADO.NET Entity Data Model
Designer:
Note
All the mapping file fragments that are shown in this section are generated by the EDM Generator
(EdmGen.exe) tool.
The conceptual model is an Entity Data Model (EDM) schema that defines the entities and associations in the EDM.
The XML syntax that defines this model is called the conceptual schema definition language (CSDL). Entity types
defined in CSDL each have a name, a key for uniquely identifying instances, and a set of properties. The data types
assigned to properties are specified as either simple types, which are scalar properties, or as complex types, which
are types that consist of one or more scalar or complex properties. Additional properties may also specify nullability
or assign a default value. Associations define the relationships between entities. Entity Framework language
elements and terminology are explained in more detail in Entity Framework Terminology.
The following XML fragment represents part of the conceptual model for the School EDM that defines the Course
and Department entity types that are related by the FK_Course_Department association, with other entities
and associations removed.
Copy Code
A separate data model uses store schema definition language (SSDL) to describe the logical model for persistent
data, usually stored in a relational database. The data types of properties declared in SSDL files are those of the
storage model. This storage model fragment shows an example of storage metadata for the Course and
Department tables in the School database that are related by the FK_Course_Department foreign key, with
other entities removed.
Copy Code
A mapping specification uses mapping specification language (MSL) to connect the types declared in the conceptual
model to the database metadata declared in the storage model. This MSL fragment demonstrates a one-to-one
mapping between the conceptual and storage models for the Course and Department entities in the School
model.
Copy Code
The School model that is discussed here uses a simple one-to-one mapping between a conceptual entity and a
database table but the Entity Framework supports more complex mappings. For example, the relational database
might use more than one table to store data related to each employee. One table could contain contact information
for all people and a separate related table could contain information that pertains only to employees. The Entity
Framework enables developers to define entities using inheritance hierarchies and to map one entity to data from
more than one table in a database, with full support for data updates, inserts, and deletes. For more information,
see Data Modeling in the Entity Framework.
The Entity Framework builds on top of storage-specific ADO.NET data providers by providing an EntityConnection to
an underlying data provider and relational database.
When a query is executed, it is parsed and converted into a canonical command tree, which is an object model
representation of the query. Canonical command trees represent select, update, insert, and delete commands. All
subsequent processing is performed on the command tree, which is the means of communication between the
System.Data.EntityClient provider and the underlying .NET Framework data provider, such as
System.Data.SqlClient.
The following diagram illustrates the Entity Framework architecture for accessing data:
Querying Objects
The Entity Framework tools generate a class derived from ObjectContext that represents the entity container
defined in the conceptual model. The ObjectContext class supports queries against an EDM that return entities as
objects, as well as creating, updating, and deleting entity objects. The Entity Framework supports object queries
against an EDM. Queries can be composed using Entity SQL, Language-Integrated Query (LINQ), and object query
builder methods.
In a conceptual model, entities are related to each other by associations. In the object layer, these associations are
represented by properties that expose collections of related objects based on an entity reference. For example, in
the School model, Department.Course gets an entity collection of Course objects based on the association
between Course and Department. Because referenced objects are not automatically loaded, you must call the
Load method on the entity reference to load the related object data into the object context. You can also specify a
query path that defines which related objects to load with returned objects. For more information, see Querying
Data as Objects (Entity Framework).
The following example from the quickstart shows a query that, when executed, retrieves all Department objects.
A query path definition ensures that the Course objects related to Department objects are also returned. An
Entity SQL WHERE clause orders the returned objects by Name.
Visual Basic
Copy Code
' Define a query that returns all Department objects and related
' Course objects, ordered by name.
Dim departmentQuery As ObjectQuery(Of Department) = _
schoolContext.Department.Include("Course").OrderBy("it.Name")
C#
Copy Code
You can define an EDM that uses stored procedures to execute queries at the data source. The result sets from
these stored procedures are mapped to entities in the conceptual model. For more information, see Stored
Procedure Support (Entity Framework).
An object in an object context is an entity type representation of data in the data source. You can modify, create,
and delete objects in an object context. The object context manages identities and relationships between objects.
You can also serialize objects and bind objects to controls. For more information, see Working with Objects (Entity
Framework).
The following example from the quickstart gets a collection of Course objects related to a Department object and
binds the collection to a DataGridView control.
Visual Basic
Copy Code
Visual Basic
Copy Code
You can define an EDM that uses stored procedures to insert, update, and delete data at the data source. These
stored procedures are mapped to entities in the conceptual model. For more information, see Stored Procedure
Support (Entity Framework).
In This Section
Application Scenarios
More…
Describes how to perform common Entity Framework tasks, including the following. For a complete list of
categories and tasks, click the "More..." link.
How to: Add, Modify, and Delete Objects (Entity Framework)
Example
In this example, an object query returns a single SalesOrderHeader object based on a specified SalesOrderID.
The status for this order is changed from 5 (shipped) to 1 (in process), a new item is added to the order, and the
first existing item is deleted. The SaveChanges method is called to write changes to the database. The resulting
state of the order is then written to the console.
Visual Basic
Copy Code
The example in this topic is based on the Adventure Works Sales Model. To run the code in this example, you must
have already added the AdventureWorks Sales Model to your project and configured your project to use the Entity
Framework. To do this, complete the procedures in How to: Manually Configure an Entity Framework Project and
How to: Manually Define an Entity Data Model (Entity Framework).
Example
The following example is from a Windows Form. When the form is loaded, an ObjectResult of SalesOrderHeader
objects is returned by calling the Execute method of the ObjectQuery. This result is bound to a combo box. When
an order is selected, the related EntityCollection of SalesOrderDetail objects is bound to a DataGridView
control.
Visual Basic
Copy Code
Imports System
Imports System.Collections.Generic
Imports System.Collections
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Linq
Imports System.Text
Imports System.Windows.Forms
Imports System.Data.Objects
Imports System.Data.Objects.DataClasses
Imports AdventureWorksModel
Catch ex As EntitySqlException
MessageBox.Show(ex.Message)
End Try
End Sub
Private Sub ordersListBox_SelectedIndexChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles ordersListBox.SelectedIndexChanged
' Get the currently selected SalesOrderHeader object.
Dim order As SalesOrderHeader = CType(Me.ordersListBox.SelectedItem, _
SalesOrderHeader)
Try
' Save changes in the object context.
context.SaveChanges(True)
Catch ex As OptimisticConcurrencyException
' Resolve the concurrently conflict by refreshing the
' object context before saving changes.
context.Refresh(RefreshMode.ClientWins, order.SalesOrderDetail)
using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using AdventureWorksModel;
namespace Microsoft.Samples.Edm
{
public partial class Main : Form
{
private AdventureWorksEntities context;
private int customerId = 277;
public Main()
{
// Initializes the designer-generated controls.
InitializeComponent();
}
How to: Execute a Query that Returns an Entity Type (Entity Framework)
LINQ to Entities
The examples in this topic are based on the Adventure Works Sales Model. To run the code in this example, you
must have already added the AdventureWorks Sales Model to your project and configured your project to use the
Entity Framework. To do this, complete the procedures in How to: Manually Configure an Entity Framework Project
and How to: Manually Define an Entity Data Model (Entity Framework). You can also use the Entity Data Model
Wizard to define the AdventureWorks Sales Model. For more information, see How to: Use the Entity Data Model
Wizard (Entity Framework).
Example
Dim productsQuery = _
From product In products _
Select product
Console.WriteLine("Product Names:")
For Each product In productsQuery
Console.WriteLine(product.Name)
Next
End Using
C#
Copy Code
Console.WriteLine("Product Names:");
foreach (var prod in productsQuery)
{
Console.WriteLine(prod.Name);
}
}
The following is the Entity SQL example.
Visual Basic
Copy Code
ObjectQuery<Product> productQuery =
new ObjectQuery<Product>(queryString, advWorksContext, MergeOption.NoTracking);
Visual Basic
Copy Code
LINQ to Entities
The example in this topic is based on the Adventure Works Sales Model. To run the code in this example, you must
have already added the AdventureWorks Sales Model to your project and configured your project to use the Entity
Framework. To do this, complete the procedures in How to: Manually Configure an Entity Framework Project and
How to: Manually Define an Entity Data Model (Entity Framework). You can also use the Entity Data Model Wizard
to define the AdventureWorks Sales Model. For more information, see How to: Use the Entity Data Model Wizard
(Entity Framework).
Example
Visual Basic
Copy Code
Try
' Execute the query and display information for each item
' in the orders that belong to the contact.
For Each order As SalesOrderHeader In contacts.SalesOrderHeader
Console.WriteLine(String.Format("PO Number: {0}", _
order.PurchaseOrderNumber))
Console.WriteLine(String.Format("Order Date: {0}", _
order.OrderDate.ToString()))
Console.WriteLine("Order items:")
For Each item As SalesOrderDetail In order.SalesOrderDetail
Console.WriteLine(String.Format("Product:{0}" _
+ "Quantity: {1}", item.ProductID.ToString(), _
item.OrderQty.ToString()))
Next
Next
Catch ex As EntitySqlException
Console.WriteLine(ex.ToString())
Catch ex As EntityCommandExecutionException
Console.WriteLine(ex.ToString())
End Try
End Using
C#
Copy Code
try
{
// Execute the query and display information for each item
// in the orders that belong to the contact.
foreach (SalesOrderHeader order in contacts
.SalesOrderHeader)
{
Console.WriteLine(String.Format("PO Number: {0}",
order.PurchaseOrderNumber));
Console.WriteLine(String.Format("Order Date: {0}",
order.OrderDate.ToString()));
Console.WriteLine("Order items:");
foreach (SalesOrderDetail item in order.SalesOrderDetail)
{
Console.WriteLine(String.Format("Product: {0} "
+ "Quantity: {1}", item.ProductID.ToString(),
item.OrderQty.ToString()));
}
}
}
catch (EntitySqlException ex)
{
Console.WriteLine(ex.ToString());
}
catch (EntityCommandExecutionException ex)
{
Console.WriteLine(ex.ToString());
}
}
This is the Entity SQL example.
Visual Basic
Copy Code
Try
' Execute the query and display information for each item
' in the orders that belong to the first contact.
For Each order As SalesOrderHeader In contact.SalesOrderHeader
Console.WriteLine(String.Format("PO Number: {0}", _
order.PurchaseOrderNumber))
Console.WriteLine(String.Format("Order Date: {0}", _
order.OrderDate.ToString()))
Console.WriteLine("Order items:")
For Each item As SalesOrderDetail In order.SalesOrderDetail
Console.WriteLine(String.Format("Product:{0}" _
+ "Quantity: {1}", item.ProductID.ToString(), _
item.OrderQty.ToString()))
Next
Next
Catch ex As EntitySqlException
Console.WriteLine(ex.ToString())
Catch ex As EntityCommandExecutionException
Console.WriteLine(ex.ToString())
End Try
End Using
C#
Copy Code
Contact contact =
contactQuery.Include("SalesOrderHeader.SalesOrderDetail")
.FirstOrDefault();
try
{
// Execute the query and display information for each item
// in the orders that belong to the first contact.
foreach (SalesOrderHeader order in contact
.SalesOrderHeader)
{
Console.WriteLine(String.Format("PO Number: {0}",
order.PurchaseOrderNumber));
Console.WriteLine(String.Format("Order Date: {0}",
order.OrderDate.ToString()));
Console.WriteLine("Order items:");
foreach (SalesOrderDetail item in order.SalesOrderDetail)
{
Console.WriteLine(String.Format("Product: {0} "
+ "Quantity: {1}", item.ProductID.ToString(),
item.OrderQty.ToString()));
}
}
}
catch (EntitySqlException ex)
{
Console.WriteLine(ex.ToString());
}
catch (EntityCommandExecutionException ex)
{
Console.WriteLine(ex.ToString());
}
}
This is the query builder method example.
Visual Basic
Copy Code
In This Section
How to: Customize an Entity Data Model to Work with Custom Objects (Entity Framework)
To run the example in this topic, you must have already used the EDM Generator (EdmGen.exe) utility or the Entity
Data Model Wizard to generate the EDM mapping files. For more information, see How to: Use EdmGen.exe to
Generate an Entity Data Model (Entity Framework). If you are using the Entity Data Model Designer in Visual
Studio, you must also disable object layer generation based on the updated CSDL file. Otherwise, you will have
duplicate data classes in your project.
2. Rename the EntityType and EntitySet elements to reflect the names of the custom data classes.
3. Remove the EntityType and EntitySet elements for any entity that does not have a corresponding custom
data class.
4. Rename the Property elements of each type to match the name of the properties in the custom data class.
5. Remove the Property elements for any properties that do not exist in the custom data class.
To update the MSL file to map custom data objects to objects in the data source
2. Rename the EntitySetMapping element and the TypeName attribute to reflect the names of the custom
classes.
3. Remove the EntitySetMapping element for any entity that does not have a corresponding custom data class.
4. Rename the ScalarProperty elements of each type to match the names of the properties in the custom data
class.
5. Remove the ScalarProperty element for any properties that do not exist in the custom data class.
6. Rename the EndProperty element in the AssociationSetMapping to reflect the names of the custom
classes.
7. Rename the ScalarProperty elements in each AssociationSetMapping to match the names of the
properties in the custom data class.
Note
8. Remove the AssociationSetMapping element for associations between any entities that do not exist in the
custom data classes.
2. Remove the EntityType elements for any entities that are not mapped to custom data classes.
3. Remove the ScalarProperty elements for any properties that are not mapped to properties of the custom
data classes.
1. Run the EdmGen.exe utility in the directory that contains the mapping files. Use the following command:
Copy Code
%windir%\Microsoft.NET\Framework\v3.5\edmgen.exe /mode:ValidateArtifacts
/inssdl:.\YourModel.ssdl /inmsl:.\YourModel.msl /incsdl:.\YourModel.csdl
Note
Remove line breaks and replace YourModel with the name used for your mapping files.
1. In the Solution Explorer in Visual Studio, right-click the CSDL file and select Run Custom Tool.
This regenerates the object layer based on the modified CSDL file.
2. Expand the CSDL file node, open the designer file, and save the file as a different file name.
This saves the autogenerated object layer file. Code from this file is used in the topic How to: Use Object
Services with Custom Objects (Entity Framework).
4. Select the CSDL file and clear the Custom Tool value in the Properties window.
This will stop the object layer file from being regenerated. To generate this file in the future, type
EntityModelCodeGenerator for Custom Tool in the Properties window and repeat step 1.
Example
The following CSDL file has been customized to support the Orders and LineItem custom data classes.
Copy Code
Copy Code
Copy Code
1. Add the following using statements (Imports in Visual Basic) to the code page:
Visual Basic
Copy Code
Imports System.Data
Imports System.Data.Objects.DataClasses
Imports System.Data.Metadata.Edm
Imports Microsoft.Samples.Edm
C#
Copy Code
using System.Data;
using System.Data.Objects.DataClasses;
using System.Data.Metadata.Edm;
using Microsoft.Samples.Edm;
2. Insert EdmSchemaAttribute just above the namespace declaration.
3. Add one instance of EdmRelationshipAttribute for each association. This attribute specifies the name and
namespace of the association, the names of the roles in the association, the types in the association, and the
multiplicity at each end of the association, such as one-to-one or one-to-many. Do this just above the
namespace declaration.
5. Add EdmScalarPropertyAttribute to the property of each class that represents the entity key, which is used to
uniquely identify objects. Specify a value of true for the EntityKeyProperty property of this attribute.
6. Add EdmScalarPropertyAttribute to the remaining properties. If the property does not accept null values,
specify a value of false for the IsNullable property on this attribute.
Example
This example shows EDM attributes applied to Order and LineItem classes. These custom classes are mapped to
the SalesOrderHeader and SalesOrderDetail tables in the AdventureWorks database. Both classes inherit from
EntityObject.
Visual Basic
Copy Code
Option Explicit On
Option Strict On
Imports System
Imports System.Data.SqlTypes
Imports System.Collections.Generic
Imports System.Text
Imports System.Data
Imports System.Data.Objects.DataClasses
Imports System.Data.Metadata.Edm
Imports Microsoft.Samples.Edm
<Assembly: EdmSchemaAttribute()>
<Assembly: EdmRelationshipAttribute("Microsoft.Samples.Edm", _
"FK_LineItem_Order_OrderId", "Order", _
RelationshipMultiplicity.One, GetType(Order), "LineItem", _
RelationshipMultiplicity.Many, GetType(LineItem))>
Namespace Microsoft.Samples.Edm
<EdmEntityTypeAttribute(NamespaceName:="Microsoft.Samples.Edm", Name:="Order")> _
Public Class Order
Inherits EntityObject
' Define private property variables.
Private _orderId As Integer
Private _orderDate As DateTime
Private _dueDate As DateTime
Private _shipDate As DateTime
Private _status As Byte
Private _customer As Integer
Private _subTotal As Decimal
Private _tax As Decimal
Private _freight As Decimal
Private _totalDue As Decimal
Private _extendedInfo As OrderInfo
'Default Constructor.
Sub New()
End Sub
' Public properties of the Order object.
<EdmScalarPropertyAttribute(EntityKeyProperty:=True, IsNullable:=False)> _
Public Property OrderId() As Integer
Get
Return _orderId
End Get
Set(ByVal value As Integer)
ReportPropertyChanging("OrderId")
_orderId = value
ReportPropertyChanged("OrderId")
End Set
End Property
' Navigation property that returns a collection of line items.
<EdmRelationshipNavigationPropertyAttribute("Microsoft.Samples.Edm", _
"FK_LineItem_Order_OrderId", "LineItem")> _
Public ReadOnly Property LineItem() As EntityCollection(Of LineItem)
Get
Return CType(Me, IEntityWithRelationships).RelationshipManager _
.GetRelatedCollection(Of LineItem) _
("FK_LineItem_Order_OrderId", "LineItem")
End Get
End Property
<EdmScalarPropertyAttribute(IsNullable:=False)> _
Public Property OrderDate() As Date
Get
Return _orderDate
End Get
Set(ByVal value As DateTime)
ReportPropertyChanging("OrderDate")
_orderDate = value
ReportPropertyChanged("OrderDate")
End Set
End Property
<EdmScalarPropertyAttribute(IsNullable:=False)> _
Public Property DueDate() As Date
Get
Return _dueDate
End Get
Set(ByVal value As Date)
ReportPropertyChanging("DueDate")
_dueDate = value
ReportPropertyChanged("DueDate")
End Set
End Property
<EdmScalarPropertyAttribute()> _
Public Property ShipDate() As Date
Get
Return _shipDate
End Get
Set(ByVal value As Date)
ReportPropertyChanging("ShipDate")
_shipDate = value
ReportPropertyChanged("ShipDate")
End Set
End Property
<EdmScalarPropertyAttribute(IsNullable:=False)> _
Public Property Status() As Byte
Get
Return _status
End Get
Set(ByVal value As Byte)
If _status <> value Then
ReportPropertyChanging("Status")
_status = value
ReportPropertyChanged("Status")
End If
End Set
End Property
<EdmScalarPropertyAttribute(IsNullable:=False)> _
Public Property Customer() As Integer
Get
Return _customer
End Get
Set(ByVal value As Integer)
ReportPropertyChanging("Customer")
_customer = value
ReportPropertyChanged("Customer")
End Set
End Property
<EdmScalarPropertyAttribute(IsNullable:=False)> _
Public Property SubTotal() As Decimal
Get
Return _subTotal
End Get
Set(ByVal value As Decimal)
If _subTotal <> value Then
' Validate the value before setting it.
If value < 0 Then
Throw New ApplicationException(String.Format( _
My.Resources.propertyNotValidNegative, _
value.ToString, "SubTotal"))
End If
ReportPropertyChanging("SubTotal")
_subTotal = value
ReportPropertyChanged("SubTotal")
End Sub
' Defines a navigation property to the Order class.
<EdmRelationshipNavigationPropertyAttribute("Microsoft.Samples.Edm", _
"FK_LineItem_Order_OrderId", "Order")> _
Public Property Order() As Order
Get
Return CType(Me, _
IEntityWithRelationships).RelationshipManager _
.GetRelatedReference(Of Order) _
("FK_LineItem_Order_OrderId", "Order").Value
End Get
Set(ByVal value As Order)
CType(Me, _
IEntityWithRelationships).RelationshipManager _
.GetRelatedReference(Of Order) _
("FK_LineItem_Order_OrderId", "Order").Value = value
End Set
End Property
<EdmScalarPropertyAttribute(EntityKeyProperty:=True, IsNullable:=False)> _
Public Property LineItemId() As Integer
Get
Return _lineItemId
End Get
Set(ByVal value As Integer)
ReportPropertyChanging("LineItemId")
_lineItemId = value
ReportPropertyChanged("LineItemId")
End Set
End Property
<EdmScalarPropertyAttribute()> _
Public Property TrackingNumber() As String
Get
Return _trackingNumber
End Get
Set(ByVal value As String)
If _trackingNumber <> value Then
' Validate the value before setting it.
If value.Length > 25 Then
Throw New ApplicationException(String.Format( _
My.Resources.propertyNotValidString, _
"TrackingNumber", "25"))
End If
ReportPropertyChanging("TrackingNumber")
_trackingNumber = value
ReportPropertyChanged("TrackingNumber")
End If
End Set
End Property
<EdmScalarPropertyAttribute(IsNullable:=False)> _
Public Property Quantity() As Short
Get
Return _quantity
End Get
Set(ByVal value As Short)
If _quantity <> value Then
' Validate the value before setting it.
If value < 1 Then
Throw New ApplicationException(String.Format( _
My.Resources.propertyNotValidNegative, _
value.ToString(), "Quantity"))
End If
ReportPropertyChanging("Quantity")
_quantity = value
ReportPropertyChanged("Quantity")
[assembly: EdmSchemaAttribute()]
[assembly: EdmRelationshipAttribute("Microsoft.Samples.Edm",
"FK_LineItem_Order_OrderId", "Order",
RelationshipMultiplicity.One, typeof(Order),"LineItem",
RelationshipMultiplicity.Many, typeof(LineItem))]
namespace Microsoft.Samples.Edm
{
[EdmEntityTypeAttribute(NamespaceName="Microsoft.Samples.Edm",Name="Order")]
public class Order : EntityObject
{
// Define private property variables.
private int _orderId;
private DateTime _orderDate;
private DateTime _dueDate;
private DateTime _shipDate;
private byte _status;
private int _customer;
private decimal _subTotal;
private decimal _tax;
private decimal _freight;
private decimal _totalDue;
private OrderInfo _ExtendedInfo;
}
}
[EdmScalarPropertyAttribute(IsNullable = false)]
public byte Status
{
get
{
return _status;
}
set
{
if (_status != value)
{
ReportPropertyChanging("Status");
_status = value;
ReportPropertyChanged("Status");
}
}
}
[EdmScalarPropertyAttribute(IsNullable = false)]
public int Customer
{
get
{
return _customer;
}
set
{
ReportPropertyChanging("Customer");
_customer = value;
ReportPropertyChanged("Customer");
}
}
[EdmScalarPropertyAttribute(IsNullable = false)]
public decimal SubTotal
{
get
{
return _subTotal;
}
set
{
if (_subTotal != value)
{
// Validate the value before setting it.
if (value < 0)
{
throw new ApplicationException(string.Format(
Properties.Resources.propertyNotValidNegative,
new string[2] { value.ToString(), "SubTotal" }));
}
ReportPropertyChanging("SubTotal");
_subTotal = value;
ReportPropertyChanged("SubTotal");
ReportPropertyChanging("TaxAmt");
_tax = value;
ReportPropertyChanged("TaxAmt");
ReportPropertyChanging("Freight");
_freight = value;
ReportPropertyChanging("Freight");
// Recalculate the order total.
CalculateOrderTotal();
}
}
}
public decimal TotalDue
{
get
{
return _totalDue;
}
}
[EdmComplexPropertyAttribute()]
public OrderInfo ExtendedInfo
{
get
{
return _ExtendedInfo;
}
set
{
this.ReportPropertyChanging("ExtendedInfo");
_ExtendedInfo = value;
this.ReportPropertyChanged("ExtendedInfo");
}
}
private void CalculateOrderTotal()
{
// Update the total due as a sum of the other cost properties.
_totalDue = _subTotal + _tax + _freight;
}
}
[EdmComplexTypeAttribute(NamespaceName =
"Microsoft.Samples.Edm", Name = "OrderInfo")]
public partial class OrderInfo : ComplexObject
{
private string _orderNumber;
private string _purchaseOrder;
private string _accountNumber;
private string _comment;
[EdmScalarPropertyAttribute(IsNullable = false)]
public string OrderNumber
{
get
{
return _orderNumber;
}
set
{
// Validate the value before setting it.
if (value.Length > 25)
{
throw new ApplicationException(string.Format(
Properties.Resources.propertyNotValidString,
new string[3] { value, "OrderNumber", "25" }));
}
ReportPropertyChanging("OrderNumber");
_orderNumber = value;
ReportPropertyChanged("OrderNumber");
}
}
[EdmScalarPropertyAttribute()]
public string PurchaseOrder
{
get
{
return _purchaseOrder;
}
set
{
// Validate the value before setting it.
if ((value != null) && value.Length > 25)
{
throw new ApplicationException(string.Format(
Properties.Resources.propertyNotValidString,
new string[3] { value, "PurchaseOrder", "25" }));
}
if (_purchaseOrder != value)
{
ReportPropertyChanging("PurchaseOrder");
_purchaseOrder = value;
ReportPropertyChanged("PurchaseOrder");
}
}
}
[EdmScalarPropertyAttribute()]
public string AccountNumber
{
get
{
return _accountNumber;
}
set
{
// Validate the value before setting it.
if ((value != null) && value.Length > 15)
{
throw new ApplicationException(string.Format(
Properties.Resources.propertyNotValidString,
new string[3] { value, "AccountNumber", "15" }));
}
ReportPropertyChanging("AccountNumber");
_accountNumber = value;
ReportPropertyChanged("AccountNumber");
}
}
[EdmScalarPropertyAttribute()]
public string Comment
{
get
{
return _comment;
}
set
{
// Validate the value before setting it.
if ((value != null) && value.Length > 128)
{
throw new ApplicationException(string.Format(
Properties.Resources.propertyNotValidString,
new string[3] { value, "Comment", "128" }));
}
if (_comment != value)
{
ReportPropertyChanging("Comment");
_comment = value;
ReportPropertyChanged("Comment");
}
}
}
}
// Default constructor.
public LineItem()
{
ReportPropertyChanging("Price");
_price = value;
ReportPropertyChanged("Price");
How to: Inherit from the EntityObject and ComplexObject Base Classes (Entity Framework)
Instead of inheriting from EntityObject or ComplexObject, you can also implement custom data class interfaces.
For more information, see Implementing Custom Data Class Interfaces (Entity Framework).
1. Modify the definition of each custom data class so that it inherits from EntityObject, as in the following
example:
Visual Basic
Copy Code
<EdmEntityTypeAttribute(NamespaceName:="Microsoft.Samples.Edm",
Name:="Order")> _
Public Class Order
Inherits EntityObject
C#
Copy Code
[EdmEntityTypeAttribute(NamespaceName="Microsoft.Samples.Edm",Name="Order")
]
public class Order : EntityObject
2. In the settable scalar properties of each data class, add a call to ReportPropertyChanging before you set the
property value, and add a call to ReportPropertyChanged after the property is set. This is shown in the
following example:
Visual Basic
Copy Code
Set(ByVal value As Integer)
ReportPropertyChanging("OrderId")
_orderId = value
ReportPropertyChanged("OrderId")
End Set
C#
Copy Code
set
{
ReportPropertyChanging("OrderId");
_orderId = value;
ReportPropertyChanged("OrderId");
}
1. Modify the definition of each custom complex data class so that it inherits from ComplexObject, as in the
following example:
Visual Basic
Copy Code
<Global.System.Data.Objects.DataClasses.EdmComplexTypeAttribute( _
NamespaceName:="Microsoft.Samples.Edm", Name:="OrderInfo")> _
Partial Public Class OrderInfo
Inherits Global.System.Data.Objects.DataClasses.ComplexObject
C#
Copy Code
[EdmComplexTypeAttribute(NamespaceName =
"Microsoft.Samples.Edm", Name = "OrderInfo")]
public partial class OrderInfo : ComplexObject
2. In the settable scalar properties of each complex data class, add a call to ReportPropertyChanging before you
set the property value, and add a call to ReportPropertyChanged after the property is set. This is shown in the
following example:
Visual Basic
Copy Code
' Validate the value before setting it.
If (value <> Nothing) AndAlso value.Length > 25 Then
Throw New ApplicationException(String.Format( _
My.Resources.propertyNotValidString, _
"PurchaseOrder", "25"))
End If
If _purchaseOrder <> value Then
ReportPropertyChanging("PurchaseOrder")
_purchaseOrder = value
ReportPropertyChanged("PurchaseOrder")
End If
C#
Copy Code
// Validate the value before setting it.
if ((value != null) && value.Length > 25)
{
throw new ApplicationException(string.Format(
Properties.Resources.propertyNotValidString,
new string[3] { value, "PurchaseOrder", "25" }));
}
if (_purchaseOrder != value)
{
ReportPropertyChanging("PurchaseOrder");
_purchaseOrder = value;
ReportPropertyChanged("PurchaseOrder");
}
Example
This example shows the custom data classes Order and LineItem and the complex data class OrderInfo. These
custom classes are mapped to the SalesOrderHeader and SalesOrderDetail tables in the AdventureWorks
database. The Order and LineItem classes inherit from EntityObject, and the complex OrderInfo data class
inherits from ComplexObject.
Visual Basic
Copy Code
Option Explicit On
Option Strict On
Imports System
Imports System.Data.SqlTypes
Imports System.Collections.Generic
Imports System.Text
Imports System.Data
Imports System.Data.Objects.DataClasses
Imports System.Data.Metadata.Edm
Imports Microsoft.Samples.Edm
<Assembly: EdmSchemaAttribute()>
<Assembly: EdmRelationshipAttribute("Microsoft.Samples.Edm", _
"FK_LineItem_Order_OrderId", "Order", _
RelationshipMultiplicity.One, GetType(Order), "LineItem", _
RelationshipMultiplicity.Many, GetType(LineItem))>
Namespace Microsoft.Samples.Edm
<EdmEntityTypeAttribute(NamespaceName:="Microsoft.Samples.Edm", Name:="Order")> _
Public Class Order
Inherits EntityObject
' Define private property variables.
Private _orderId As Integer
Private _orderDate As DateTime
Private _dueDate As DateTime
Private _shipDate As DateTime
Private _status As Byte
Private _customer As Integer
Private _subTotal As Decimal
Private _tax As Decimal
Private _freight As Decimal
Private _totalDue As Decimal
Private _extendedInfo As OrderInfo
'Default Constructor.
Sub New()
End Sub
' Public properties of the Order object.
<EdmScalarPropertyAttribute(EntityKeyProperty:=True, IsNullable:=False)> _
Public Property OrderId() As Integer
Get
Return _orderId
End Get
Set(ByVal value As Integer)
ReportPropertyChanging("OrderId")
_orderId = value
ReportPropertyChanged("OrderId")
End Set
End Property
' Navigation property that returns a collection of line items.
<EdmRelationshipNavigationPropertyAttribute("Microsoft.Samples.Edm", _
"FK_LineItem_Order_OrderId", "LineItem")> _
Public ReadOnly Property LineItem() As EntityCollection(Of LineItem)
Get
Return CType(Me, IEntityWithRelationships).RelationshipManager _
.GetRelatedCollection(Of LineItem) _
("FK_LineItem_Order_OrderId", "LineItem")
End Get
End Property
<EdmScalarPropertyAttribute(IsNullable:=False)> _
Public Property OrderDate() As Date
Get
Return _orderDate
End Get
Set(ByVal value As DateTime)
ReportPropertyChanging("OrderDate")
_orderDate = value
ReportPropertyChanged("OrderDate")
End Set
End Property
<EdmScalarPropertyAttribute(IsNullable:=False)> _
Public Property DueDate() As Date
Get
Return _dueDate
End Get
Set(ByVal value As Date)
ReportPropertyChanging("DueDate")
_dueDate = value
ReportPropertyChanged("DueDate")
End Set
End Property
<EdmScalarPropertyAttribute()> _
Public Property ShipDate() As Date
Get
Return _shipDate
End Get
Set(ByVal value As Date)
ReportPropertyChanging("ShipDate")
_shipDate = value
ReportPropertyChanged("ShipDate")
End Set
End Property
<EdmScalarPropertyAttribute(IsNullable:=False)> _
Public Property Status() As Byte
Get
Return _status
End Get
Set(ByVal value As Byte)
If _status <> value Then
ReportPropertyChanging("Status")
_status = value
ReportPropertyChanged("Status")
End If
End Set
End Property
<EdmScalarPropertyAttribute(IsNullable:=False)> _
Public Property Customer() As Integer
Get
Return _customer
End Get
Set(ByVal value As Integer)
ReportPropertyChanging("Customer")
_customer = value
ReportPropertyChanged("Customer")
End Set
End Property
<EdmScalarPropertyAttribute(IsNullable:=False)> _
Public Property SubTotal() As Decimal
Get
Return _subTotal
End Get
Set(ByVal value As Decimal)
If _subTotal <> value Then
' Validate the value before setting it.
If value < 0 Then
Throw New ApplicationException(String.Format( _
My.Resources.propertyNotValidNegative, _
value.ToString, "SubTotal"))
End If
ReportPropertyChanging("SubTotal")
_subTotal = value
ReportPropertyChanged("SubTotal")
End Sub
' Defines a navigation property to the Order class.
<EdmRelationshipNavigationPropertyAttribute("Microsoft.Samples.Edm", _
"FK_LineItem_Order_OrderId", "Order")> _
Public Property Order() As Order
Get
Return CType(Me, _
IEntityWithRelationships).RelationshipManager _
.GetRelatedReference(Of Order) _
("FK_LineItem_Order_OrderId", "Order").Value
End Get
Set(ByVal value As Order)
CType(Me, _
IEntityWithRelationships).RelationshipManager _
.GetRelatedReference(Of Order) _
("FK_LineItem_Order_OrderId", "Order").Value = value
End Set
End Property
<EdmScalarPropertyAttribute(EntityKeyProperty:=True, IsNullable:=False)> _
Public Property LineItemId() As Integer
Get
Return _lineItemId
End Get
Set(ByVal value As Integer)
ReportPropertyChanging("LineItemId")
_lineItemId = value
ReportPropertyChanged("LineItemId")
End Set
End Property
<EdmScalarPropertyAttribute()> _
Public Property TrackingNumber() As String
Get
Return _trackingNumber
End Get
Set(ByVal value As String)
If _trackingNumber <> value Then
' Validate the value before setting it.
If value.Length > 25 Then
Throw New ApplicationException(String.Format( _
My.Resources.propertyNotValidString, _
"TrackingNumber", "25"))
End If
ReportPropertyChanging("TrackingNumber")
_trackingNumber = value
ReportPropertyChanged("TrackingNumber")
End If
End Set
End Property
<EdmScalarPropertyAttribute(IsNullable:=False)> _
Public Property Quantity() As Short
Get
Return _quantity
End Get
Set(ByVal value As Short)
If _quantity <> value Then
' Validate the value before setting it.
If value < 1 Then
Throw New ApplicationException(String.Format( _
My.Resources.propertyNotValidNegative, _
value.ToString(), "Quantity"))
End If
ReportPropertyChanging("Quantity")
_quantity = value
ReportPropertyChanged("Quantity")
[assembly: EdmSchemaAttribute()]
[assembly: EdmRelationshipAttribute("Microsoft.Samples.Edm",
"FK_LineItem_Order_OrderId", "Order",
RelationshipMultiplicity.One, typeof(Order),"LineItem",
RelationshipMultiplicity.Many, typeof(LineItem))]
namespace Microsoft.Samples.Edm
{
[EdmEntityTypeAttribute(NamespaceName="Microsoft.Samples.Edm",Name="Order")]
public class Order : EntityObject
{
// Define private property variables.
private int _orderId;
private DateTime _orderDate;
private DateTime _dueDate;
private DateTime _shipDate;
private byte _status;
private int _customer;
private decimal _subTotal;
private decimal _tax;
private decimal _freight;
private decimal _totalDue;
private OrderInfo _ExtendedInfo;
}
}
[EdmScalarPropertyAttribute(IsNullable = false)]
public byte Status
{
get
{
return _status;
}
set
{
if (_status != value)
{
ReportPropertyChanging("Status");
_status = value;
ReportPropertyChanged("Status");
}
}
}
[EdmScalarPropertyAttribute(IsNullable = false)]
public int Customer
{
get
{
return _customer;
}
set
{
ReportPropertyChanging("Customer");
_customer = value;
ReportPropertyChanged("Customer");
}
}
[EdmScalarPropertyAttribute(IsNullable = false)]
public decimal SubTotal
{
get
{
return _subTotal;
}
set
{
if (_subTotal != value)
{
// Validate the value before setting it.
if (value < 0)
{
throw new ApplicationException(string.Format(
Properties.Resources.propertyNotValidNegative,
new string[2] { value.ToString(), "SubTotal" }));
}
ReportPropertyChanging("SubTotal");
_subTotal = value;
ReportPropertyChanged("SubTotal");
ReportPropertyChanging("TaxAmt");
_tax = value;
ReportPropertyChanged("TaxAmt");
ReportPropertyChanging("Freight");
_freight = value;
ReportPropertyChanging("Freight");
}
public decimal TotalDue
{
get
{
return _totalDue;
}
}
[EdmComplexPropertyAttribute()]
public OrderInfo ExtendedInfo
{
get
{
return _ExtendedInfo;
}
set
{
this.ReportPropertyChanging("ExtendedInfo");
_ExtendedInfo = value;
this.ReportPropertyChanged("ExtendedInfo");
}
}
private void CalculateOrderTotal()
{
// Update the total due as a sum of the other cost properties.
_totalDue = _subTotal + _tax + _freight;
}
}
[EdmComplexTypeAttribute(NamespaceName =
"Microsoft.Samples.Edm", Name = "OrderInfo")]
public partial class OrderInfo : ComplexObject
{
private string _orderNumber;
private string _purchaseOrder;
private string _accountNumber;
private string _comment;
[EdmScalarPropertyAttribute(IsNullable = false)]
public string OrderNumber
{
get
{
return _orderNumber;
}
set
{
// Validate the value before setting it.
if (value.Length > 25)
{
throw new ApplicationException(string.Format(
Properties.Resources.propertyNotValidString,
new string[3] { value, "OrderNumber", "25" }));
}
ReportPropertyChanging("OrderNumber");
_orderNumber = value;
ReportPropertyChanged("OrderNumber");
}
}
[EdmScalarPropertyAttribute()]
public string PurchaseOrder
{
get
{
return _purchaseOrder;
}
set
{
// Validate the value before setting it.
if ((value != null) && value.Length > 25)
{
throw new ApplicationException(string.Format(
Properties.Resources.propertyNotValidString,
new string[3] { value, "PurchaseOrder", "25" }));
}
if (_purchaseOrder != value)
{
ReportPropertyChanging("PurchaseOrder");
_purchaseOrder = value;
ReportPropertyChanged("PurchaseOrder");
}
}
}
[EdmScalarPropertyAttribute()]
public string AccountNumber
{
get
{
return _accountNumber;
}
set
{
// Validate the value before setting it.
if ((value != null) && value.Length > 15)
{
throw new ApplicationException(string.Format(
Properties.Resources.propertyNotValidString,
new string[3] { value, "AccountNumber", "15" }));
}
ReportPropertyChanging("AccountNumber");
_accountNumber = value;
ReportPropertyChanged("AccountNumber");
}
}
[EdmScalarPropertyAttribute()]
public string Comment
{
get
{
return _comment;
}
set
{
// Validate the value before setting it.
if ((value != null) && value.Length > 128)
{
throw new ApplicationException(string.Format(
Properties.Resources.propertyNotValidString,
new string[3] { value, "Comment", "128" }));
}
if (_comment != value)
{
ReportPropertyChanging("Comment");
_comment = value;
ReportPropertyChanged("Comment");
}
}
}
}
ReportPropertyChanging("Price");
_price = value;
ReportPropertyChanged("Price");
For more information, see Implementing Custom Data Class Interfaces (Entity Framework). You must also apply
EDM attributes that map the custom classes and properties to entities defined in the conceptual schema definition
language (CSDL) file. For more information, see How to: Map Custom Objects to Entities (Entity Framework).
Instead of directly implementing data class interfaces, you can also inherit from EntityObject. This is the
recommended way to use custom data classes with an EDM. For more information, see Customizing Objects (Entity
Framework) and How to: Inherit from the EntityObject and ComplexObject Base Classes (Entity Framework).
1. Modify the definition of each custom data class so that it implements the IEntityWithChangeTracker,
IEntityWithKey, and IEntityWithRelationships interfaces, as in the following example:
Visual Basic
Copy Code
<EdmEntityTypeAttribute(NamespaceName:="Microsoft.Samples.Edm", Name:="Order")> _
Public Class Order
Implements IEntityWithRelationships, IEntityWithChangeTracker, IEntityWithKey
C#
Copy Code
[EdmEntityTypeAttribute(NamespaceName = "Microsoft.Samples.Edm", Name = "Order")]
public class Order : IEntityWithRelationships, IEntityWithChangeTracker, IEntityWithKey
2. (Optional) Explicitly implement the EntityKey property in each custom data class, as in the following example:
Visual Basic
Copy Code
Dim _entityKey As EntityKey = Nothing
Visual Basic
Copy Code
Dim _changeTracker As IEntityChangeTracker = Nothing
' Every time the change tracker is set, we must also set all the
' complex type change trackers.
If Not _extendedInfo Is Nothing Then
_extendedInfo.SetComplexChangeTracker("ExtendedInfo", _changeTracker)
End If
End Sub
C#
Copy Code
IEntityChangeTracker _changeTracker = null;
// Every time the change tracker is set, we must also set all the
// complex type change trackers.
if (_extendedInfo != null)
{
_extendedInfo.SetComplexChangeTracker("ExtendedInfo", _changeTracker);
}
}
4. This method is required to report changes in data properties to Object Services.
Visual Basic
Copy Code
Dim _relationships As RelationshipManager = Nothing
Visual Basic
Copy Code
<EdmScalarPropertyAttribute(IsNullable:=False)> _
Public Property Status() As Byte
Get
Return _status
End Get
Set(ByVal value As Byte)
If _status <> value Then
' Report the change if the change tracker exists.
If Not _changeTracker Is Nothing Then
_changeTracker.EntityMemberChanging("Status")
_status = value
_changeTracker.EntityMemberChanged("Status")
Else
_status = value
End If
End If
End Set
End Property
C#
Copy Code
[EdmScalarPropertyAttribute(IsNullable = false)]
public byte Status
{
get
{
return _status;
}
set
{
if (_status != value)
{
// Report the change if the change tracker exists.
if (_changeTracker != null)
{
_changeTracker.EntityMemberChanging("Status");
_status = value;
_changeTracker.EntityMemberChanged("Status");
}
else
{
_status = value;
}
}
}
}
7. In the settable complex properties of each data class, add a call to EntityComplexMemberChanging before
setting the property value, and add a call to EntityComplexMemberChanged after the property is set.
Example
This example shows the custom data classes Order and LineItem and a complex type OrderInfo. These custom
classes are mapped to the SalesOrderHeader and SalesOrderDetail tables in the AdventureWorks database.
Both entity classes implement all three custom data class interfaces. The OrderInfo complex type class
demonstrates a suggested change tracking implementation.
Visual Basic
Copy Code
Option Explicit On
Option Strict On
Imports System
Imports System.Data.SqlTypes
Imports System.Collections.Generic
Imports System.Text
Imports System.Data
Imports System.Data.Objects.DataClasses
Imports System.Data.Metadata.Edm
Imports Microsoft.Samples.Edm
<Assembly: EdmSchemaAttribute()>
<Assembly: EdmRelationshipAttribute("Microsoft.Samples.Edm", _
"FK_LineItem_Order_OrderId", "Order", _
RelationshipMultiplicity.One, GetType(Order), "LineItem", _
RelationshipMultiplicity.Many, GetType(LineItem))>
Namespace Microsoft.Samples.Edm
<EdmEntityTypeAttribute(NamespaceName:="Microsoft.Samples.Edm", Name:="Order")> _
Public Class Order
Implements IEntityWithRelationships, IEntityWithChangeTracker, IEntityWithKey
#Region "ExplicitImplementation"
Dim _changeTracker As IEntityChangeTracker = Nothing
' Every time the change tracker is set, we must also set all the
' complex type change trackers.
If Not _extendedInfo Is Nothing Then
_extendedInfo.SetComplexChangeTracker("ExtendedInfo", _changeTracker)
End If
End Sub
_changeTracker.EntityMemberChanged("DueDate")
Else
_dueDate = value
End If
End Set
End Property
<EdmScalarPropertyAttribute()> _
Public Property ShipDate() As Date
Get
Return _shipDate
End Get
Set(ByVal value As Date)
' Report the change if the change tracker exists.
If Not _changeTracker Is Nothing Then
_changeTracker.EntityMemberChanging("ShipDate")
_changeTracker.EntityMemberChanged("ShipDate")
Else
_shipDate = value
End If
End Set
End Property
<EdmScalarPropertyAttribute(IsNullable:=False)> _
Public Property Status() As Byte
Get
Return _status
End Get
Set(ByVal value As Byte)
If _status <> value Then
' Report the change if the change tracker exists.
If Not _changeTracker Is Nothing Then
_changeTracker.EntityMemberChanging("Status")
_status = value
_changeTracker.EntityMemberChanged("Status")
Else
_status = value
End If
End If
End Set
End Property
<EdmScalarPropertyAttribute(IsNullable:=False)> _
Public Property Customer() As Integer
Get
Return _customer
End Get
Set(ByVal value As Integer)
' Report the change if the change tracker exists.
If Not _changeTracker Is Nothing Then
_changeTracker.EntityMemberChanging("Customer")
_customer = value
_changeTracker.EntityMemberChanged("Customer")
Else
_customer = value
End If
End Set
End Property
<EdmScalarPropertyAttribute(IsNullable:=False)> _
Public Property SubTotal() As Decimal
Get
Return _subTotal
End Get
Set(ByVal value As Decimal)
If _subTotal <> value Then
' Validate the value before setting it.
If value < 0 Then
Throw New ApplicationException(String.Format( _
My.Resources.propertyNotValidNegative, _
value.ToString, "SubTotal"))
End If
' Report the change if the change tracker exists.
If Not _changeTracker Is Nothing Then
_changeTracker.EntityMemberChanging("SubTotal")
_subTotal = value
_changeTracker.EntityMemberChanged("SubTotal")
Else
_subTotal = value
End If
' Recalculate the order total.
CalculateOrderTotal()
End If
End Set
End Property
<EdmScalarPropertyAttribute(IsNullable:=False)> _
Public Property TaxAmt() As Decimal
Get
Return _tax
End Get
Set(ByVal value As Decimal)
' Validate the value before setting it.
If value < 0 Then
Throw New ApplicationException(String.Format( _
My.Resources.propertyNotValidNegative, _
value.ToString(), "Tax"))
End If
' Report the change if the change tracker exists.
If Not _changeTracker Is Nothing Then
_changeTracker.EntityMemberChanging("TaxAmt")
_tax = value
_changeTracker.EntityMemberChanged("TaxAmt")
Else
_tax = value
End If
Else
_extendedInfo = value
End If
' Rest the change tracker. Complex type property cannot be Nothing.
If Not _extendedInfo Is Nothing Then
_extendedInfo.SetComplexChangeTracker("ExtendedInfo", _changeTracker)
End If
End Set
End Property
Private Sub CalculateOrderTotal()
' Update the total due as a sum of the other cost properties.
_totalDue = _subTotal + _tax + _freight
End Sub
End Class
' Base class for complex types that implements change tracking.
Public MustInherit Class ComplexTypeChangeTracker
Protected _complexChangeTracker As IEntityChangeTracker = Nothing
Private _rootComplexPropertyName As String
' Protected method that is called before the change for change tracking
' each of the scalar properties in the complex type.
Protected Sub ReportMemberChanging(ByVal scalarPropertyName As String)
If Not _complexChangeTracker Is Nothing Then
_complexChangeTracker.EntityComplexMemberChanging( _
_rootComplexPropertyName, Me, scalarPropertyName)
End If
End Sub
' Protected method that is called after the change for change tracking
' each of the scalar properties in the complex type.
Protected Sub ReportMemberChanged(ByVal scalarPropertyName As String)
If Not _complexChangeTracker Is Nothing Then
_complexChangeTracker.EntityComplexMemberChanged( _
_rootComplexPropertyName, Me, scalarPropertyName)
End If
End Sub
End Class
<EdmComplexTypeAttribute(NamespaceName:="Microsoft.Samples.Edm", Name:="OrderInfo")> _
Partial Public Class OrderInfo
Inherits ComplexTypeChangeTracker
Private _orderNumber As String
Private _purchaseOrder As String
Private _accountNumber As String
Private _comment As String
Private _extendedInfo As OrderInfo
' Call SetChangeTracker on the base class to set the change tracker
' and the name of the root complex type property on the entity.
MyBase.SetComplexChangeTracker(rootComplexPropertyName, changeTracker)
End Sub
<EdmScalarPropertyAttribute(IsNullable:=False)> _
Public Property OrderNumber() As String
Get
Return _orderNumber
End Get
Set(ByVal value As String)
' Validate the value before setting it.
If value.Length > 25 Then
Throw New ApplicationException(String.Format( _
My.Resources.propertyNotValidString, _
"OrderNumber", "25"))
End If
' Report the change if the change tracker exists.
If Not _complexChangeTracker Is Nothing Then
ReportMemberChanging("OrderNumber")
_orderNumber = value
ReportMemberChanged("OrderNumber")
Else
_orderNumber = value
End If
End Set
End Property
<EdmScalarPropertyAttribute()> _
Public Property PurchaseOrder() As String
Get
Return _purchaseOrder
End Get
Set(ByVal value As String)
If (value <> Nothing) AndAlso value.Length > 25 Then
Throw New ApplicationException(String.Format( _
My.Resources.propertyNotValidString, _
"PurchaseOrder", "25"))
End If
If _purchaseOrder <> value Then
' Report the change if the change tracker exists.
If Not _complexChangeTracker Is Nothing Then
ReportMemberChanging("PurchaseOrder")
_purchaseOrder = value
ReportMemberChanged("PurchaseOrder")
Else
_purchaseOrder = value
End If
End If
End Set
End Property
<EdmScalarPropertyAttribute()> _
Public Property AccountNumber() As String
Get
Return _accountNumber
End Get
Set(ByVal value As String)
' Validate the value before setting it.
If (value <> Nothing) AndAlso value.Length > 15 Then
Throw New ApplicationException(String.Format( _
My.Resources.propertyNotValidString, _
"AccountNumber", "15"))
End If
' Report the change if the change tracker exists.
If Not _complexChangeTracker Is Nothing Then
ReportMemberChanging("AccountNumber")
_accountNumber = value
ReportMemberChanged("AccountNumber")
Else
_accountNumber = value
End If
End Set
End Property
<EdmScalarPropertyAttribute()> _
Public Property Comment() As String
Get
Return _comment
End Get
Set(ByVal value As String)
' Validate the value before setting it.
If (value <> Nothing) AndAlso value.Length > 128 Then
Throw New ApplicationException(String.Format( _
My.Resources.propertyNotValidString, _
"Comment", "128"))
End If
If _comment <> value Then
' Report the change if the change tracker exists.
If Not _complexChangeTracker Is Nothing Then
ReportMemberChanging("Comment")
_comment = value
ReportMemberChanged("Comment")
Else
_comment = value
End If
End If
End Set
End Property
End Class
<EdmEntityTypeAttribute(NamespaceName:="Microsoft.Samples.Edm", Name:="LineItem")> _
Public Class LineItem
Implements IEntityWithRelationships, IEntityWithChangeTracker, IEntityWithKey
[assembly: EdmSchemaAttribute()]
[assembly: EdmRelationshipAttribute("Microsoft.Samples.Edm",
"FK_LineItem_Order_OrderId", "Order",
RelationshipMultiplicity.One, typeof(Order), "LineItem",
RelationshipMultiplicity.Many, typeof(LineItem))]
namespace Microsoft.Samples.Edm
{
[EdmEntityTypeAttribute(NamespaceName = "Microsoft.Samples.Edm", Name = "Order")]
public class Order : IEntityWithRelationships, IEntityWithChangeTracker, IEntityWithKey
{
// Define private property variables.
private int _orderId;
private DateTime _orderDate;
private DateTime _dueDate;
private DateTime _shipDate;
private byte _status;
private int _customer;
private decimal _subTotal;
private decimal _tax;
private decimal _freight;
private decimal _totalDue;
private OrderInfo _extendedInfo;
#region ExplicitImplementation
IEntityChangeTracker _changeTracker = null;
// Every time the change tracker is set, we must also set all the
// complex type change trackers.
if (_extendedInfo != null)
{
_extendedInfo.SetComplexChangeTracker("ExtendedInfo", _changeTracker);
}
}
// Protected method that is called before the change for change tracking
// each of the scalar properties in the complex type.
protected void ReportMemberChanging(string scalarPropertyName)
{
if (null != _complexChangeTracker)
{
_complexChangeTracker.EntityComplexMemberChanging(_rootComplexPropertyName,
this, scalarPropertyName);
}
}
// Protected method that is called after the change for change tracking
// each of the scalar properties in the complex type.
protected void ReportMemberChanged(string scalarPropertyName)
{
if (null != _complexChangeTracker)
{
_complexChangeTracker.EntityComplexMemberChanged(_rootComplexPropertyName,
this, scalarPropertyName);
}
}
}
[EdmComplexTypeAttribute(NamespaceName = "Microsoft.Samples.Edm", Name = "OrderInfo")]
public partial class OrderInfo : ComplexTypeChangeTracker
{
private string _orderNumber;
private string _purchaseOrder;
private string _accountNumber;
private string _comment;
[EdmScalarPropertyAttribute(IsNullable = false)]
public string OrderNumber
{
get
{
return _orderNumber;
}
set
{
// Validate the value before setting it.
if (value.Length > 25)
{
throw new ApplicationException(string.Format(
Properties.Resources.propertyNotValidString,
new string[3] { value, "OrderNumber", "25" }));
}
// Report the change if the change tracker exists.
if (_complexChangeTracker != null)
{
ReportMemberChanging("OrderNumber");
_orderNumber = value;
ReportMemberChanged("OrderNumber");
}
else
{
_orderNumber = value;
}
}
}
[EdmScalarPropertyAttribute()]
public string PurchaseOrder
{
get
{
return _purchaseOrder;
}
set
{
// Validate the value before setting it.
if ((value != null) && value.Length > 25)
{
throw new ApplicationException(string.Format(
Properties.Resources.propertyNotValidString,
new string[3] { value, "PurchaseOrder", "25" }));
}
if (_purchaseOrder != value)
{
// Report the change if the change tracker exists.
if (_complexChangeTracker != null)
{
ReportMemberChanging("PurchaseOrder");
_purchaseOrder = value;
ReportMemberChanged("PurchaseOrder");
}
else
{
_purchaseOrder = value;
}
}
}
}
[EdmScalarPropertyAttribute()]
public string AccountNumber
{
get
{
return _accountNumber;
}
set
{
// Validate the value before setting it.
if ((value != null) && value.Length > 15)
{
throw new ApplicationException(string.Format(
Properties.Resources.propertyNotValidString,
new string[3] { value, "AccountNumber", "15" }));
}
if (_purchaseOrder != value)
{
// Report the change if the change tracker exists.
if (_complexChangeTracker != null)
{
ReportMemberChanging("AccountNumber");
_accountNumber = value;
ReportMemberChanged("AccountNumber");
}
else
{
_accountNumber = value;
}
}
}
}
[EdmScalarPropertyAttribute()]
public string Comment
{
get
{
return _comment;
}
set
{
// Validate the value before setting it.
if ((value != null) && value.Length > 128)
{
throw new ApplicationException(string.Format(
Properties.Resources.propertyNotValidString,
new string[3] { value, "Comment", "128" }));
}
if (_comment != value)
{
// Report the change if the change tracker exists.
if (_complexChangeTracker != null)
{
ReportMemberChanging("Comment");
_comment = value;
ReportMemberChanged("Comment");
}
else
{
_comment = value;
}
}
}
}
}
[EdmEntityTypeAttribute(NamespaceName = "Microsoft.Samples.Edm",
Name = "LineItem")]
public class LineItem : IEntityWithRelationships,
IEntityWithChangeTracker, IEntityWithKey
{
// Define private property variables.
int _lineItemId;
string _trackingNumber;
short _quantity;
int _product;
decimal _price;
decimal _discount;
decimal _total;
How to: Use Object Services with Custom Objects (Entity Framework)
The ability to instantiate an ObjectContext specific to your Entity Data Model (EDM), including predefined
connections.
The simplest way to take full advantage of Object Services features is to add the generated class that inherits from
ObjectContext to your project. This class is generated by the Entity Framework tools, based on your EDM.
1. From the command prompt, navigate to the location of the conceptual schema definition language (CSDL) file
for your model, and run the following command with the line breaks removed:
Copy Code
%windir%\Microsoft.NET\Framework\v3.5\edmgen.exe
/mode:EntityClassGeneration
/incsdl:.\YourModel.csdl /outobjectlayer:.\YourModel.context.cs
/language:CSharp
2. This regenerates the object layer in C#, based on the specified CSDL file.
3. Open the newly generated code file, copy the class that inherits from ObjectContext, and paste this class into
your custom data class code file.
Note
You can also remove the data classes and add the remaining class to your project.
1. From the command prompt, navigate to the location of the CSDL file for your model, and run the following
command with the line breaks removed:
Copy Code
%windir%\Microsoft.NET\Framework\v3.5\edmgen.exe
/mode:EntityClassGeneration
/incsdl:.\YourModel.csdl /outobjectlayer:.\YourModel.context.vb
/language:VB
2. This regenerates the object layer in Visual Basic, based on the specified CSDL file.
3. Open the newly generated code file, copy the class that inherits from ObjectContext, and paste this class into
your custom data class code file.
Note
You can also remove the data classes and add the remaining class to your project.
Example
This example shows the generated object context code that supports the Order and LineItem custom data
classes.
Visual Basic
Copy Code
<Assembly: Global.System.Data.Objects.DataClasses.EdmSchemaAttribute("9f3bb474-6454-4ff1-911e-
4a8be227e97c")>
Namespace Microsoft.Samples.Edm
'''<summary>
'''There are no comments for SalesOrdersEntities in the schema.
'''</summary>
Partial Public Class SalesOrdersEntities
Inherits Global.System.Data.Objects.ObjectContext
'''<summary>
'''Initializes a new SalesOrdersEntities object using the connection string found in the 'SalesOrdersEntities'
section of the application configuration file.
'''</summary>
Public Sub New()
MyBase.New("name=SalesOrdersEntities", "SalesOrdersEntities")
End Sub
'''<summary>
'''Initialize a new SalesOrdersEntities object.
'''</summary>
Public Sub New(ByVal connectionString As String)
MyBase.New(connectionString, "SalesOrdersEntities")
End Sub
'''<summary>
'''Initialize a new SalesOrdersEntities object.
'''</summary>
Public Sub New(ByVal connection As Global.System.Data.EntityClient.EntityConnection)
MyBase.New(connection, "SalesOrdersEntities")
End Sub
'''<summary>
'''There are no comments for LineItem in the schema.
'''</summary>
<Global.System.ComponentModel.BrowsableAttribute(False)> _
Public ReadOnly Property LineItem() As Global.System.Data.Objects.ObjectQuery(Of LineItem)
Get
If (Me._LineItem Is Nothing) Then
Me._LineItem = MyBase.CreateQuery(Of LineItem)("[LineItem]")
End If
Return Me._LineItem
End Get
End Property
Private _LineItem As Global.System.Data.Objects.ObjectQuery(Of LineItem) = Nothing
'''<summary>
'''There are no comments for Order in the schema.
'''</summary>
<Global.System.ComponentModel.BrowsableAttribute(False)> _
Public ReadOnly Property Order() As Global.System.Data.Objects.ObjectQuery(Of Order)
Get
If (Me._Order Is Nothing) Then
Me._Order = MyBase.CreateQuery(Of Order)("[Order]")
End If
Return Me._Order
End Get
End Property
Private _Order As Global.System.Data.Objects.ObjectQuery(Of Order) = Nothing
'''<summary>
'''There are no comments for LineItem in the schema.
'''</summary>
Public Sub AddToLineItem(ByVal lineItem As LineItem)
MyBase.AddObject("LineItem", lineItem)
End Sub
'''<summary>
'''There are no comments for Order in the schema.
'''</summary>
Public Sub AddToOrder(ByVal order As Order)
MyBase.AddObject("Order", order)
End Sub
End Class
End Namespace
C#
Copy Code
[assembly: System.Data.Objects.DataClasses.EdmSchemaAttribute()]
namespace Microsoft.Samples.Edm
{
/// <summary>
/// There are no comments for SalesOrdersEntities in the schema.
/// </summary>
public partial class SalesOrdersEntities : global::System.Data.Objects.ObjectContext
{
/// <summary>
/// Initializes a new SalesOrdersEntities object using the connection string found in the 'SalesOrdersEntities'
section of the application configuration file.
/// </summary>
public SalesOrdersEntities() :
base("name=SalesOrdersEntities", "SalesOrdersEntities")
{
}
/// <summary>
/// Initialize a new SalesOrdersEntities object.
/// </summary>
public SalesOrdersEntities(string connectionString) :
base(connectionString, "SalesOrdersEntities")
{
}
/// <summary>
/// Initialize a new SalesOrdersEntities object.
/// </summary>
public SalesOrdersEntities(global::System.Data.EntityClient.EntityConnection connection) :
base(connection, "SalesOrdersEntities")
{
}
/// <summary>
/// There are no comments for LineItem in the schema.
/// </summary>
[global::System.ComponentModel.BrowsableAttribute(false)]
public global::System.Data.Objects.ObjectQuery<LineItem> LineItem
{
get
{
if ((this._LineItem == null))
{
this._LineItem = base.CreateQuery<LineItem>("[LineItem]");
}
return this._LineItem;
}
}
private global::System.Data.Objects.ObjectQuery<LineItem> _LineItem = null;
/// <summary>
/// There are no comments for Order in the schema.
/// </summary>
[global::System.ComponentModel.BrowsableAttribute(false)]
public global::System.Data.Objects.ObjectQuery<Order> Order
{
get
{
if ((this._Order == null))
{
this._Order = base.CreateQuery<Order>("[Order]");
}
return this._Order;
}
}
private global::System.Data.Objects.ObjectQuery<Order> _Order = null;
/// <summary>
/// There are no comments for LineItem in the schema.
/// </summary>
public void AddToLineItem(LineItem lineItem)
{
base.AddObject("LineItem", lineItem);
}
/// <summary>
/// There are no comments for Order in the schema.
/// </summary>
public void AddToOrder(Order order)
{
base.AddObject("Order", order);
}
}
}
More...
The following security considerations apply to all applications that use the Entity Framework.
Translate the command tree to the data source's native query language.
During the logon operation, information that is based on the user password is passed to the server through the
network libraries of the underlying data source. A malicious provider can steal user credentials, generate malicious
queries, or tamper with the result set.
When you use Windows Authentication to connect to a SQL Server data source, the connection string does
not contain logon and password information.
You should never embed connection strings in your source code. You can store connection strings in
configuration files, which eliminates the need to embed them in your application's code. By default, the
Entity Data Model Wizard stores connection strings in the application configuration file. You must secure
this file to prevent unauthorized access.
If you must construct connection strings at runtime, use the EntityConnectionStringBuilder class. This
string builder class helps prevent connection string injection attacks by validating and escaping invalid
input information. For more information, see How to: Build an EntityConnection Connection String (Entity
Framework). Also use the appropriate string builder class to construct the data source connection string
that is part of the Entity Data Model (EDM) connection string. For information about connection string
builders for ADO.NET providers, see Connection String Builders (ADO.NET).
Be aware that logon information and passwords may be visible in a memory dump.
When data source logon and password information is supplied in the connection string, this information is
maintained in memory until garbage collection reclaims the resources. This makes it impossible to determine when
a password string is no longer in memory. If an application crashes, a memory dump file may contain sensitive
security information, and the user running the application and any user with administrative access to the computer
can view the memory dump file. Use Windows Authentication for connections to Microsoft SQL Server.
FileIOPermission: Write to open the specified metadata files or PathDiscovery to search a directory for
metadata files.
Permission to open a database connection and execute commands against the database, such as
The provider invariant name is modifiable in the app.config. The client application must take responsibility for
accessing the underlying provider through the standard provider factory model by using a strong name.
The following security considerations apply when querying an EDM. These considerations apply to Entity SQL
queries using EntityClient and to object queries using LINQ, Entity SQL, and query builder methods.
Entity SQL queries accept parameters everywhere that literals are accepted. You should use
parameterized queries instead of injecting literals from an external agent directly into the query.
Although query composition is possible in LINQ to Entities, it is performed through the object model
API. Unlike Entity SQL queries, LINQ to Entities queries are not composed by using string manipulation or
concatenation, and they are not susceptible to traditional SQL injection attacks.
In queries against a large database that do not include appropriate filter conditions.
When accepting user input, you must make sure that the input cannot cause result sets to become larger than
what the system can handle. You can also use the Take method in LINQ to Entities or the LIMIT operator in Entity
SQL to limit the size of the result set.
The following security considerations apply when generating and working with entity types.
The following should be considered when you work with paths in ASP.NET applications.
Verify whether your host performs path checks.
When the |DataDirectory| (enclosed in pipe symbols) substitution string is used, ADO.NET verifies that the
resolved path is supported. For example, ".." is not allowed behind DataDirectory. That same check for resolving
the Web application root operator (~) is performed by the process hosting ASP.NET. IIS performs this check;
however, hosts other than IIS may not verify that the resolved path is supported. You should know the behavior of
the host on which you deploy an Entity Framework application.
The following security considerations apply when generating and working with EDM model and mapping files.
In order to better understand the performance of queries in the Entity Framework, it is helpful to understand the
operations that occur when a query executes against an Entity Data Model (EDM) and returns data as objects. The
following table describes this series of operations.
Relative
Operation Cost Frequency Comments
Loading Moderate Once in each EDM model and mapping metadata is loaded into a
metadata application domain. MetadataWorkspace. This metadata is cached
globally and is available to other instances of
ObjectContext in the same application domain. For
more information, see Metadata Workspace
Overview.
Generating High Once in each Before the Entity Framework can execute a query
views application domain. against an EDM or save changes to the data
(Can be pre- source, it must generate a set of local query views
generated.) to access the database. Because of the high cost of
generating these views, you can pre-generate the
views and add them to the project at design-time.
For more information, see How to: Pre-Generate
Views to Improve Query Performance (Entity
Framework).
Preparing the Moderate2 Once for each Includes the costs to compose the query command,
query unique query. generate a command tree based on the EDM
metadata, and define the shape of the returned
data. Because Entity SQL query commands are
cached, later executions of the same query take
even less time. You can also use compiled LINQ
queries to reduce this cost in later executions. For
more information, see Compiled Queries (LINQ to
Entities). For general information about LINQ query
execution, see LINQ to Entities Flow of Execution.
Executing the Low2 Once for each The cost of executing the command against the
query query. data source by using the ADO.NET data provider.
Because most data sources cache query plans,
later executions of the same query may take even
less time.
Loading and Low3 Once for each Types are loaded and validated against the types
validating ObjectContext that the EDM defines.
types instance.
Tracking Low3 Once for each An EntityKey is generated for each tracked object
object that a query that the query returns. This key is used to create
returns. 4 an ObjectStateEntry in the ObjectStateManager.
The MergeOption that is used to execute the query
defines the tracking behavior. If the query uses the
NoTracking merge option or if the object already
exists in the ObjectContext and the query uses
the AppendOnly or PreserveChanges merge
options, this stage does not affect performance.
For more information, see Change Tracking and
Identity Resolution (Entity Framework).
Materializing Moderate3 Once for each The process of reading the returned DbDataReader
the objects object that a query object and creating objects and setting property
returns. 4 values that are based on the values in each
instance of the DbDataRecord class. If the object
already exists in the ObjectContext and the query
uses the AppendOnly or PreserveChanges
merge options, this stage does not affect
performance. For more information, see Change
Tracking and Identity Resolution (Entity
Framework).
1
When a data source provider implements connection pooling, the cost of opening a connection is distributed
across the pool. The .NET Provider for SQL Server supports connection pooling.
2
Cost increases with increased query complexity.
3
Total cost increases proportional to the number of objects returned by the query.
4
This overhead is not required for EntityClient queries because EntityClient queries return an EntityDataReader
instead of objects. For more information, see EntityClient Provider for the Entity Framework.
Additional Considerations
The following are other considerations that may affect performance of Entity Framework applications.
Query Execution
Because queries can be resource intensive, consider at what point in your code and on what computer a query is
executed.
Mapping complexity
Models that are more complex than a simple one-to-one mapping between entities in the conceptual model and
tables in the storage model generate more complex commands than models that have a one-to-one mapping.
Query complexity
Queries that require a large number of joins in the commands that are executed against the data source or that
return a large amount of data may affect performance in the following ways:
Queries against an EDM that seem simple may result in the execution of more complex queries against the
data source. This can occur because the Entity Framework translates a query against an EDM into an
equivalent query against the data source. When a single entity set in the conceptual model maps to more
than one table in the data source, or when a relationship between entities is mapped to a join table, the
query command executed against the data source query may require one or more joins.
Note
Use the ToTraceString method of the ObjectQuery or EntityCommand classes to view the commands
that are executed against the data source for a given query. For more information, see How to: View
the Store Commands (Entity Framework).
Nested Entity SQL queries may create joins on the server and can return a large number of rows.
Copy Code
Any queries that return a large amount of data can cause decreased performance if the client is
performing operations that consume resources in a way that is proportional to the size of the result set. In
such cases, you should consider limiting the amount of data returned by the query. For more information,
see How to: Page Through Query Results (Entity Framework).
Any commands automatically generated by the Entity Framework may be more complex than similar commands
written explicitly by a database developer. If you need explicit control over the commands executed against your
data source, consider defining a mapping to a table-valued function or stored procedure. For more information, see
Stored Procedure Support (Entity Framework).
Relationships
For optimal query performance, you must define relationships between entities both as associations in the entity
model and as logical relationships in the data source.
Query Paths
By default, when you execute an ObjectQuery, related objects are not returned (although objects that represent
the relationships themselves are). You can load related objects in one of two ways: either by setting the query path
before the ObjectQuery is executed, or by calling the Load method on the navigation property that the object
exposes. When you consider which option to use, be aware that there is a tradeoff between the number of requests
against the database and the amount of data returned in a single query. For more information, see Shaping Query
Results (Entity Framework).
Using query paths
Query paths define the graph of objects that a query returns. When you define a query path, only a single request
against the database is required to return all objects that the path defines. Using query paths can result in complex
commands being executed against the data source from seemingly simple object queries. This occurs because one
or more joins are required to return related objects in a single query. This complexity is greater in queries against
a complex entity model, such as an entity with inheritance or a path that includes many-to-many relationships.
Note
Use the ToTraceString method to see the command that will be generated by an ObjectQuery. For
more information, see How to: View the Store Commands (Entity Framework).
When a query path includes too many related objects or the objects contain too much row data, the data source
might be unable to complete the query. This occurs if the query requires intermediate temporary storage that
exceeds the capabilities of the data source. When this occurs, you can reduce the complexity of the data source
query by explicitly loading related objects.
Note
if you call Load while looping through a collection of returned objects, such as when you use the
foreach statement (For Each in Visual Basic), the data source-specific provider must support multiple
active results sets on a single connection. For a SQL Server database, you must specify a value of
MultipleActiveResultSets = true in the provider connection string.
Although explicitly loading related objects will reduce the number of joins and reduced the amount of redundant
data, Load requires repeated connections to the database, which can become costly when explicitly loading a large
number of objects.
Saving Changes
When you call the SaveChanges method on an ObjectContext, a separate create, update, or delete command is
generated for every added, updated, or deleted object in the context. These commands are executed on the data
source in a single transaction. As with queries, the performance of create, update, and delete operations depends
on the complexity of the mapping in the EDM.
Distributed Transactions
Operations in an explicit transaction that require resources that are managed by the distributed transaction
coordinator (DTC) will be much more expensive than a similar operation that does not require the DTC. Promotion
to the DTC will occur in the following situations:
An explicit transaction with an operation against a SQL Server 2000 database or other data source that
An explicit transaction with an operation against SQL Server 2005 when the connection is managed by
Object Services. This occurs because SQL Server 2005 promotes to a DTC whenever a connection is
closed and reopened within a single transaction, which is the default behavior of Object Services. This DTC
promotion does not occur when using SQL Server 2008. To avoid this promotion when using SQL Server
2005, you must explicitly open and close the connection within the transaction. For more information, see
Managing Connections in Object Services (Entity Framework).
An explicit transaction is used when one or more operations are executed inside a System.Transactions transaction.
For more information, see Managing Transactions in Object Services (Entity Framework).
You can improve the overall performance of queries in the Entity Framework by using the following strategies.
Pre-generate views.
Generating views based on an entity model is a significant cost the first time that an application executes a query.
Use the EdmGen.exe utility to pre-generate views as a Visual Basic or C# code file that can be added to the project
during design. Pre-generated views are validated at runtime to ensure that they are consistent with the current
version of the specified entity model. For more information, see How to: Pre-Generate Views to Improve Query
Performance (Entity Framework).
To avoid returning too much data in a single query, consider paging the results of the query into more manageable
groups. For more information, see How to: Page Through Query Results (Entity Framework).
Performance Data
Some performance data for the Entity Framework is published in the following posts on the ADO.NET team blog:
Describes considerations for migrating an existing application to use the Entity Framework.
To take advantage of the benefits of the Entity Framework, you can migrate an existing application to the Entity
Framework. Some tasks are common to all migrated applications. These common tasks include upgrading the
application to use the .NET Framework version 3.5 Service Pack 1 (SP1), defining the EDM, and configuring the
Entity Framework. When you migrate an application to the Entity Framework, there are additional considerations
that apply. These considerations depend on the type of application being migrated and on the specific functionality
of the application. This topic provides information to help you choose the best approach to use when you upgrade
an existing application.
The following considerations apply when you migrate any application to the Entity Framework:
Any application that uses the .NET Framework 3.5 can be migrated to the Entity Framework, as long as
the data provider for the data source that is used by the application supports the Entity Framework.
The Entity Framework may not support all the functionality of a data source provider, even if that provider
For a large or complex application, you are not required to migrate the whole application to the Entity
Framework at one time. However, any part of the application that does not use the Entity Framework
must still be changed when the data source changes.
The data provider connection used by the Entity Framework can be shared with other parts of your
application because the Entity Framework uses ADO.NET data providers to access the data source. For
example, the SqlClient provider is used by the Entity Framework to access a SQL Server database. For
more information, see EntityClient Provider for the Entity Framework.
The path to migrate an existing application to the Entity Framework depends both on the type of application and on
the existing data access strategy. However, you must always perform the following tasks when you migrate an
existing application to the Entity Framework.
Note
All of these tasks are performed automatically when you use the Entity Data Model tools with Visual
Studio 2008. For more information, see How to: Use the Entity Data Model Wizard (Entity Framework).
A project created by using an earlier version of Visual Studio and the .NET Framework must be upgraded to
use Visual Studio 2008 SP1 and the .NET Framework 3.5 SP1. For more information, see Visual Studio
Conversion Wizard.
The EDM defines entities in the conceptual model; structures in the data source, such as tables, stored
procedures, and views; and the mapping between the entities and data source structures. For more
information, see How to: Manually Define an Entity Data Model (Entity Framework).
Types that are defined in the storage model must match the name of objects in the data source. If the existing
application exposes data as objects, you must ensure that the entities and properties that are defined in the
conceptual model match the names of these existing data classes and properties. For more information, see
How to: Customize an Entity Data Model to Work with Custom Objects (Entity Framework).
Note
The Entity Data Model Designer can be used to rename entities in the conceptual model to match
existing objects. For more information, see ADO.NET Entity Data Model Designer Overview.
The Entity Framework uses a specially formatted connection string when executing queries against an EDM.
This connection string encapsulates information about the EDM mapping files and the connection to the data
source. For more information, see How to: Define the Connection String (Entity Framework).
4. Configure the Visual Studio project.
References to Entity Framework assemblies and the EDM must be added to the Visual Studio project. You can
add these mapping files to the project to ensure that they are deployed with the application in the location that
is indicated in the connection string. For more information, see How to: Manually Configure an Entity
Framework Project.
When you migrate an application to the Entity Framework, the way that you migrate existing data classes depends
on the business logic, custom methods, and property validation implemented in these classes. You should select
one of the following approaches for working with existing data classes.
If your data classes only get and set object properties, replace your existing data classes with the entity
types generated by the Entity Data Model tools. For more information, see How to: Use the Entity Data
Model Wizard (Entity Framework).
If your data classes implement custom validation code or other business logic, migrate this logic into the
partial classes that are generated by the Entity Data Model tools. The Entity Data Model tools generate
entity types as partial classes. This enables you to reuse methods and properties by converting your
existing classes into partial classes. When you do this, you must remove from the existing application any
properties that are duplicated in the generated class. For more information about how to create partial
classes, see Customizing Objects (Entity Framework).
For each property of a data class, the Entity Framework tools generate partial methods named
OnPropertyNameChanging and OnPropertyNameChanged. You can move your existing property
validation code into these partial methods. For more information, see How to: Execute Business Logic
During Property Changes (Entity Framework).
If you have a significant amount of custom code in your existing data classes or you want to keep your
existing data classes for other reasons, you should do one of the following:
Modify your data classes to inherit from the EntityObject or the ComplexObject class. All generated
EDM types inherit from EntityObject or ComplexObject, and the Entity Framework enables you to
use custom data classes by inheriting from these base classes. This is the recommended way to use
custom data classes with an EDM. For more information, see Customizing Objects (Entity Framework).
Modify your data classes to implement a set of interfaces. Do this if your data classes cannot inherit
from EntityObject or ComplexObject. For more information about how to implement these
interfaces, see Customizing Objects (Entity Framework).
Note
When you use existing data classes or partial classes with an EDM, the class names must match the
entity names that are defined in the conceptual model. Use the Entity Designer to rename entities. For
more information, see How to: Create and Modify Entity Types.
You may consider executing an Entity SQL query using the EntityClient provider and enumerating through
the returned EntityDataReader object. Do this only if your application displays tabular data using a data
reader and does not require the facilities provided by Object Services for materializing data into objects,
tracking changes, and making updates. You can continue to use existing data access code that makes
updates to the data source, but you can use the existing connection accessed from the StoreConnection
property of EntityConnection. For more information, see EntityClient Provider for the Entity Framework.
In the Entity Framework, Object Services provides many of the same functionalities provided by DataSet,
including in-memory persistence, change tracking, data binding, and serializing objects as XML data. For
more information, see Object Services Overview (Entity Framework).
If Object Services does not provide the functionality of DataSet needed by your application, you can still
take advantage of the benefits of LINQ queries by using LINQ to DataSet. For more information, see LINQ
to DataSet.
The .NET Framework lets you encapsulate data in a data source, such as a DataSet or an ASP.NET data source
control, and then bind user interface elements to those data controls. The following list describes considerations for
binding controls to Entity Framework data.
When you query the EDM, Object Services returns the data as objects that are instances of entity types.
These objects can be bound directly to controls, and this binding supports updates. This means that
changes to data in a control, such as a row in a DataGridView, automatically get saved to the database
when the SaveChanges method is called.
If your application enumerates the results of a query to display data in a DataGridView or other type of
control that supports data binding, you can modify your application to bind the control to the result of an
ObjectQuery.
The Entity Framework includes a data source control designed to simplify data binding in ASP.NET Web
applications. For more information, see Entity Framework Data Source Control.
Other Considerations
The following are considerations that may apply when you migrate specific types of applications to the Entity
Framework.
Object serialization enables you to create Entity Framework data services. These services provide data to
applications that consume XML data, such as AJAX-based Internet applications. In these cases, consider
using ADO.NET Data Services. These data services are based on the EDM and provide dynamic access to
entity data by using standard Representational State Transfer (REST) HTTP actions, such as GET, PUT,
and POST. For more information, see ADO.NET Data Services Framework.
The Entity Framework does not support a native-XML data type. This means that when an entity is
mapped to a table with an XML column, the equivalent entity property for the XML column is a string.
Objects can be disconnected and serialized as XML. For more information, see Serializing Objects (Entity
Framework).
If your application requires the ability to query XML data, you can still take advantage of the benefits of
LINQ queries by using LINQ to XML. For more information, see LINQ to XML.
ASP.NET Web applications must frequently maintain the state of a Web page or of a user session. Objects
in an ObjectContext instance can be stored in the client view state or in the session state on the server,
and later retrieved and reattached to a new object context. For more information, see Attaching Objects
(Entity Framework).
The Entity Framework provides a set of tools that integrate with and make it easier to develop in Visual Studio. For
more information, see Entity Data Model Tools. This topic does not describe how to use specific technologies to
deploy an Entity Framework–based application.
Visual Studio provides facilities for distributing and deploying applications, such as ClickOnce deployment. For more
information, see Deploying Applications and Components in the Visual Studio documentation.
The following considerations apply when you deploy an application that uses the Entity Framework:
The Entity Framework is a component of the .NET Framework starting with the .NET Framework 3.5
Service Pack 1 (SP1). You must ensure that the .NET Framework 3.5 SP1 or a later version is installed
when deploying an Entity Framework–based application.
When an Entity Data Model (EDM) is generated by the Entity Data Model Wizard, EDM connection strings
are created in the application configuration file. By default, model and mapping files are deployed as
embedded application resources. Use the Metadata Artifact Processing property of the Entity Designer file
to control whether model and mapping files are deployed as embedded resources. For more information,
see Deployment Tasks with the Entity Designer.
Ensure that the model and mapping files (.csdl, .ssdl, .msl) are deployed with the application and in the
location specified by the EDM connection string. For more information, see Connection Strings (Entity
Framework).
When you embed EDM model and mapping files as application resources, you must recompile and
Because the Entity Framework is a component of the .NET Framework, it can be redistributed with your
application as permitted by the .NET Framework license agreement. For more information, see
Redistributing the .NET Framework.
In This Section
The following features and components of the Entity Framework work together to provide an end-to-end
programming environment.
The Entity Data Model (EDM) is the centerpiece of the Entity Framework. It specifies the design schema,
which is used to build the programmable classes used by application code. Storage structures for
persisting data are represented a storage schema, and a mapping specification connects the design
schema with the storage schema. Conceptual entities can be materialized as objects or can be read in
serialized form using a data reader. Developers can extend these objects as needed to support varying
application needs. For more information, see Entity Data Model.
The Object Services component enables programmers to work with the common language runtime (CLR)
classes generated from the conceptual model. It also provides infrastructure support for the Entity
Framework, providing services such as state management, change tracking, identity resolution, loading
and navigating relationships, propagation of object changes to database modifications, and query support
for Entity SQL. For more information, see Object Services (Entity Framework).
LINQ to Entities provides Language-Integrated Query (LINQ) support for querying entities. LINQ to
Entities enables developers to write queries against the database using one of the supported .NET
Framework programming languages such as Visual Basic or Visual C#. For more information, see LINQ to
Entities.
Entity SQL is a SQL-like storage-independent language, designed to query and manipulate rich object
graphs of objects based on the Entity Data Model (EDM). For more information, see Entity SQL Language.
The EntityClient provider extends the ADO.NET provider model by accessing data in terms of conceptual
entities and relationships. It executes queries that use Entity SQL. Entity SQL provides the underlying
query language that enables EntityClient to communicate with the database. For more information, see
EntityClient Provider for the Entity Framework.
The ADO.NET metadata component manages metadata for the design time and runtime needs of the
Entity Framework. All metadata associated with models and mappings are exposed through metadata
interfaces that are independent of the mechanism used for metadata storage. The current storage
mechanism uses file that are based on three XML dialects: conceptual schema definition language (CSDL),
store schema definition language (SSDL), and mapping specification language (MSL). For more
information, see ADO.NET Metadata.
The Entity Framework includes an evolving set of tools that generate mappings and partial classes that
represent the entities in the conceptual model. For more information, see Entity Data Model Tools.
The Entity Framework includes an updated SqlClient Data Provider that supports canonical command
trees. For more information, see .NET Framework Data Provider for SQL Server (SqlClient) for the Entity
Framework.
Architectural Diagram
The following diagram shows how the various user accessible programming interfaces relate in the Entity
Framework. A downward arrow indicates a query against the data source, and an upward arrow indicates returned
data. Object Services generates a canonical command tree that represents a LINQ to Entities or Entity SQL
operation against the conceptual model. The EntityClient provider transforms this canonical command tree, based
on the EDM, into a new canonical command tree that is an equivalent operation against the data source.
Entity Data Model
EDM Specifications
ADO.NET Metadata
Object Services
.NET Framework Data Provider for SQL Server (SqlClient) for the Entity Framework
Related Sections
In This Section
Sample Applications
Term Definition
alias An attribute of the Schema element in CSDL and SSDL schemas that can be
substituted for the full namespace to shorten element references in the schema.
association set A logical container for instances of associations of the same type.
For more information, see Association Sets (EDM).
base type A type in the Entity Data Model from which one or more derived types inherit
some of their properties.
For more information, see Inheritance (EDM).
complex type A .NET Framework class that represents a complex property as defined in the
conceptual model. Complex types enable scalar properties to be organized within
entities. Complex objects are instances of complex types. For more information,
see Complex Type Objects (Entity Framework).
ComplexType The specification for a data type that represents a non-scalar property of an
entity type that does not have a key property.
For more information, see Complex Type (EDM).
conceptual model An abstract specification for the entity types, complex types, associations, entity
containers, entity sets, and association sets in the domain of an application built
on an Entity Data Model. The conceptual model is defined in CSDL in the
conceptual model file.
For more information, see Data Modeling in the Entity Framework.
conceptual model An XML file that is the conceptual model, expressed in CSDL. This file has a .csdl
file extension.
conceptual schema An XML-based language that is used to define the entity types, associations,
definition language entity containers, entity sets, and association sets of a conceptual model.
(CSDL) For more information, see Conceptual Schema (CSDL).
constraint Restricts the possible values of a property and makes sure that a value is valid.
For more information, see Type Constraints (EDM).
concurrency A process that allows multiple users to access and change shared data at the
same time. The Entity Framework implements an optimistic concurrency model.
For more information, see Saving Changes and Managing Concurrency (Entity
Framework).
data binding The process or method for configuring controls on a form or Web page to fetch
data from or write data to entity objects.
For more information, see Binding Objects to Controls (Entity Framework).
direction Refers to the asymmetrical nature of some associations. Direction is specified with
FromRole and ToRole attributes of a NavigationProperty or
ReferentialConstraint element in a schema.
For more information, see Entity Data Model Relationships and Association
Element (SSDL).
entity A concept in the domain of an application from which a data type is defined.
For more information, see Entities and Relationships (EDM).
entity container Specifies entity sets and association sets that will be implemented in a specified
namespace.
For more information, see Entity Containers (EDM).
Entity Data Model A model that enables application data to be represented as a set of entities and
relationships that are mapped to a defined data source.
(EDM) For more information, see Data Modeling in the Entity Framework.
Entity Data Model An XML file that encapsulates the conceptual model, storage model, and mapping
Designer file that compose an EDM. This file also contains information that is used by the
Entity Data Model Designer. This file has an .edmx extension.
For more information, see ADO.NET Entity Data Model Designer Overview.
entity set A logical container for entities of a given type and its subtypes. Entity sets are
mapped to tables in a database.
For more information, see Entity Sets (EDM).
Entity SQL A storage-independent dialect of SQL that works directly with conceptual entity
schemas and that supports Entity Data Model features such as inheritance and
relationships.
For more information, see Entity SQL Language.
entity type A .NET Framework class that represents an entity as defined in the conceptual
model. Entity types may have scalar, complex, and navigation properties. Objects
are instances of entity types. For more information, see Object Services Overview
(Entity Framework).
EntityType The specification for a data type that includes a key and a named set of
properties and represents a top-level item in a conceptual model or storage
model.
For more information, see Entity Type (EDM).
key The attribute of an entity type that specifies which property or set of properties is
used to identify unique instances of the entity type. Represented in the object
layer by the EntityKey class.
For more information, see Key Attribute (EntityType CSDL) and Key Attribute
(EntityType SSDL).
LINQ to Entities A query syntax that defines a set of query operators that allow traversal, filter,
and projection operations to be expressed in a direct, declarative way in Visual
C# and Visual Basic.
For more information, see LINQ to Entities.
mapping file An XML file that is the mapping between the conceptual model and the storage
model, expressed in MSL. This file has a .msl extension.
mapping An XML-based language that is used to map items defined in a conceptual model
specification to items in a storage model.
language (MSL) For more information, see Mapping Specification (MSL).
metadata type A set of classes that enable you to interact with EDM metadata. This type
hierarchy hierarchy provides programmatic support to represent the same concepts
discussed in the EDM Specifications.
For more information, see Metadata Type Hierarchy Overview.
metadata A class that represents the metadata runtime service component that provides
workspace support for retrieving metadata.
For more information, see Metadata Workspace.
modification Stored procedures that are used to insert, update, and delete data that is in the
functions data source. These functions are used in place of Entity Framework generated
commands. Modification functions are defined by the Function element in the
storage model. The ModificationFunctionMapping element maps these
modification functions to insert, update, and delete operations against entities
that are defined in the conceptual model. For more information, see Stored
Procedure Support (Entity Framework).
multiplicity The number of entities that can exist on each side of a relationship, as defined by
an association. Also known as cardinality.
For more information, see Entity Data Model Relationships.
multiple entity sets The ability for an entity type to be defined in more than one entity set.
per type For more information, see Entity Sets (EDM).
navigation A property of an entity type that represents a relationship to another entity type,
property as defined by an association. Navigation properties are used to return related
objects as an EntityCollection or an EntityReference, depending on the multiplicity
at the other end of the association.
For more information, see Navigation Properties (EDM).
query path A string representation of a path that specifies which related objects to return
when an object query is executed. A query path is defined by calling the Include
method on an ObjectQuery.
For more information, see Shaping Query Results (Entity Framework).
object context Represents the entity container defined in the conceptual model. It contains a
connection to the underlying data source and provides services such as change
tracking and identity resolution. An object context is represented by an instance
of the ObjectContext class.
For more information, see Object Services Overview (Entity Framework).
object query A query executed against an EDM within an object context that returns data as
objects.
For more information, see Object Queries (Entity Framework).
object-relational A technique for transforming data from a relational database into data types that
mapping can be used in object-oriented software applications.
Object Services uses the EDM to provide such object-relational behavior by
exposing entities in the conceptual model as entity types in an Entity Framework
application.
Object Services Services provided by the Entity Framework that enable application code to
operate on entities like .NET Framework objects.
For more information, see Object Services Overview (Entity Framework).
referential A constraint that is defined in an EDM that indicates that an entity has a
constraint dependent relationship to another entity. This constraint means that an instance
of a dependent entity cannot exist without a corresponding instance of the
principle entity
For more information, see Referential Constraints (Entity Framework).
role The name given to each End of an association to clarify the semantics of the
relationship.
For more information, see Role Attribute (Association CSDL) and Role Attribute
(Association SSDL).
scalar property A property of an entity that maps to a single field in the storage model.
simple type A primitive type that is used for defining properties in the conceptual model.
For more information, see Simple Types (EDM).
split entity An entity type that is mapped to two separate types in the storage model.
For more information, see How to: Define a Model with Single Entity Mapped to
Two Tables.
storage model A definition for the logical model of data in a supported data source, such as a
relational database. The storage model is defined in SSDL in the storage model
file.
For more information, see Data Modeling in the Entity Framework.
storage model file An XML file that is the storage model, expressed in SSDL. This file has a .ssdl
extension.
store schema An XML-based language that is used to define the entity types, associations,
definition language entity containers, entity sets, and association sets of a storage model that
(SSDL) frequently corresponds to a database schema.
For more information, see Storage Metadata Schema (SSDL).
table-per- A method of modeling a type hierarchy in a database that includes the attributes
hierarchy of all the types in the hierarchy in one table.
For more information, see How to: Define a Model with Table-per-Hierarchy
Inheritance (Entity Framework).
table-per-type A method of modeling a type hierarchy in a database that uses multiple tables
with one-to-one relationships to model the various types.
For more information, see How to: Define a Model with Table-per-Type
Inheritance (Entity Framework).