Query Projections (WCF Data Services)
Projection provides a mechanism in the Open Data Protocol (OData) to reduce the amount of data in the feed returned by a query by specifying that only certain properties of an entity are returned in the response. For more information, see OData: Select System Query Option ($select).
This topic describes how to define a query projection, what the requirements are for entity and non-entity types, making updates to projected results, creating projected types, and lists some projection considerations.
You can add a projection clause to a query either by using the
$select query option in a URI or by using the select clause (Select in Visual Basic) in a LINQ query. Returned entity data can be projected into either entity types or non-entity types on the client. Examples in this topic demonstrate how to use the
select clause in a LINQ query.
Data loss might occur in the data service when you save updates that were made to projected types. For more information, see Projection Considerations.
Entity types must have one or more identity properties that make up the entity key. Entity types are defined on clients in one of the following ways:
When the type has a property named
When the type has a property named type
ID, where type is the name of the type.
By default, when you project query results into a type defined at the client, the properties requested in the projection must exist in the client type. However, when you specify a value of
true for the IgnoreMissingProperties property of the DataServiceContext, properties specified in the projection are not required to occur in the client type.
When you project query results into entity types on the client, the DataServiceContext can track those objects with updates to be sent back to the data service when the SaveChanges method is called. However, updates that are made to data projected into non-entity types on the client cannot be sent back to the data service. This is because without a key to identify the entity instance, the data service cannot update the correct entity in the data source. Non-entity types are not attached to the DataServiceContext.
When one or more properties of an entity type defined in the data service do not occur in the client type into which the entity is projected, inserts of new entities will not contain these missing properties. In this case, updates that are made to existing entities will also not include these missing properties. When a value exists for such a property, the update resets it to the default value for the property, as defined in the data source.
The following example uses an anonymous LINQ query that projects the address-related properties of the
Customers type into a new
CustomerAddress type, which is defined on the client and is attributed as an entity type:
[!CODE [Astoria Northwind Client#SelectCustomerAddressSpecific](../CodeSnippet/VS_Snippets_Misc/astoria northwind client#selectcustomeraddressspecific)]
In this example, the object initializer pattern is used to create a new instance of the
CustmerAddress type instead of calling a constructor. Constructors are not supported when projecting into entity types, but they can be used when projecting into non-entity and anonymous types. Because
CustomerAddress is an entity type, changes can be made and sent back to the data service.
Also, the data from the
Customer type is projected into an instance of the
CustomerAddress entity type instead of an anonymous type. Projection into anonymous types is supported, but the data is read-only because anonymous types are treated as non-entity types.
The MergeOption settings of the DataServiceContext are used for identity resolution during query projection. This means that if an instance of the
Customer type already exists in the DataServiceContext, an instance of
CustomerAddress with the same identity will follow the identity resolution rules set by the MergeOption
The following table describes the behaviors when projecting results into entity and non-entity types:
|Action||Entity Type||Non-Entity Type|
|Creating a new projected instance by using initializers, as in the following example:|
[!CODE [Astoria Northwind Client#ProjectWithInitializer](../CodeSnippet/VS_Snippets_Misc/astoria northwind client#projectwithinitializer)]
|Creating a new projected instance by using constructors, as in the following example:|
[!CODE [Astoria Northwind Client#ProjectWithConstructor](../CodeSnippet/VS_Snippets_Misc/astoria northwind client#projectwithconstructor)]
|A NotSupportedException is raised.||Supported|
|Using projection to transform a property value, as in the following example:|
[!CODE [Astoria Northwind Client#ProjectWithTransform](../CodeSnippet/VS_Snippets_Misc/astoria northwind client#projectwithtransform)]
This transformation is not supported for entity types because it can lead to confusion and potentially overwriting the data in the data source that belongs to another entity.
|A NotSupportedException is raised.||Supported|
The following additional considerations apply when defining a query projection.
When you define custom feeds for the Atom format, you must make sure that all entity properties that have custom mappings defined are included in the projection. When a mapped entity property is not included in the projection, data loss might occur. For more information, see Feed Customization.
When inserts are made to a projected type that does not contain all of the properties of the entity in the data model of the data service, the properties not included in the projection at the client are set to their default values.
When updates are made to a projected type that does not contain all of the properties of the entity in the data model of the data service, existing values not included in the projection on the client will be overwritten with uninitialized default values.
When a projection includes a complex property, the entire complex object must be returned.
Query projections queries on the client are translated to use the
$selectquery option in the request URI. When a query with projection is executed against a previous version of WCF Data Services that does not support the
$selectquery option, an error is returned. This can also happen when the MaxProtocolVersion of the DataServiceBehavior for the data service is set to a value of V1. For more information, see Data Service Versioning.
For more information, see How to: Project Query Results.