您的位置:首页 > 其它

ADO.NET Entity Framework & LINQ to Entities - deel 1

2010-11-10 11:49 537 查看
Some weeks ago Microsoft released Beta 3 of the ADO.NET
Entity Framework

(sometimes called ADO.NET vNext). Probably the
final version will be shipped during the first half of 2008 as an
update to the Visual Studio 2008 & .NET 3.5 release.

Update 20/10/2008
: Visual Studio 2008 & .NET 3.5
Service Pack 1 has been released in August 2008. This article has been
updated so all examples will work fine in the final version of the
Entity Framework.

The Entity Framework looks like a interesting technology which is
more powerful and advanced than LINQ to SQL. Both technologies have a
different kind of philosophy but several features have similar
implementations. The EF is more than just an ORM (Object Relational
Mapping) tool. It allows developers to query and manipulate data using a
conceptual model instead of a physical storage model. It will also
become the foundation of new application blocks like Astoria

(ADO.NET Data Services) which will enable you to expose any data store
as web services and Jasper
(Data Access Incubation Projects) which can be used to build dynamic data layers
.

This article will not explain all details about the Entity Framework
nor compare everything with LINQ to SQL. But I will try to create a
small tutorial on how to start with the Entity Framework using the
Northwind sample database. If possible I will refer to LINQ to SQL
features. This article will be the first in a series about the ADO.NET
Entity Framework and the LINQ to Entities querying language.

The
Entity Framework architecture

Installation

Generate
an Entity Data Model

The
Entity Data Model (EDM)

LINQ
to SQL Diagram vs. Entity Data Model

Names
of EntityTypes and EntitySets

Scheme
file (EDMX)

Model
Browser

Mapping
Details

Generated
entity classes

Documentation

Entity
SQL

ObjectQuery
queries which return entity types

ObjectQuery
queries with parameters

ObjectQuery
queries which return primitive types

ObjectQuery
queries which return anonymous types

EntityCommand
queries which return entity types

EntityCommand
queries which return anonymous types

EntityCommand
queries with parameters

LINQ
to Entities

LINQ
queries with parameters

LINQ
queries which return anonymous types

Part 2 :

View
SQL statements

SQL
profiling tools

ToTraceString
method

Tools

eSqlBlast

LINQPad

Part 3 :

Add,
update and delete entities

Update
(modify) an entity

Add (create)
and entity

Add
(create) entity with associated entities

Delete an
entity

Concurrency
handling

Set
ConcurrencyMode

Resolve
concurrency conflicts

Change
tracking

ObjectStateManager

Dump() &
DumpAsHtml() extension methods

NoTracking
option

Part 4 :

Querying
metadata


The Entity
Framework architecture



The ADO.NET Entity Framework is a layered
framework which abstracts the relational schema of a database and
presents a conceptual model.

Data Source
: The bottom layer is the data
which can be stored in one or many databases.

Data Providers
: The data will be accessed by a
ADO.NET data provider. At this moment only SQL Server is supported but
in the near future there will be data providers for Oracle, MySQL, DB2,
Firebird, Sybase, VistaDB, SQLite, ...

Entity Data Model (EDM)
: The Entity Data
Model consists of 3 parts :

Conceptual schema definition language (CSDL)
:
Declare and define entities, associations, inheritance, ... Entity
classes are generated from this schema.

Store schema definition language (SSDL)
:
Metadata describing the storage container (=database) that persists
data.

Mapping specification language (MSL)
: Maps
the entities in the CSDL file to tables described in the SSDL file.

Entity Client
: EntityClient is an ADO.NET
managed provider that supports accessing data described in an Entity
Data Model. It is similar to SQLClient, OracleClient and others. It
provides several components like EntityCommand, EntityConnection and
EntityTransaction.

Object Services
: This component enables you
to query, insert, update, and delete data, expressed as strongly-typed
CLR objects that are instances of entity types. Object Services
supports both Entity SQL and LINQ to Entities queries.

Entity SQL
(ESQL)
: Entity
SQL is a derivative of Transact-SQL, designed to query and manipulate
entities defined in the Entity Data Model. It supports inheritance and
associations. Both Object Services components and Entity Client
components can execute Entity SQL statements.

LINQ to Entities
: This is a strong-typed
query language for querying against entities defined in the Entity Data
Model.

Please check the MSDN pages about the ADO.NET Entity Framework
for
detailed information about all layers and components. There is also an
interesting Entity Framework FAQ
from Microsoft developer Danny
Simmons.


Installation

Download beta 3 of the ADO.NET Entity Framework from the Microsoft website
and install it. Make sure you
have installed Visual Studio 2008 RTM and the .NET 3.5 framework.


Generate an Entity Data Model

1) Start with a new console application

2) Add a new item. Choose the ADO.NET Entity Model

item. Give it the name NorthwindModel.edmx
.

3) The Entity Data Model Wizard
will be started.
Step 1/3 : Choose Model Contents
. Choose
Generate from database

.



4) Step 2/3 : Choose your data connection
. Select a
connection to the SQL Server Northwind database.

5) Step 3/3 : Choose your database objects
. Now you
can select all tables, views and stored procedures which should be
mapped in your conceptual model.



6) Finish the wizard. The Entity Data Model will be generated. An EDMX
file, which is the equivalent of DBML file in LINQ to SQL, will be
added to your project.


The Entity Data
Model (EDM)


LINQ to SQL Diagram
vs. Entity Data Model

LINQ to SQL Object Relational Diagram



Entity Data Model (EDM)

(Beta 3)



Entity Data Model (EDM)

(SP1)



The Entity Data Model diagram has a lot of similarities with a LINQ
to SQL diagram. An EDM entity is divided into 2 parts : the Scalar
Properties

and the Navigation Properties
. A NavigationProperty references another
EntityType
and it defines the direction of the relationship
(one-to-many, one-to-one, ...).

EDM associations use another visualization and they have other
properties then LINQ to SQL but they actually represent the same.

Update 20/10/2008
: In Visual Studio 2008 SP1 all
properties will be organized by alphabetical order.

LINQ to SQL :
Association




EDM : Association




Names of EntityTypes and
EntitySets

By default, LINQ to SQL changes plural table
names to singular entity class names automatically. The EDM designer
does not do this. So the Northwind table Employees is mapped to an
EntityType called Employees. Be careful because this can lead to
confusion.



So change the name of the EntityType manually :



After changing the name, you will notice that the diagram is being
updated and IntelliSense now correctly shows ObjectQuery<Employee
>
NorthwindEntities.Employees when hovering the Employees EntitySet in a
LINQ to Entities query.



Some simple name convention rules:

EntityType, Name -> single

EntityType, EntitySetName -> plural

NavigationProperty, 0..1, instance -> single

NavigationProperty, *, collection -> plural


Scheme file (EDMX)

If you would open the EDMX
file as XML, than you
will see that this file contains 3 major sections.

ConceptualModels
(CSDL)

StorageModels
(SSDL)

Mapping
(MSL)

<?xml version="1.0"
encoding="utf-8"
?>

<edmx:Edmx Version="1.0"
xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx"
>

<edmx:Runtime>

<!-- CSDL content -->

<edmx:ConceptualModels
>

<Schema Namespace="NorthwindModel"
Alias="Self"
xmlns="http://schemas.microsoft.com/ado/2006/04/edm"
>

<EntityContainer Name="NorthwindEntities"
>

<EntitySet Name="Employees"
EntityType="NorthwindModel.Employee"
/>

<AssociationSet Name="FK_Orders_Employees"
Association="NorthwindModel.FK_Orders_Employees"
>

<End Role="Employees"
EntitySet="Employees"
/>

<End Role="Orders"
EntitySet="Orders"
/>

</AssociationSet>

</EntityContainer>

<EntityType Name="Employee"
>

<Documentation><Summary>Employee entity which corresponds with the Northwind.Employees table</Summary></Documentation>

<Key>

<PropertyRef Name="EmployeeID"
/>

</Key>

<Property Name="EmployeeID"
Type="Int32"
Nullable="false"
/>

<Property Name="LastName"
Type="String"
Nullable="false"
MaxLength="20"
/>

<Property Name="FirstName"
Type="String"
Nullable="false"
MaxLength="10"
/>

<NavigationProperty Name="Orders"
Relationship="NorthwindModel.FK_Orders_Employees"
FromRole="Employees"
ToRole="Orders"
/>

</EntityType>

</Schema>

</edmx:ConceptualModels
>

<!-- SSDL content -->

<edmx:StorageModels
>

<Schema Namespace="NorthwindModel.Store"
Alias="Self"
ProviderManifestToken="09.00.1399"

xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl"
>

<EntityContainer Name="dbo"
>

<EntitySet Name="Employees"
EntityType="NorthwindModel.Store.Employees"
/>

<AssociationSet Name="FK_Orders_Employees"
Association="NorthwindModel.Store.FK_Orders_Employees"
>

<End Role="Employees"
EntitySet="Employees"
/>

<End Role="Orders"
EntitySet="Orders"
/>

</AssociationSet>

</Schema>

</edmx:StorageModels
>

<!-- C-S mapping content -->

<edmx:Mappings
>

<Mapping Space="C-S"
xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS"
>

<EntityContainerMapping StorageEntityContainer="dbo"
CdmEntityContainer="NorthwindEntities"
>

<EntitySetMapping Name="Employees"
>

<EntityTypeMapping TypeName="IsTypeOf(NorthwindModel.Employee)"
>

<MappingFragment StoreEntitySet="Employees"
>

<ScalarProperty Name="EmployeeID"
ColumnName="EmployeeID"
/>

<ScalarProperty Name="LastName"
ColumnName="LastName"
/>

<ScalarProperty Name="FirstName"
ColumnName="FirstName"
/>

</MappingFragment>

</EntityTypeMapping>

</EntitySetMapping>

<AssociationSetMapping Name="FK_Orders_Employees"
TypeName="NorthwindModel.FK_Orders_Employees"
StoreEntitySet="Orders"
>

<EndProperty Name="Employees"
>

<ScalarProperty Name="EmployeeID"
ColumnName="EmployeeID"
/>

</EndProperty>

<EndProperty Name="Orders"
>

<ScalarProperty Name="OrderID"
ColumnName="OrderID"
/>

</EndProperty>

<Condition ColumnName="EmployeeID"
IsNull="false"
/>

</AssociationSetMapping>

</EntityContainerMapping>

</Mapping>

</edmx:Mappings
>

</edmx:Runtime>

</edmx:Edmx>

[/code]
You do not have to modify this XML file manually. The Visual EDM
designer and the Mapping Details and Model Browser windows will combine
these 3 parts together and give you a nice visual representation of the
whole Entity Data Model.

When you build your project, MSBuild will extract the CSDL/SSDL/MSL
content from the EDMX
file and places these 3 seperate
XML files in your project output directory.


Model browser



The Model Browser
window can be
used to visualize the conceptual model and storage model in a
well-organized tree hierarchy.

Conceptual Model

Entity Types : Employee

Associations : FK_Orders_Employees

Entity Container

Entity Sets : Employees

Association Sets

Function Imports

Storage Model

Tables / Views : Employees

Stored Procedures

Constraints


Mapping
details

The EDM designer has also a nice Mapping Details

window. It consists of 2 views.

Map Entity to Tables / View

This view shows all fields in the database and the corresponding
properties in the entity. It can be used to view and edit mappings in
the Entity Data Model.



Map Entity to Functions

This view can be used to select a specialized stored procedure to
insert, update or delete an instance of the entity.




Generated
entity classes

In addition to this XML schema
file, the wizard has also generated entity classes.
Let's take a
closer look at these classes in the .Designer.cs
file
and compare them with the LINQ to SQL classes.

1) LINQ to SQL class vs EDM EntityObject class

// LINQ to SQL

[Table(Name="dbo.Employees"
)]

public
partial
class
Employee
: INotifyPropertyChanging, INotifyPropertyChanged

[/code]
An EDM class uses different attributes and it is always inherited
from EntityObject
or ComplexObject.
The
EntityObject class provides change tracking and relationship
management. Of course this class also inherits from the
INotifyPropertyChanging and INotifyPropertyChanged interfaces so all
entities support two-way binding.

// Entity Data Model

[global
::System.Data.Objects.DataClasses.EdmEntityTypeAttribute
(NamespaceName="NorthwindModel"
, Name="Employee"
)]

[global
::System.Runtime.Serialization.DataContractAttribute
()]

[global
::System.Serializable
()]

public
partial
class
Employee
: global
::System.Data.Objects.DataClasses.EntityObject

[/code]

2) LINQ to SQL entity constructor vs. EDM Create
method


// LINQ to SQL

public
Employee()

{

this
._Employees = new
EntitySet<Employee>(new
Action
<Employee>(this
.attach_Employees), new
Action
<Employee>(this
.detach_Employees));

this
._EmployeeTerritories = new
EntitySet<EmployeeTerritory>(new
Action
<EmployeeTerritory>(this
.attach_EmployeeTerritories),

new
Action
<EmployeeTerritory>(this
.detach_EmployeeTerritories));

this
._Orders = new
EntitySet<Order>(new
Action
<Order>(this
.attach_Orders), new
Action
<Order>(this
.detach_Orders));

this
._Employee1 = default
(EntityRef<Employee>);

OnCreated();

}

[/code]
EDM does not generate a constructor like LINQ to SQL does. Instead it
creates a factory method with input parameters for all required (not
nullable) properties.

// Entity Data Model

public
static
Employee
CreateEmployee(int
employeeID, string
lastName, string
firstName)

{

Employee
employee = new
Employee
();

employee.EmployeeID = employeeID;

employee.LastName = lastName;

employee.FirstName = firstName;

return
employee;

}

[/code]

3) LINQ to SQL vs. EDM : entity property

// LINQ to SQL

[Column(Storage="_EmployeeID"
, AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY"
, IsPrimaryKey=true
, IsDbGenerated=true
)]

public
int
EmployeeID

{

get

{

return
this
._EmployeeID;

}

set

{

if
((this
._EmployeeID != value
))

{

this
.OnEmployeeIDChanging(value
);

this
.SendPropertyChanging();

this
._EmployeeID = value
;

this
.SendPropertyChanged("EmployeeID"
);

this
.OnEmployeeIDChanged();

}

}

}

[/code]
The attributes of a public property are different in EDM but the get
and set accessors are almost the same.

// Entity Data Model

[global
::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute
(EntityKeyProperty=true
, IsNullable=false
)]

[global
::System.Runtime.Serialization.DataMemberAttribute
()]

public
int
EmployeeID

{

get

{

return
this
._EmployeeID;

}

set

{

this
.OnEmployeeIDChanging(value
);

this
.ReportPropertyChanging("EmployeeID"
);

this
._EmployeeID = global
::System.Data.Objects.DataClasses.StructuralObject
.SetValidValue(value
);

this
.ReportPropertyChanged("EmployeeID"
);

this
.OnEmployeeIDChanged();

}

}

[/code]

4) LINQ to SQL Table vs. EDM ObjectQuery

// LINQ to SQL

public
System.Data.Linq.Table<Employee> Employees

{

get

{

return
this
.GetTable<Employee>();

}

}

[/code]
In LINQ to SQL the GetTable method is called to return a collection
of entities. In EDM an Entity SQL query will be executed through a
Object Services component which returns an EntitySet of EntityTypes.

// Entity Data Model

[global
::System.ComponentModel.BrowsableAttribute
(false
)]

public
global
::System.Data.Objects.ObjectQuery
<Employee
> Employees

{

get

{

if
((this
._Employees == null
))

{

this
._Employees = base
.CreateQuery<Employee
>("[Employees]"
);

}

return
this
._Employees;

}

}

private
global
::System.Data.Objects.ObjectQuery
<Employee
> _Employees;

[/code]

5) LINQ to SQL DataContext vs. EDM ObjectContext

// LINQ to SQL

[System.Data.Linq.Mapping.DatabaseAttribute(Name="Northwind"
)]

public
partial
class
NorthwindDataContext
: System.Data.Linq.DataContext

[/code]
EDM has an equivalent of the LINQ to SQL DataContext, namely an ObjectContext
.
The ObjectContext
class is the primary class for
interacting with data as objects that are instances of entity types
defined in the Entity Data Model. An ObjectContext can be used to make a
connection to the database, to retrieve data, to store the persistent
objects and to perform insert, update and delete actions on the
database.

// Entity Data Model

public
partial
class
NorthwindEntities
: global
::System.Data.Objects.ObjectContext

[/code]

The connection string of an ObjectContext refers to the metadata
(CSDL/SSDL/MSL files) and the data source (database connection string).

connectionString="metadata=./NorthwindModel.csdl|./NorthwindModel.ssdl|./NorthwindModel.msl;

provider=System.Data.SqlClient;

provider connection string="

Data Source=SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=True;MultipleActiveResultSets=True""

[/code]


Documentation

EntityTypes, Associations and Properties in the Entity Data Model
have a Documentation
property. This is new compared to
LINQ to SQL.



These documentation properties will update the XML comment of the
generated partial entity classes. This is great because it can be used
to generate code documentation help files with SandCastle.

///

<summary>

///
Employee entity which corresponds with the Northwind.Employees table

///

</summary>

///

<KeyProperties>

///
EmployeeID

///

</KeyProperties>

[global
::System.Data.Objects.DataClasses.EdmEntityTypeAttribute
(NamespaceName="NorthwindModel"
, Name="Employee"
)]

[global
::System.Runtime.Serialization.DataContractAttribute
()]

[global
::System.Serializable
()]

public
partial
class
Employee
: global
::System.Data.Objects.DataClasses.EntityObject

[/code]


Entity SQL

Entity SQL (E-SQL) is a text-based, collection-oriented and
late-bound query language which is influenced by Transact-SQL. It
allows you to create queries on the Entity Data Model. Entity SQL
statements can be executed with both Object Services components and
Entity Client components. It is quite elaborated and some things can
become complicated. In this first article I will only be focusing on
the various query techniques. So only simple queries without complex
conditions, without associations and without aggregates will be
demonstrated.


ObjectQuery<T> queries which
return entity types

This example will show how to execute an Entity SQL query that
returns a collection of instances of one entity type.

1) First create a Northwind ObjectContext
instance.

2) The Entity SQL statements itself are string expressions. In most
cases they will be composed as SELECT-FROM
query
expressions. Use the VALUE
keyword
in
the SELECT clause to indicate that the entity should be flattened to a
row.

3) We will use some Object Services components to execute the query.
So call the CreateQuery<T>()
factory method of
the ObjectContext
. This will create an ObjectQuery
object which represents a query against the store. This query will be
formulated through the Entity SQL statement.

4) The Entity Framework uses deferred loading. So the SQL statement is executed at the point your code
explicitly needs the data.
In this case the query will be
executed in the first loop of the ForEach iteration.

NorthwindEntities
context = new
NorthwindEntities
();

var
sql = "SELECT VALUE emp FROM NorthwindEntities.Employees AS emp"
;

var
query = context.CreateQuery<Employee
>(sql);

foreach
(var
emp in
query)

Console
.WriteLine("{0} {1} {2} {3}"
, emp.EmployeeID, emp.FirstName, emp.LastName, emp.Country);

[/code]
Instead of using the factory method CreateQuery<T>() you can
also create an ObjectQuery
object yourself. The second
parameter is the object context.

NorthwindEntities
context = new
NorthwindEntities
();

var
sql = "NorthwindEntities.Employees"
;

ObjectQuery
<Employee
> query = new
ObjectQuery
<Employee
>(sql, context);

foreach
(var
emp in
query)

Console
.WriteLine("{0} {1} {2} {3}"
, emp.EmployeeID, emp.FirstName, emp.LastName, emp.Country);

[/code]
Let's add a WHERE
clause :

var
sql = "SELECT VALUE emp FROM NorthwindEntities.Employees AS emp "
+

"WHERE emp.Country = 'USA'"
;

var
query = context.CreateQuery<Employee
>(sql);

[/code]


ObjectQuery<T>
queries with parameters

Parameters are variables that are defined outside Entity SQL but in
the query statement you have to define these parameter names with the at
(@) symbol as a prefix. Parameters have to be created as ObjectParameter
objects. They can be added to the ObjectQuery

instance.

So let us add a Country parameter :

var
sql = "SELECT VALUE emp FROM NorthwindEntities.Employees AS emp "
+

"WHERE emp.Country = @country"
;

var
query = context.CreateQuery<Employee
>(sql);

query.Parameters.Add(new
ObjectParameter
("country"
, "USA"
));

[/code]
We can also do the same without using the CreateQuery<T>()
factory method.

var
sql = "SELECT VALUE emp FROM NorthwindEntities.Employees AS emp "
+

"WHERE emp.Country = @country"
;

ObjectQuery
<Employee
> query = new
ObjectQuery
<Employee
>(sql, context);

query.Parameters.Add(new
ObjectParameter
("country"
, "USA"
));

[/code]
ObjectParameter
objects can also be passed to the CreateQuery<T>()
method.

var
sql = "SELECT VALUE emp FROM NorthwindEntities.Employees AS emp "
+

"WHERE emp.Country = @country"
;

var
query = context.CreateQuery<Employee
>(sql, new
ObjectParameter
("country"
, "USA"
));

[/code]

A third alternative is to use the Where
extension
method. Use the keyword it
to refer to the current
query statement.

var
sql = "SELECT VALUE emp FROM NorthwindEntities.Employees AS emp"
;

var
query = context.CreateQuery<Employee
>(sql)

.Where("it.Country = @country"
, new
ObjectParameter
("country"
, "USA"
));

[/code]


ObjectQuery<T> queries
which return primitive types

It is also possible to return a collection of primitive types instead of
entity types. Therefore you have to make sure that the SELECT clause
only returns 1 value. You also have to specify the primitive type in the
CreateQuery
method.

var
sql = "SELECT VALUE emp.EmployeeID FROM NorthwindEntities.Employees AS emp "
+

"WHERE emp.Country = @country"
;

var
query = context.CreateQuery<int
>(sql, new
ObjectParameter
("Country"
, "USA"
));

foreach
(var
id in
query)

Console
.WriteLine("{0}"
, id.ToString());

[/code]
var
sql = "SELECT VALUE emp.Country FROM NorthwindEntities.Employees AS emp "
+

"WHERE emp.EmployeeID = @id"
;

var
query = context.CreateQuery<string
>(sql, new
ObjectParameter
("id"
, 1));

Console
.WriteLine(query.First());

[/code]
Besides using Entity SQL, you can also use a query builder method to
achieve the same result. Entity SQL provides a SelectValue
method which will skip the implicit row construction. Only one item may
be specified in a select value clause.

string
country = context.Employees.SelectValue<string
>("it.Country"
, new
ObjectParameter
("id"
, 1)).First();

Console
.WriteLine(country);

[/code]


ObjectQuery<T> queries
which return anonymous types

It is also possible to do some data shaping and to create
ObjectQuery<T> queries which return anonymous types. Just change
the SELECT clause and use the DbDataRecord
class in the
CreateQuery
method. The DBDataRecord class was
introduced in .NET 1.0 and it provides data binding support for any kind
of enumeration.

var
sql = "SELECT emp.LastName, emp.FirstName "
+

"FROM NorthwindEntities.Employees AS emp "
;

var
query = context.CreateQuery<DbDataRecord
>(sql);

foreach
(var
emp in
query)

Console
.WriteLine("{0} {1}"
, emp[0], emp[1]);

[/code]
var
sql = "SELECT emp.LastName AS FamilyName, emp.FirstName "
+

"FROM NorthwindEntities.Employees AS emp "
;

var
query = context.CreateQuery<DbDataRecord
>(sql);

foreach
(var
emp in
query)

Console
.WriteLine("{0} {1}"
, emp["FamilyName"
], emp["FirstName"
]);

[/code]


EntityCommand queries which
return entity types

Entity SQL can also be executed through EntityClient components. This
needs more plumbing but in some cases it can have advantages.

1) First create an EntityConnection
. I have re-used
the connectionstring of my Northwind data context. Open this connection.

2) Create an EntityCommand
object and pass the
Entity SQL statement and connection to it.

3) Create a DbDataReader
and loop through the
results of the command.

NorthwindEntities
context = new
NorthwindEntities
();

EntityConnection
conn = new
EntityConnection
(context.Connection.ConnectionString);

conn.Open();

var
sql = "SELECT VALUE emp FROM NorthwindEntities.Employees AS emp"
;

EntityCommand
cmd = new
EntityCommand
(sql, conn);

DbDataReader
reader = cmd.ExecuteReader(CommandBehavior
.SequentialAccess);

while
(reader.Read())

{

Console
.WriteLine("{0} {1} {2} {3}"
, reader["EmployeeID"
], reader["LastName"
],

reader["FirstName"
], reader["Country"
]);

}

[/code]
When using a data reader with sequential access you always have to be
careful when accessing data. This should be done in sequential order !

e.g. When you change the order of the members/properties, you will
get an InvalidOperationException
. "Attempt to read
from column ordinal '0' is not valid. With
CommandBehavior.SequentialAccess, you may only read from column ordinal
'2' or greater.
"

Update 20/10/2008
: In Beta 3 all members/properties were
ordered according the order in the database. In SP1 all properties are
organized by alphabetical order. So in this example you should read
Country, EmployeeID, FirstName and LastName.


EntityCommand queries which
return anonymous types

Data shaping with anonymous types can be done with just the same
techniques :

EntityConnection
conn = new
EntityConnection
(context.Connection.ConnectionString);

conn.Open();

var
sql = "SELECT emp.LastName, emp.FirstName "
+

"FROM NorthwindEntities.Employees AS emp"
;

EntityCommand
cmd = new
EntityCommand
(sql, conn);

DbDataReader
reader = cmd.ExecuteReader(CommandBehavior
.SequentialAccess);

while
(reader.Read())

{

Console
.WriteLine("{0} {1}"
, reader["LastName"
], reader["FirstName"
]);

}

[/code]


EntityCommand
queries with parameters

Adding parameters can also be done easily. Add parameter names with
@-prefixes in the Entity SQL string and create EntityParameter
objects. Add them to the EntityCommand
object.

EntityConnection
conn = new
EntityConnection
(context.Connection.ConnectionString);

conn.Open();

var
sql = "SELECT VALUE emp FROM NorthwindEntities.Employees AS emp "
+

"WHERE emp.Country = @country"
;

EntityCommand
cmd = new
EntityCommand
(sql, conn);

EntityParameter
param = new
EntityParameter
("country"
, DbType
.String);

param.Value = "USA"
;

cmd.Parameters.Add(param);

DbDataReader
reader = cmd.ExecuteReader(CommandBehavior
.SequentialAccess);

while
(reader.Read())

{

Console
.WriteLine("{0} {1} {2} {3}"
, reader["EmployeeID"
], reader["LastName"
],

reader["FirstName"
], reader["Country"
]);

}

[/code]


LINQ to Entities

LINQ was introduced in .NET 3.5 and I am still excited about this technology.
I prefer querying with LINQ to
Entities above Entity SQL. LINQ queries do have some restrictions but
they are easier, more natural and in addition they are strong-typed so
IntelliSense can help you creating queries.

LINQ to Entities is almost the same as LINQ to Objects and LINQ to
SQL. So I will just show 2 basic LINQ to Entities queries. Other
examples of LINQ queries can be found in several articles
on my website.


LINQ queries with
parameters

NorthwindEntities
context = new
NorthwindEntities
();

string
country = "USA"
;

var
query = from
e in
context.Employees

where
e.Country == country

select
e;

foreach
(var
emp in
query)

Console
.WriteLine("{0} {1} {2} {3}"
, emp.EmployeeID, emp.FirstName, emp.LastName, emp.Country);

[/code]


LINQ
queries which return anonymous types

NorthwindEntities
context = new
NorthwindEntities
();

var
query = from
e in
context.Employees

select
new
{ e.LastName, e.FirstName };

foreach
(var
emp in
query)

Console
.WriteLine("{0} {1}"
, emp.LastName, emp.FirstName);

[/code]

I hope that this walkthrough provides a good overview of the Entity
Data Model and the various querying techniques that the Entity
Framework provides. In the next parts of my series about the ADO.NET
Entity Framework I will try to cover more advanced Entity SQL query
techniques, viewing SQL statements, eager loading, change tracking,
concurrency, ... So stay tuned. If you have any remarks or suggestions,
please let me know.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: