Partager via


Reflection Provider (WCF Data Services)

Important

WCF Data Services has been deprecated and will no longer be available for download from the Microsoft Download Center. WCF Data Services supported earlier versions of the Microsoft OData (V1-V3) protocol only and has not been under active development. OData V1-V3 has been superseded by OData V4, which is an industry standard published by OASIS and ratified by ISO. OData V4 is supported through the OData V4 compliant core libraries available at Microsoft.OData.Core. Support documentation is available at OData.Net, and the OData V4 service libraries are available at Microsoft.AspNetCore.OData.

RESTier is the successor to WCF Data Services. RESTier helps you bootstrap a standardized, queryable, HTTP-based REST interface in minutes. Like WCF Data Services before it, Restier provides simple and straightforward ways to shape queries and intercept submissions before and after they hit the database. And like Web API + OData, you still have the flexibility to add your own custom queries and actions with techniques you're already familiar with.

In addition to exposing data from a data model through the Entity Framework, WCF Data Services can expose data that is not strictly defined in an entity-based model. The reflection provider exposes data in classes that return types that implement the IQueryable<T> interface. WCF Data Services uses reflection to infer a data model for these classes and can translate address-based queries against resources into language integrated query (LINQ)-based queries against the exposed IQueryable<T> types.

Note

You can use the AsQueryable method to return an IQueryable<T> interface from any class that implements the IEnumerable<T> interface. This enables most generic collection types to be used as a data source for your data service.

The reflection provider supports type hierarchies. For more information, see How to: Create a Data Service Using the Reflection Provider.

Inferring the Data Model

When you create the data service, the provider infers the data model by using reflection. The following list shows how the reflection provider infers the data model:

  • Entity container - the class that exposes the data as properties that return an IQueryable<T> instance. When you address a reflection-based data model, the entity container represents the root of the service. Only one entity container class is supported for a given namespace.

  • Entity sets - properties that return IQueryable<T> instances are treated as entity sets. Entity sets are addressed directly as resources in the query. Only one property on the entity container can return an IQueryable<T> instance of a given type.

  • Entity types - the type T of the IQueryable<T> that the entity set returns. Classes that are part of an inheritance hierarchy are translated by the reflection provider into an equivalent entity type hierarchy.

  • Entity keys - each data class that is an entity type must have a key property. This property is attributed with the DataServiceKeyAttribute attribute ([DataServiceKeyAttribute]).

    Note

    You should only apply the DataServiceKeyAttribute attribute to a property that can be used to uniquely identify an instance of the entity type. This attribute is ignored when applied to a navigation property.

  • Entity type properties - other than the entity key, the reflection provider treats the accessible, non-indexer properties of a class that is an entity type as follows:

    • If the property returns a primitive type, then the property is assumed to be a property of an entity type.

    • If the property returns a type that is also an entity type, then the property is assumed to be a navigation property that represents the "one" end of a many-to-one or one-to-one relationship.

    • If the property returns an IEnumerable<T> of an entity type, then the property is assumed to be a navigation property that represents the "many" end of a one-to-many or many-to-many relationship.

    • If the return type of the property is a value type, then the property represents a complex type.

Note

Unlike a data model that is based on the entity-relational model, models that are based on the reflection provider do not understand relational data. You should use the Entity Framework to expose relational data through WCF Data Services.

Data Type Mapping

When a data model is inferred from .NET Framework classes, the primitive types in the data model are mapped to .NET Framework data types as follows:

.NET Framework data type Data model type
Byte [] Edm.Binary
Boolean Edm.Boolean
Byte Edm.Byte
DateTime Edm.DateTime
Decimal Edm.Decimal
Double Edm.Double
Guid Edm.Guid
Int16 Edm.Int16
Int32 Edm.Int32
Int64 Edm.Int64
SByte Edm.SByte
Single Edm.Single
String Edm.String

Note

.NET Framework nullable value types are mapped to the same data model types as the corresponding value types that cannot be assigned a null.

Enabling Updates in the Data Model

To allow updates to data that is exposed through this kind of data model, the reflection provider defines an IUpdatable interface. This interface instructs the data service on how to persist updates to the exposed types. To enable updates to resources that are defined by the data model, the entity container class must implement the IUpdatable interface. For an example of an implementation of the IUpdatable interface, see How to: Create a Data Service Using a LINQ to SQL Data Source.

The IUpdatable interface requires that the following members be implemented so that updates can be propagated to the data source by using the reflection provider:

Member Description
AddReferenceToCollection Provides the functionality to add an object to a collection of related objects that are accessed from a navigation property.
ClearChanges Provides the functionality that cancels pending changes to the data.
CreateResource Provides the functionality to create a new resource in the specified container.
DeleteResource Provides the functionality to delete a resource.
GetResource Provides the functionality to retrieve a resource that is identified by a specific query and type name.
GetValue Provides the functionality to return the value of a property of a resource.
RemoveReferenceFromCollection Provides the functionality to remove an object to a collection of related objects accessed from a navigation property.
ResetResource Provides the functionality to update a specified resource.
ResolveResource Provides the functionality to return the resource that is represented by a specific object instance.
SaveChanges Provides the functionality to save all pending changes.
SetReference Provides the functionality to set a related object reference by using a navigation property.
SetValue Provides the functionality to set the value of the property of a resource.

Handling Concurrency

WCF Data Services supports an optimistic concurrency model by enabling you to define a concurrency token for an entity. This concurrency token, which includes one or more properties of the entity, is used by the data service to determine whether a change has occurred in the data that is being requested, updated, or deleted. When token values obtained from the eTag in the request differ from the current values of the entity, an exception is raised by the data service. The ETagAttribute is applied to an entity type to define a concurrency token in the reflection provider. The concurrency token cannot include a key property or a navigation property. For more information, see Updating the Data Service.

Using LINQ to SQL with the Reflection Provider

Because the Entity Framework is natively supported by default, it is the recommended data provider for using relational data with WCF Data Services. However, you can use the reflection provider to use LINQ to SQL classes with a data service. The Table<TEntity> result sets that are returned by methods on the DataContext generated by the LINQ to SQL Object Relational Designer (O/R Designer) implement the IQueryable<T> interface. This enables the reflection provider to access these methods and return entity data from SQL Server by using the generated LINQ to SQL classes. However, because LINQ to SQL does not implement the IUpdatable interface, you need to add a partial class that extends the existing DataContext partial class to add the IUpdatable implementation. For more information, see How to: Create a Data Service Using a LINQ to SQL Data Source.

See also