InternetUnicodeHTMLCSSScalable Vector Graphics (SVG)Extensible Markup Language (xml) ASP.Net TOCASP.NetMiscellaneous FeatureASP.NET ScriptingASP.NET Run-time Object System.IO Namespace ADO.NETADO.NET OverviewSecuring ADO.NETADO.NET Data Type MappingsADO.NET Retrieving and Modifying DataADO.NET Entity Data ModelADO.NET Oracle Draft for Information Only
ContentADO.NET Entity Framework
ADO.NET Entity FrameworkThe docs.microsoft.com/ef/ site is now the main location for the Entity Framework content.The content for this topic is now available on the following page: Introducing Entity Framework. Entity Framework overviewThe Entity Framework is a set of technologies in ADO.NET that support the development of data-oriented software applications. Architects and developers of data-oriented applications have struggled with the need to achieve two very different objectives. They must model the entities, relationships, and logic of the business problems they are solving, and they must also work with the data engines used to store and retrieve the data. The data may span multiple storage systems, each with its own protocols; even applications that work with a single storage system must balance the requirements of the storage system against the requirements of writing efficient and maintainable application code. 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. With the Entity Framework, developers can work at a higher level of abstraction when they deal with data, and can create and maintain data-oriented applications with less code than in traditional 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 starting with version 3.5 SP1 is installed.Give life to modelsA longstanding and common design approach when building an application or service is the division of the application or service into three parts: a domain model, a logical model, and a physical model. The domain 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. Domain 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 models by enabling developers to query entities and relationships in the domain model (called a conceptual model in the Entity Framework) 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.When working with Code First, the conceptual model is mapped to the storage model in code. The Entity Framework can infer the conceptual model based on the object types and additional configurations that you define. The mapping metadata is generated during run time based on a combination of how you defined your domain types and additional configuration information that you provide in code. Entity Framework generates the database as needed based on the metadata. For more information, see Creating and Mapping a Conceptual Model. When working with the Entity Data Model Tools, the conceptual model, the storage model, and the mappings between the two are expressed in XML-based schemas and defined in files that have corresponding name extensions:
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. The Entity Framework uses these model and mapping files to create, read, update, and delete operations against entities and relationships in the conceptual model to equivalent operations in the data source. The Entity Framework even supports mapping entities in the conceptual model to stored procedures in the data source. For more information, see CSDL, SSDL, and MSL Specifications. Map objects to dataObject-oriented programming poses a challenge for interacting with data storage systems. Although the organization of classes frequently mirrors the organization of relational database tables, the fit is not perfect. Multiple normalized tables frequently correspond to a single class, and relationships between classes are often represented differently than relationships between tables are represented. For example, to represent the customer for a sales order, an Order class might use a property that contains a reference to an instance of a Customer class, while an Order table row in a database contains a foreign key column (or set of columns) with a value that corresponds to a primary key value in the Customer table. A Customer class might have a property named Orders that contains a collection of instances of the Order class, while the Customer table in a database has no comparable column. The Entity Framework provides developers with the flexibility to represent relationships in this way, or to more closely model relationships as they are represented in the database. 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. By default, the classes that are generated for a particular conceptual model derive from base classes that provide 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 associations. Developers can also customize the classes that are generated for a conceptual model. For more information, see Working with Objects. Access and change entity dataMore 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. The Entity Framework uses information in the model and mapping files to translate object queries against entity types represented in the conceptual model into data source-specific queries. Query results are materialized into objects that the Entity Framework manages. The Entity Framework provides the following ways to query a conceptual model and return objects:
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 the Entity Framework 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 Data Model Tools can generate a class derived from System.Data.Objects.ObjectContext or System.Data.Entity.DbContext 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. Data providersThe 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 Entity Framework includes an updated SqlClient Data Provider that supports canonical command trees. For more information, see SqlClient for the Entity Framework. Entity data model toolsTogether with the Entity Framework runtime, Visual Studio includes the mapping and modeling tools. For more information, see Modeling and Mapping. Learn moreTo learn more about the Entity Framework, see: Getting Started - Provides information about how to get up and running quickly using the Quickstart, which shows how to create a simple Entity Framework application. Entity Framework Terminology - Defines many of the terms that are introduced by the Entity Data Model and the Entity Framework and that are used in Entity Framework documentation. Entity Framework Resources - Provides links to conceptual topics and links to external topics and resources for building Entity Framework applications. See alsoModeling and MappingIn the Entity Framework, you can define the conceptual model, storage model, and the mapping between the two in the way that best suits your application. The Entity Data Model Tools in Visual Studio allow you to create an .edmx file from a database or a graphical model and then update that file when either the database or model changes. Starting with the Entity Framework 4.1 you can also create a model programmatically using Code First development. There are two different scenarios for Code First development. In both cases, the developer defines a model by coding .NET Framework class definitions, and then optionally specifies additional mapping or configuration by using Data Annotations or the fluent API. For more information, see Creating and Mapping a Conceptual Model. You can also use the EDM Generator, which is included with the .NET Framework. The EdmGen.exe generates the .csdl, .ssdl, and .msl files from an existing data source. You can also manually create the model and mapping content. For more information, see EDM Generator (EdmGen.exe). EDM Generator (EdmGen.exe)EdmGen.exe is a command-line tool used for working with Entity Framework model and mapping files. You can use the EdmGen.exe tool to do the following:
The EdmGen.exe tool is installed in the .NET Framework directory. In many cases, this is located in C:\windows\Microsoft.NET\Framework\v4.0. For 64-bit systems, this is located in C:\windows\Microsoft.NET\Framework64\v4.0. You can also access the EdmGen.exe tool from the Visual Studio command prompt (Click Start, point to All Programs, point to Microsoft Visual Studio 2010, point to Visual Studio Tools, and then click Visual Studio 2010 Command Prompt). SyntaxEdmGen /mode:choice [options] ModeWhen using the EdmGen.exe tool, you must specify one of the following modes.
Options
In This SectionHow to: Use EdmGen.exe to Generate the Model and Mapping Files How to: Use EdmGen.exe to Generate Object-Layer Code How to: Use EdmGen.exe to Validate Model and Mapping Files See alsoHow to: Use EdmGen.exe to Generate the Model and Mapping FilesThis topic shows how to use the EDM Generator (EdmGen.exe) tool to generate the following files based on the School database:
The EdmGen.exe tool uses /mode:FullGeneration to generate the files listed above. For more information about EdmGen.exe commands, see EDM Generator (EdmGen.exe). If you use EdmGen.exe to generate the model and mapping files, you still need to configure your Visual Studio project to use the Entity Framework. For more information, see How to: Manually Configure an Entity Framework Project. Note A conceptual model generated by EdmGen.exe includes all the objects in the database. If you want to generate a conceptual model that includes only specific objects, use the Entity Data Model Wizard. For more information, see How to: Use the Entity Data Model Wizard. To generate the School model for a Visual Basic project using EdmGen.exe
To generate the School model for a C# project using EdmGen.exe
See also
How to: Use EdmGen.exe to Generate Object-Layer CodeThis topic shows how to use the EDM Generator (EdmGen.exe) tool to generate object-layer code based on the .csdl file. To generate object-layer code for the School model for a Visual Basic project using EdmGen.exe
To generate object-layer code for the School model for a C# project using EdmGen.exe
See also
How to: Use EdmGen.exe to Validate Model and Mapping FilesThis topic shows how to use the EDM Generator (EdmGen.exe) tool to validate the model and mapping files. For more information, see Entity Data Model. To validate the School model using EdmGen.exe
See also
How to: Define the Connection StringThis topic shows how to define the connection string that is used when connecting to a conceptual model. This topic is based on the AdventureWorks Sales conceptual model. The AdventureWorks Sales Model is used throughout the task-related topics in the Entity Framework documentation. This topic assumes that you have already configured the Entity Framework and defined the AdventureWorks Sales Model. For more information, see How to: Manually Define the Model and Mapping Files. The procedures in this topic are also included in How to: Manually Configure an Entity Framework Project. Note If you use the Entity Data Model Wizard in a Visual Studio project, it automatically generates an .edmx file and configures the project to use the Entity Framework. For more information, see How to: Use the Entity Data Model Wizard To define the Entity Framework connection string
<connectionStrings> <add name="AdventureWorksEntities" connectionString="metadata=.\AdventureWorks.csdl|.\AdventureWorks.ssdl|.\AdventureWorks.msl; provider=System.Data.SqlClient;provider connection string='Data Source=localhost; Initial Catalog=AdventureWorks;Integrated Security=True;Connection Timeout=60; multipleactiveresultsets=true'" providerName="System.Data.EntityClient" /> </connectionStrings> If your project does not have an application configuration file, you can add one by selecting Add New Item from the Project menu, selecting the General category, selecting Application Configuration File, and then clicking Add. See alsoHow to: Make Model and Mapping Files Embedded ResourcesThe Entity Framework enables you to deploy model and mapping files as embedded resources of an application. The assembly with the embedded model and mapping files must be loaded in the same application domain as the entity connection. For more information, see Connection Strings. By default, the Entity Data Model tools embed the model and mapping files. When you manually define the model and mapping files, use this procedure to ensure that the files are deployed as embedded resources together with an Entity Framework application. Note To maintain embedded resources, you must repeat this procedure whenever the model and mapping files are modified. To embed model and mapping files
ExampleThe following connection string references embedded model and mapping files for the AdventureWorks Sales Model. This connection string is stored in the project's App.config file. See also
Working with Data Definition LanguageStarting with the .NET Framework version 4, the Entity Framework supports data definition language (DDL). This allows you to create or delete a database instance based on the connection string and the metadata of the storage (SSDL) model. The following methods on the ObjectContext use the connection string and the SSDL content to accomplish the following: create or delete the database, check whether the database exists, and view the generated DDL script: Note Executing the DDL commands assumes sufficient permissions. The methods previously listed delegate most of the work to the underlying ADO.NET data provider. It is the provider’s responsibility to ensure that the naming convention used to generate database objects is consistent with conventions used for querying and updates. The following example shows you how to generate the database based on the existing model. It also adds a new entity object to the object context and then saves it to the database. ProceduresTo define a database based on the existing model
// Initialize the connection string. String connectionString = "metadata=res://*/School.csdl|res://*/School.ssdl|res://*/School.msl;provider=System.Data.SqlClient;" + "provider connection string=\"Data Source=.;Initial Catalog=School;Integrated Security=True;MultipleActiveResultSets=True\""; using (SchoolEntities context = new SchoolEntities(connectionString)) { try { if (context.DatabaseExists()) { // Make sure the database instance is closed. context.DeleteDatabase(); } // View the database creation script. Console.WriteLine(context.CreateDatabaseScript()); // Create the new database instance based on the storage (SSDL) section // of the .edmx file. context.CreateDatabase(); // The following code adds a new objects to the context // and saves the changes to the database. Department dpt = new Department { Name = "Engineering", Budget = 350000.00M, StartDate = DateTime.Now }; context.Departments.AddObject(dpt); // An entity has a temporary key // until it is saved to the database. Console.WriteLine(dpt.EntityKey.IsTemporary); context.SaveChanges(); // The object was saved and the key // is not temporary any more. Console.WriteLine(dpt.EntityKey.IsTemporary); } catch (InvalidOperationException ex) { Console.WriteLine(ex.InnerException.Message); } catch (NotSupportedException ex) { Console.WriteLine(ex.InnerException.Message); } } Querying a Conceptual ModelThe ADO.NET Entity Framework enables you to query a conceptual model. To query the conceptual model using the latest version of the Entity Framework, see Querying Data. Querying Data[This page is specific to the latest version of the Entity Framework. The latest version is available as the 'Entity Framework' NuGet package. For more information, see Entity Framework Releases and Versioning.] The msdn.com/data/ef is now the main location for the Entity Framework content. The content for the Querying Data topic is now available on the following pages. Querying and Finding EntitiesThis topic covers the various ways you can query for data using Entity Framework, including LINQ and the Find method. The techniques shown in this topic apply equally to models created with Code First and the EF Designer. Finding entities using a queryDbSet and IDbSet implement IQueryable and so can be used as the starting point for writing a LINQ query against the database. This is not the appropriate place for an in-depth discussion of LINQ, but here are a couple of simple examples: using (var context = new BloggingContext()) { // Query for all blogs with names starting with B var blogs = from b in context.Blogs where b.Name.StartsWith("B") select b; // Query for the Blog named ADO.NET Blog var blog = context.Blogs .Where(b => b.Name == "ADO.NET Blog") .FirstOrDefault(); } Note that DbSet and IDbSet always create queries against the database and will always involve a round trip to the database even if the entities returned already exist in the context. A query is executed against the database when:
When results are returned from the database, objects that do not exist in the context are attached to the context. If an object is already in the context, the existing object is returned (the current and original values of the object's properties in the entry are not overwritten with database values). When you perform a query, entities that have been added to the context but have not yet been saved to the database are not returned as part of the result set. To get the data that is in the context, see Local Data. If a query returns no rows from the database, the result will be an empty collection, rather than null. Finding entities using primary keysThe Find method on DbSet uses the primary key value to attempt to find an entity tracked by the context. If the entity is not found in the context then a query will be sent to the database to find the entity there. Null is returned if the entity is not found in the context or in the database. Find is different from using a query in two significant ways:
Finding an entity by primary keyThe following code shows some uses of Find: using (var context = new BloggingContext()) { // Will hit the database var blog = context.Blogs.Find(3); // Will return the same instance without hitting the database var blogAgain = context.Blogs.Find(3); context.Blogs.Add(new Blog { Id = -1 }); // Will find the new blog even though it does not exist in the database var newBlog = context.Blogs.Find(-1); // Will find a User which has a string primary key var user = context.Users.Find("johndoe1987"); } Finding an entity by composite primary keyEntity Framework allows your entities to have composite keys - that's a key that is made up of more than one property. For example, you could have a BlogSettings entity that represents a users settings for a particular blog. Because a user would only ever have one BlogSettings for each blog you could chose to make the primary key of BlogSettings a combination of BlogId and Username. The following code attempts to find the BlogSettings with BlogId = 3 and Username = "johndoe1987": using (var context = new BloggingContext()) { var settings = context.BlogSettings.Find(3, "johndoe1987"); } Note that when you have composite keys you need to use ColumnAttribute or the fluent API to specify an ordering for the properties of the composite key. The call to Find must use this order when specifying the values that form the key. Loading Related EntitiesEntity Framework supports three ways to load related data - eager loading, lazy loading and explicit loading. The techniques shown in this topic apply equally to models created with Code First and the EF Designer. Eagerly LoadingEager loading is the process whereby a query for one type of entity also loads related entities as part of the query. Eager loading is achieved by use of the Include method. For example, the queries below will load blogs and all the posts related to each blog. using (var context = new BloggingContext()) { // Load all blogs and related posts var blogs1 = context.Blogs .Include(b => b.Posts) .ToList(); // Load one blogs and its related posts var blog1 = context.Blogs .Where(b => b.Name == "ADO.NET Blog") .Include(b => b.Posts) .FirstOrDefault(); // Load all blogs and related posts // using a string to specify the relationship var blogs2 = context.Blogs .Include("Posts") .ToList(); // Load one blog and its related posts // using a string to specify the relationship var blog2 = context.Blogs .Where(b => b.Name == "ADO.NET Blog") .Include("Posts") .FirstOrDefault(); } Note that Include is an extension method in the System.Data.Entity namespace so make sure you are using that namespace. Eagerly loading multiple levelsIt is also possible to eagerly load multiple levels of related entities. The queries below show examples of how to do this for both collection and reference navigation properties. using (var context = new BloggingContext()) { // Load all blogs, all related posts, and all related comments var blogs1 = context.Blogs .Include(b => b.Posts.Select(p => p.Comments)) .ToList(); // Load all users, their related profiles, and related avatar var users1 = context.Users .Include(u => u.Profile.Avatar) .ToList(); // Load all blogs, all related posts, and all related comments // using a string to specify the relationships var blogs2 = context.Blogs .Include("Posts.Comments") .ToList(); // Load all users, their related profiles, and related avatar // using a string to specify the relationships var users2 = context.Users .Include("Profile.Avatar") .ToList(); } Note that it is not currently possible to filter which related entities are loaded. Include will always bring in all related entities. Lazy LoadingLazy loading is the process whereby an entity or collection of entities is automatically loaded from the database the first time that a property referring to the entity/entities is accessed. When using POCO entity types, lazy loading is achieved by creating instances of derived proxy types and then overriding virtual properties to add the loading hook. For example, when using the Blog entity class defined below, the related Posts will be loaded the first time the Posts navigation property is accessed: public class Blog { public int BlogId { get; set; } public string Name { get; set; } public string Url { get; set; } public string Tags { get; set; } public virtual ICollection<Post> Posts { get; set; } } Turn lazy loading off for serializationLazy loading and serialization don’t mix well, and if you aren’t careful you can end up querying for your entire database just because lazy loading is enabled. Most serializers work by accessing each property on an instance of a type. Property access triggers lazy loading, so more entities get serialized. On those entities properties are accessed, and even more entities are loaded. It’s a good practice to turn lazy loading off before you serialize an entity. The following sections show how to do this. Turning off lazy loading for specific navigation propertiesLazy loading of the Posts collection can be turned off by making the Posts property non-virtual: public class Blog { public int BlogId { get; set; } public string Name { get; set; } public string Url { get; set; } public string Tags { get; set; } public ICollection<Post> Posts { get; set; } } Loading of the Posts collection can still be achieved using eager loading (see Eagerly Loading above) or the Load method (see Explicitly Loading below). Turn off lazy loading for all entitiesLazy loading can be turned off for all entities in the context by setting a flag on the Configuration property. For example: public class BloggingContext : DbContext { public BloggingContext() { this.Configuration.LazyLoadingEnabled = false; } } Loading of related entities can still be achieved using eager loading (see Eagerly Loading above) or the Load method (see Explicitly Loading below). Explicitly LoadingEven with lazy loading disabled it is still possible to lazily load related entities, but it must be done with an explicit call. To do so you use the Load method on the related entity’s entry. For example: using (var context = new BloggingContext()) { var post = context.Posts.Find(2); // Load the blog related to a given post context.Entry(post).Reference(p => p.Blog).Load(); // Load the blog related to a given post using a string context.Entry(post).Reference("Blog").Load(); var blog = context.Blogs.Find(1); // Load the posts related to a given blog context.Entry(blog).Collection(p => p.Posts).Load(); // Load the posts related to a given blog // using a string to specify the relationship context.Entry(blog).Collection("Posts").Load(); } Note that the Reference method should be used when an entity has a navigation property to another single entity. On the other hand, the Collection method should be used when an entity has a navigation property to a collection of other entities. Applying filters when explicitly loading related entitiesThe Query method provides access to the underlying query that Entity Framework will use when loading related entities. You can then use LINQ to apply filters to the query before executing it with a call to a LINQ extension method such as ToList, Load, etc. The Query method can be used with both reference and collection navigation properties but is most useful for collections where it can be used to load only part of the collection. For example: using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); // Load the posts with the 'entity-framework' tag related to a given blog context.Entry(blog) .Collection(b => b.Posts) .Query() .Where(p => p.Tags.Contains("entity-framework")) .Load(); // Load the posts with the 'entity-framework' tag related to a given blog // using a string to specify the relationship context.Entry(blog) .Collection("Posts") .Query() .Where(p => p.Tags.Contains("entity-framework")) .Load(); } When using the Query method it is usually best to turn off lazy loading for the navigation property. This is because otherwise the entire collection may get loaded automatically by the lazy loading mechanism either before or after the filtered query has been executed. Note that while the relationship can be specified as a string instead of a lambda expression, the returned IQueryable is not generic when a string is used and so the Cast method is usually needed before anything useful can be done with it. Using Query to count related entities without loading themSometimes it is useful to know how many entities are related to another entity in the database without actually incurring the cost of loading all those entities. The Query method with the LINQ Count method can be used to do this. For example: using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); // Count how many posts the blog has var postCount = context.Entry(blog) .Collection(b => b.Posts) .Query() .Count(); } No-Tracking QueriesSometimes you may want to get entities back from a query but not have those entities be tracked by the context. This may result in better performance when querying for large numbers of entities in read-only scenarios. The techniques shown in this topic apply equally to models created with Code First and the EF Designer. A new extension method AsNoTracking allows any query to be run in this way. For example: using (var context = new BloggingContext()) { // Query for all blogs without tracking them var blogs1 = context.Blogs.AsNoTracking(); // Query for some blogs without tracking them var blogs2 = context.Blogs .Where(b => b.Name.Contains(".NET")) .AsNoTracking() .ToList(); } Raw SQL QueriesEntity Framework allows you to query using LINQ with your entity classes. However, there may be times that you want to run queries using raw SQL directly against the database. This includes calling stored procedures, which can be helpful for Code First models that currently do not support mapping to stored procedures. The techniques shown in this topic apply equally to models created with Code First and the EF Designer. Writing SQL queries for entitiesThe SqlQuery method on DbSet allows a raw SQL query to be written that will return entity instances. The returned objects will be tracked by the context just as they would be if they were returned by a LINQ query. For example: using (var context = new BloggingContext()) { var blogs = context.Blogs.SqlQuery("SELECT * FROM dbo.Blogs").ToList(); } Note that, just as for LINQ queries, the query is not executed until the results are enumerated—in the example above this is done with the call to ToList. Care should be taken whenever raw SQL queries are written for two reasons. First, the query should be written to ensure that it only returns entities that are really of the requested type. For example, when using features such as inheritance it is easy to write a query that will create entities that are of the wrong CLR type. Second, some types of raw SQL query expose potential security risks, especially around SQL injection attacks. Make sure that you use parameters in your query in the correct way to guard against such attacks. Loading entities from stored proceduresYou can use DbSet.SqlQuery to load entities from the results of a stored procedure. For example, the following code calls the dbo.GetBlogs procedure in the database: using (var context = new BloggingContext()) { var blogs = context.Blogs.SqlQuery("dbo.GetBlogs").ToList(); } You can also pass parameters to a stored procedure using the following syntax: using (var context = new BloggingContext()) { var blogId = 1; var blogs = context.Blogs.SqlQuery("dbo.GetBlogById @p0", blogId).Single(); } Writing SQL queries for non-entity typesA SQL query returning instances of any type, including primitive types, can be created using the SqlQuery method on the Database class. For example: using (var context = new BloggingContext()) { var blogNames = context.Database.SqlQuery<string>( "SELECT Name FROM dbo.Blogs").ToList(); } The results returned from SqlQuery on Database will never be tracked by the context even if the objects are instances of an entity type. Sending raw commands to the databaseNon-query commands can be sent to the database using the ExecuteSqlCommand method on Database. For example: using (var context = new BloggingContext()) { context.Database.ExecuteSqlCommand( "UPDATE dbo.Blogs SET Name = 'Another Name' WHERE BlogId = 1"); } Note that any changes made to data in the database using ExecuteSqlCommand are opaque to the context until entities are loaded or reloaded from the database. Output ParametersIf output parameters are used, their values will not be available until the results have been read completely. This is due to the underlying behavior of DbDataReader, see Retrieving Data Using a DataReader for more details. Working with ObjectsThe Entity Framework enables you to query, insert, update, and delete data, which is expressed as typed common language runtime (CLR) objects that are instances of entity types. The entity types represent the entities defined in the conceptual model. The Entity Framework maps entities and relationships that are defined in a conceptual model to a data source. The Entity Framework provides facilities to do the following: materialize data returned from the data source as objects; track changes that were made to the objects; handle concurrency; propagate object changes back to the data source; and bind objects to controls. For more information about working with objects in the latest version of the Entity Framework see, Working with Objects. Working with Objects (Entity Framework)[This page is specific to the latest version of the Entity Framework. The latest version is available as the 'Entity Framework' NuGet package. For more information, see Entity Framework Releases and Versioning.] The msdn.com/data/ef is now the main location for the Entity Framework content. The content for the Working with Object topic is now available on the following pages. Optimistic Concurrency Patterns Working with DbContextIn order to use Entity Framework to query, insert, update, and delete data using .NET objects, you first need to Create a Model which maps the entities and relationships that are defined in your model to tables in a database. Once you have a model, the primary class your application interacts with is System.Data.Entity.DbContext (often referred to as the context class). You can use a DbContext associated to a model to:
This page gives some guidance on how to manage the context class. Defining a DbContext derived classThe recommended way to work with context is to define a class that derives from DbContext and exposes DbSet properties that represent collections of the specified entities in the context. If you are working with the EF Designer, the context will be generated for you. If you are working with Code First, you will typically write the context yourself. public class ProductContext : DbContext { public DbSet<Category> Categories { get; set; } public DbSet<Product> Products { get; set; } } Once you have a context, you would query for, add (using Add or Attach methods ) or remove (using Remove) entities in the context through these properties. Accessing a DbSet property on a context object represent a starting query that returns all entities of the specified type. Note that just accessing a property will not execute the query. A query is executed when:
LifetimeThe lifetime of the context begins when the instance is created and ends when the instance is either disposed or garbage-collected. Use using if you want all the resources that the context controls to be disposed at the end of the block. When you use using, the compiler automatically creates a try/finally block and calls dispose in the finally block. public void UseProducts() { using (var context = new ProductContext()) { // Perform data access using the context } } Here are some general guidelines when deciding on the lifetime of the context:
ConnectionsBy default, the context manages connections to the database. The context opens and closes connections as needed. For example, the context opens a connection to execute a query, and then closes the connection when all the result sets have been processed. There are cases when you want to have more control over when the connection opens and closes. For example, when working with SQL Server Compact, it is often recommended to maintain a separate open connection to the database for the lifetime of the application to improve performance. You can manage this process manually by using the Connection property. Working with proxiesWhen creating instances of POCO entity types, Entity Framework often creates instances of a dynamically generated derived type that acts as a proxy for the entity. This proxy overrides some virtual properties of the entity to insert hooks for performing actions automatically when the property is accessed. For example, this mechanism is used to support lazy loading of relationships. The techniques shown in this topic apply equally to models created with Code First and the EF Designer. Disabling proxy creationSometimes it is useful to prevent Entity Framework from creating proxy instances. For example, serializing non-proxy instances is considerably easier than serializing proxy instances. Proxy creation can be turned off by clearing the ProxyCreationEnabled flag. One place you could do this is in the constructor of your context. For example: public class BloggingContext : DbContext { public BloggingContext() { this.Configuration.ProxyCreationEnabled = false; } public DbSet<Blog> Blogs { get; set; } public DbSet<Post> Posts { get; set; } } Note that the EF will not create proxies for types where there is nothing for the proxy to do. This means that you can also avoid proxies by having types that are sealed and/or have no virtual properties. Explicitly creating an instance of a proxyA proxy instance will not be created if you create an instance of an entity using the new operator. This may not be a problem, but if you need to create a proxy instance (for example, so that lazy loading or proxy change tracking will work) then you can do so using the Create method of DbSet. For example: using (var context = new BloggingContext()) { var blog = context.Blogs.Create(); } The generic version of Create can be used if you want to create an instance of a derived entity type. For example: using (var context = new BloggingContext()) { var admin = context.Users.Create<Administrator>(); } Note that the Create method does not add or attach the created entity to the context. Note that the Create method will just create an instance of the entity type itself if creating a proxy type for the entity would have no value because it would not do anything. For example, if the entity type is sealed and/or has no virtual properties then Create will just create an instance of the entity type. Getting the actual entity type from a proxy typeProxy types have names that look something like this: System.Data.Entity.DynamicProxies.Blog_5E43C6C196972BF0754973E48C9C941092D86818CD94005E9A759B70BF6E48E6 You can find the entity type for this proxy type using the GetObjectType method from ObjectContext. For example: using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); var entityType = ObjectContext.GetObjectType(blog.GetType()); } Note that if the type passed to GetObjectType is an instance of an entity type that is not a proxy type then the type of entity is still returned. This means you can always use this method to get the actual entity type without any other checking to see if the type is a proxy type or not. Working with entity statesThis topic will cover how to add and attach entities to a context and how Entity Framework processes these during SaveChanges. Entity Framework takes care of tracking the state of entities while they are connected to a context, but in disconnected or N-Tier scenarios you can let EF know what state your entities should be in. The techniques shown in this topic apply equally to models created with Code First and the EF Designer. Entity states and SaveChangesAn entity can be in one of five states as defined by the EntityState enumeration. These states are:
SaveChanges does different things for entities in different states:
The following examples show ways in which the state of an entity or an entity graph can be changed. Adding a new entity to the contextA new entity can be added to the context by calling the Add method on DbSet. This puts the entity into the Added state, meaning that it will be inserted into the database the next time that SaveChanges is called. For example: using (var context = new BloggingContext()) { var blog = new Blog { Name = "ADO.NET Blog" }; context.Blogs.Add(blog); context.SaveChanges(); } Another way to add a new entity to the context is to change its state to Added. For example: using (var context = new BloggingContext()) { var blog = new Blog { Name = "ADO.NET Blog" }; context.Entry(blog).State = EntityState.Added; context.SaveChanges(); } Finally, you can add a new entity to the context by hooking it up to another entity that is already being tracked. This could be by adding the new entity to the collection navigation property of another entity or by setting a reference navigation property of another entity to point to the new entity. For example: using (var context = new BloggingContext()) { // Add a new User by setting a reference from a tracked Blog var blog = context.Blogs.Find(1); blog.Owner = new User { UserName = "johndoe1987" }; // Add a new Post by adding to the collection of a tracked Blog blog.Posts.Add(new Post { Name = "How to Add Entities" }); context.SaveChanges(); } Note that for all of these examples if the entity being added has references to other entities that are not yet tracked then these new entities will also be added to the context and will be inserted into the database the next time that SaveChanges is called. Attaching an existing entity to the contextIf you have an entity that you know already exists in the database but which is not currently being tracked by the context then you can tell the context to track the entity using the Attach method on DbSet. The entity will be in the Unchanged state in the context. For example: var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" }; using (var context = new BloggingContext()) { context.Blogs.Attach(existingBlog); // Do some more work... context.SaveChanges(); } Note that no changes will be made to the database if SaveChanges is called without doing any other manipulation of the attached entity. This is because the entity is in the Unchanged state. Another way to attach an existing entity to the context is to change its state to Unchanged. For example: var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" }; using (var context = new BloggingContext()) { context.Entry(existingBlog).State = EntityState.Unchanged; // Do some more work... context.SaveChanges(); } Note that for both of these examples if the entity being attached has references to other entities that are not yet tracked then these new entities will also attached to the context in the Unchanged state. Attaching an existing but modified entity to the contextIf you have an entity that you know already exists in the database but to which changes may have been made then you can tell the context to attach the entity and set its state to Modified. For example: var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" }; using (var context = new BloggingContext()) { context.Entry(existingBlog).State = EntityState.Modified; // Do some more work... context.SaveChanges(); } When you change the state to Modified all the properties of the entity will be marked as modified and all the property values will be sent to the database when SaveChanges is called. Note that if the entity being attached has references to other entities that are not yet tracked, then these new entities will attached to the context in the Unchanged state—they will not automatically be made Modified. If you have multiple entities that need to be marked Modified you should set the state for each of these entities individually. Changing the state of a tracked entityYou can change the state of an entity that is already being tracked by setting the State property on its entry. For example: var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" }; using (var context = new BloggingContext()) { context.Blogs.Attach(existingBlog); context.Entry(existingBlog).State = EntityState.Unchanged; // Do some more work... context.SaveChanges(); } Note that calling Add or Attach for an entity that is already tracked can also be used to change the entity state. For example, calling Attach for an entity that is currently in the Added state will change its state to Unchanged. Insert or update patternA common pattern for some applications is to either Add an entity as new (resulting in a database insert) or Attach an entity as existing and mark it as modified (resulting in a database update) depending on the value of the primary key. For example, when using database generated integer primary keys it is common to treat an entity with a zero key as new and an entity with a non-zero key as existing. This pattern can be achieved by setting the entity state based on a check of the primary key value. For example: public void InsertOrUpdate(Blog blog) { using (var context = new BloggingContext()) { context.Entry(blog).State = blog.BlogId == 0 ? EntityState.Added : EntityState.Modified; context.SaveChanges(); } } Note that when you change the state to Modified all the properties of the entity will be marked as modified and all the property values will be sent to the database when SaveChanges is called. Working with property valuesFor the most part Entity Framework will take care of tracking the state, original values, and current values of the properties of your entity instances. However, there may be some cases - such as disconnected scenarios - where you want to view or manipulate the information EF has about the properties. The techniques shown in this topic apply equally to models created with Code First and the EF Designer. Entity Framework keeps track of two values for each property of a tracked entity. The current value is, as the name indicates, the current value of the property in the entity. The original value is the value that the property had when the entity was queried from the database or attached to the context. There are two general mechanisms for working with property values:
The sections below show examples of using both of the above mechanisms. Getting and setting the current or original value of an individual propertyThe example below shows how the current value of a property can be read and then set to a new value: using (var context = new BloggingContext()) { var blog = context.Blogs.Find(3); // Read the current value of the Name property string currentName1 = context.Entry(blog).Property(u => u.Name).CurrentValue; // Set the Name property to a new value context.Entry(blog).Property(u => u.Name).CurrentValue = "My Fancy Blog"; // Read the current value of the Name property using a string for the property name object currentName2 = context.Entry(blog).Property("Name").CurrentValue; // Set the Name property to a new value using a string for the property name context.Entry(blog).Property("Name").CurrentValue = "My Boring Blog"; } Use the OriginalValue property instead of the CurrentValue property to read or set the original value. Note that the returned value is typed as “object” when a string is used to specify the property name. On the other hand, the returned value is strongly typed if a lambda expression is used. Setting the property value like this will only mark the property as modified if the new value is different from the old value. When a property value is set in this way the change is automatically detected even if AutoDetectChanges is turned off. Getting and setting the current value of an unmapped propertyThe current value of a property that is not mapped to the database can also be read. An example of an unmapped property could be an RssLink property on Blog. This value may be calculated based on the BlogId, and therefore doesn't need to be stored in the database. For example: using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); // Read the current value of an unmapped property var rssLink = context.Entry(blog).Property(p => p.RssLink).CurrentValue; // Use a string to specify the property name var rssLinkAgain = context.Entry(blog).Property("RssLink").CurrentValue; } The current value can also be set if the property exposes a setter. Reading the values of unmapped properties is useful when performing Entity Framework validation of unmapped properties. For the same reason current values can be read and set for properties of entities that are not currently being tracked by the context. For example: using (var context = new BloggingContext()) { // Create an entity that is not being tracked var blog = new Blog { Name = "ADO.NET Blog" }; // Read and set the current value of Name as before var currentName1 = context.Entry(blog).Property(u => u.Name).CurrentValue; context.Entry(blog).Property(u => u.Name).CurrentValue = "My Fancy Blog"; var currentName2 = context.Entry(blog).Property("Name").CurrentValue; context.Entry(blog).Property("Name").CurrentValue = "My Boring Blog"; } Note that original values are not available for unmapped properties or for properties of entities that are not being tracked by the context. Checking whether a property is marked as modifiedThe example below shows how to check whether or not an individual property is marked as modified: using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); var nameIsModified1 = context.Entry(blog).Property(u => u.Name).IsModified; // Use a string for the property name var nameIsModified2 = context.Entry(blog).Property("Name").IsModified; } The values of modified properties are sent as updates to the database when SaveChanges is called. Marking a property as modifiedThe example below shows how to force an individual property to be marked as modified: using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); context.Entry(blog).Property(u => u.Name).IsModified = true; // Use a string for the property name context.Entry(blog).Property("Name").IsModified = true; } Marking a property as modified forces an update to be send to the database for the property when SaveChanges is called even if the current value of the property is the same as its original value. It is not currently possible to reset an individual property to be not modified after it has been marked as modified. This is something we plan to support in a future release. Reading current, original, and database values for all properties of an entityThe example below shows how to read the current values, the original values, and the values actually in the database for all mapped properties of an entity. using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); // Make a modification to Name in the tracked entity blog.Name = "My Cool Blog"; // Make a modification to Name in the database context.Database.SqlCommand("update dbo.Blogs set Name = 'My Boring Blog' where Id = 1"); // Print out current, original, and database values Console.WriteLine("Current values:"); PrintValues(context.Entry(blog).CurrentValues); Console.WriteLine("\nOriginal values:"); PrintValues(context.Entry(blog).OriginalValues); Console.WriteLine("\nDatabase values:"); PrintValues(context.Entry(blog).GetDatabaseValues()); } public static void PrintValues(DbPropertyValues values) { foreach (var propertyName in values.PropertyNames) { Console.WriteLine("Property {0} has value {1}", propertyName, values[propertyName]); } } The current values are the values that the properties of the entity currently contain. The original values are the values that were read from the database when the entity was queried. The database values are the values as they are currently stored in the database. Getting the database values is useful when the values in the database may have changed since the entity was queried such as when a concurrent edit to the database has been made by another user. Setting current or original values from another objectThe current or original values of a tracked entity can be updated by copying values from another object. For example: using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); var coolBlog = new Blog { Id = 1, Name = "My Cool Blog" }; var boringBlog = new BlogDto { Id = 1, Name = "My Boring Blog" }; // Change the current and original values by copying the values from other objects var entry = context.Entry(blog); entry.CurrentValues.SetValues(coolBlog); entry.OriginalValues.SetValues(boringBlog); // Print out current and original values Console.WriteLine("Current values:"); PrintValues(entry.CurrentValues); Console.WriteLine("\nOriginal values:"); PrintValues(entry.OriginalValues); } public class BlogDto { public int Id { get; set; } public string Name { get; set; } } Running the code above will print out: Current values: Property Id has value 1 Property Name has value My Cool Blog Original values: Property Id has value 1 Property Name has value My Boring Blog This technique is sometimes used when updating an entity with values obtained from a service call or a client in an n-tier application. Note that the object used does not have to be of the same type as the entity so long as it has properties whose names match those of the entity. In the example above, an instance of BlogDTO is used to update the original values. Note that only properties that are set to different values when copied from the other object will be marked as modified. Setting current or original values from a dictionaryThe current or original values of a tracked entity can be updated by copying values from a dictionary or some other data structure. For example: using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); var newValues = new Dictionary\<string, object> { { "Name", "The New ADO.NET Blog" }, { "Url", "blogs.msdn.com/adonet" }, }; var currentValues = context.Entry(blog).CurrentValues; foreach (var propertyName in newValues.Keys) { currentValues[propertyName] = newValues[propertyName]; } PrintValues(currentValues); } Use the OriginalValues property instead of the CurrentValues property to set original values. Setting current or original values from a dictionary using PropertyAn alternative to using CurrentValues or OriginalValues as shown above is to use the Property method to set the value of each property. This can be preferable when you need to set the values of complex properties. For example: using (var context = new BloggingContext()) { var user = context.Users.Find("johndoe1987"); var newValues = new Dictionary\<string, object> { { "Name", "John Doe" }, { "Location.City", "Redmond" }, { "Location.State.Name", "Washington" }, { "Location.State.Code", "WA" }, }; var entry = context.Entry(user); foreach (var propertyName in newValues.Keys) { entry.Property(propertyName).CurrentValue = newValues[propertyName]; } } In the example above complex properties are accessed using dotted names. For other ways to access complex properties see the two sections later in this topic specifically about complex properties. Creating a cloned object containing current, original, or database valuesThe DbPropertyValues object returned from CurrentValues, OriginalValues, or GetDatabaseValues can be used to create a clone of the entity. This clone will contain the property values from the DbPropertyValues object used to create it. For example: using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); var clonedBlog = context.Entry(blog).GetDatabaseValues().ToObject(); } Note that the object returned is not the entity and is not being tracked by the context. The returned object also does not have any relationships set to other objects. The cloned object can be useful for resolving issues related to concurrent updates to the database, especially where a UI that involves data binding to objects of a certain type is being used. Getting and setting the current or original values of complex propertiesThe value of an entire complex object can be read and set using the Property method just as it can be for a primitive property. In addition you can drill down into the complex object and read or set properties of that object, or even a nested object. Here are some examples: using (var context = new BloggingContext()) { var user = context.Users.Find("johndoe1987"); // Get the Location complex object var location = context.Entry(user) .Property(u => u.Location) .CurrentValue; // Get the nested State complex object using chained calls var state1 = context.Entry(user) .ComplexProperty(u => u.Location) .Property(l => l.State) .CurrentValue; // Get the nested State complex object using a single lambda expression var state2 = context.Entry(user) .Property(u => u.Location.State) .CurrentValue; // Get the nested State complex object using a dotted string var state3 = context.Entry(user) .Property("Location.State") .CurrentValue; // Get the value of the Name property on the nested State complex object using chained calls var name1 = context.Entry(user) .ComplexProperty(u => u.Location) .ComplexProperty(l => l.State) .Property(s => s.Name) .CurrentValue; // Get the value of the Name property on the nested State complex object using a single lambda expression var name2 = context.Entry(user) .Property(u => u.Location.State.Name) .CurrentValue; // Get the value of the Name property on the nested State complex object using a dotted string var name3 = context.Entry(user) .Property("Location.State.Name") .CurrentValue; } Use the OriginalValue property instead of the CurrentValue property to get or set an original value. Note that either the Property or the ComplexProperty method can be used to access a complex property. However, the ComplexProperty method must be used if you wish to drill down into the complex object with additional Property or ComplexProperty calls. Using DbPropertyValues to access complex propertiesWhen you use CurrentValues, OriginalValues, or GetDatabaseValues to get all the current, original, or database values for an entity, the values of any complex properties are returned as nested DbPropertyValues objects. These nested objects can then be used to get values of the complex object. For example, the following method will print out the values of all properties, including values of any complex properties and nested complex properties. public static void WritePropertyValues(string parentPropertyName, DbPropertyValues propertyValues) { foreach (var propertyName in propertyValues.PropertyNames) { var nestedValues = propertyValues[propertyName] as DbPropertyValues; if (nestedValues != null) { WritePropertyValues(parentPropertyName + propertyName + ".", nestedValues); } else { Console.WriteLine("Property {0}{1} has value {2}", parentPropertyName, propertyName, propertyValues[propertyName]); } } } To print out all current property values the method would be called like this: using (var context = new BloggingContext()) { var user = context.Users.Find("johndoe1987"); WritePropertyValues("", context.Entry(user).CurrentValues); } Automatic detect changesWhen using most POCO entities the determination of how an entity has changed (and therefore which updates need to be sent to the database) is handled by the Detect Changes algorithm. Detect Changes works by detecting the differences between the current property values of the entity and the original property values that are stored in a snapshot when the entity was queried or attached. The techniques shown in this topic apply equally to models created with Code First and the EF Designer. By default, Entity Framework performs Detect Changes automatically when the following methods are called:
Disabling automatic detection of changesIf you are tracking a lot of entities in your context and you call one of these methods many times in a loop, then you may get significant performance improvements by turning off detection of changes for the duration of the loop. For example: using (var context = new BloggingContext()) { try { context.Configuration.AutoDetectChangesEnabled = false; // Make many calls in a loop foreach (var blog in aLotOfBlogs) { context.Blogs.Add(blog); } } finally { context.Configuration.AutoDetectChangesEnabled = true; } } Don’t forget to re-enable detection of changes after the loop — We've used a try/finally to ensure it is always re-enabled even if code in the loop throws an exception. An alternative to disabling and re-enabling is to leave automatic detection of changes turned off at all times and either call context.ChangeTracker.DetectChanges explicitly or use change tracking proxies diligently. Both of these options are advanced and can easily introduce subtle bugs into your application so use them with care. If you need to add or remove many objects from a context, consider using DbSet.AddRange and DbSet.RemoveRange. This methods automatically detect changes only once after the add or remove operations are completed. Handling Concurrency ConflictsOptimistic concurrency involves optimistically attempting to save your entity to the database in the hope that the data there has not changed since the entity was loaded. If it turns out that the data has changed then an exception is thrown and you must resolve the conflict before attempting to save again. This topic covers how to handle such exceptions in Entity Framework. The techniques shown in this topic apply equally to models created with Code First and the EF Designer. This post is not the appropriate place for a full discussion of optimistic concurrency. The sections below assume some knowledge of concurrency resolution and show patterns for common tasks. Many of these patterns make use of the topics discussed in Working with Property Values. Resolving concurrency issues when you are using independent associations (where the foreign key is not mapped to a property in your entity) is much more difficult than when you are using foreign key associations. Therefore if you are going to do concurrency resolution in your application it is advised that you always map foreign keys into your entities. All the examples below assume that you are using foreign key associations. A DbUpdateConcurrencyException is thrown by SaveChanges when an optimistic concurrency exception is detected while attempting to save an entity that uses foreign key associations. Resolving optimistic concurrency exceptions with Reload (database wins)The Reload method can be used to overwrite the current values of the entity with the values now in the database. The entity is then typically given back to the user in some form and they must try to make their changes again and re-save. For example: using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); blog.Name = "The New ADO.NET Blog"; bool saveFailed; do { saveFailed = false; try { context.SaveChanges(); } catch (DbUpdateConcurrencyException ex) { saveFailed = true; // Update the values of the entity that failed to save from the store ex.Entries.Single().Reload(); } } while (saveFailed); } A good way to simulate a concurrency exception is to set a breakpoint on the SaveChanges call and then modify an entity that is being saved in the database using another tool such as SQL Management Studio. You could also insert a line before SaveChanges to update the database directly using SqlCommand. For example: context.Database.SqlCommand( "UPDATE dbo.Blogs SET Name = 'Another Name' WHERE BlogId = 1"); The Entries method on DbUpdateConcurrencyException returns the DbEntityEntry instances for the entities that failed to update. (This property currently always returns a single value for concurrency issues. It may return multiple values for general update exceptions.) An alternative for some situations might be to get entries for all entities that may need to be reloaded from the database and call reload for each of these. Resolving optimistic concurrency exceptions as client winsThe example above that uses Reload is sometimes called database wins or store wins because the values in the entity are overwritten by values from the database. Sometimes you may wish to do the opposite and overwrite the values in the database with the values currently in the entity. This is sometimes called client wins and can be done by getting the current database values and setting them as the original values for the entity. (See Working with Property Values for information on current and original values.) For example: using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); blog.Name = "The New ADO.NET Blog"; bool saveFailed; do { saveFailed = false; try { context.SaveChanges(); } catch (DbUpdateConcurrencyException ex) { saveFailed = true; // Update original values from the database var entry = ex.Entries.Single(); entry.OriginalValues.SetValues(entry.GetDatabaseValues()); } } while (saveFailed); } Custom resolution of optimistic concurrency exceptionsSometimes you may want to combine the values currently in the database with the values currently in the entity. This usually requires some custom logic or user interaction. For example, you might present a form to the user containing the current values, the values in the database, and a default set of resolved values. The user would then edit the resolved values as necessary and it would be these resolved values that get saved to the database. This can be done using the DbPropertyValues objects returned from CurrentValues and GetDatabaseValues on the entity’s entry. For example: using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); blog.Name = "The New ADO.NET Blog"; bool saveFailed; do { saveFailed = false; try { context.SaveChanges(); } catch (DbUpdateConcurrencyException ex) { saveFailed = true; // Get the current entity values and the values in the database var entry = ex.Entries.Single(); var currentValues = entry.CurrentValues; var databaseValues = entry.GetDatabaseValues(); // Choose an initial set of resolved values. In this case we // make the default be the values currently in the database. var resolvedValues = databaseValues.Clone(); // Have the user choose what the resolved values should be HaveUserResolveConcurrency(currentValues, databaseValues, resolvedValues); // Update the original values with the database values and // the current values with whatever the user choose. entry.OriginalValues.SetValues(databaseValues); entry.CurrentValues.SetValues(resolvedValues); } } while (saveFailed); } public void HaveUserResolveConcurrency(DbPropertyValues currentValues, DbPropertyValues databaseValues, DbPropertyValues resolvedValues) { // Show the current, database, and resolved values to the user and have // them edit the resolved values to get the correct resolution. } Custom resolution of optimistic concurrency exceptions using objectsThe code above uses DbPropertyValues instances for passing around current, database, and resolved values. Sometimes it may be easier to use instances of your entity type for this. This can be done using the ToObject and SetValues methods of DbPropertyValues. For example: using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); blog.Name = "The New ADO.NET Blog"; bool saveFailed; do { saveFailed = false; try { context.SaveChanges(); } catch (DbUpdateConcurrencyException ex) { saveFailed = true; // Get the current entity values and the values in the database // as instances of the entity type var entry = ex.Entries.Single(); var databaseValues = entry.GetDatabaseValues(); var databaseValuesAsBlog = (Blog)databaseValues.ToObject(); // Choose an initial set of resolved values. In this case we // make the default be the values currently in the database. var resolvedValuesAsBlog = (Blog)databaseValues.ToObject(); // Have the user choose what the resolved values should be HaveUserResolveConcurrency((Blog)entry.Entity, databaseValuesAsBlog, resolvedValuesAsBlog); // Update the original values with the database values and // the current values with whatever the user choose. entry.OriginalValues.SetValues(databaseValues); entry.CurrentValues.SetValues(resolvedValuesAsBlog); } } while (saveFailed); } public void HaveUserResolveConcurrency(Blog entity, Blog databaseValues, Blog resolvedValues) { // Show the current, database, and resolved values to the user and have // them update the resolved values to get the correct resolution. } Working with Data ProvidersThe topics in this section describe the services and providers that transform queries against a conceptual model into native queries against a data source that is supported by the Entity Framework. See alsoConnection Strings in the ADO.NET Entity FrameworkA connection string contains initialization information that is passed as a parameter from a data provider to a data source. The syntax depends on the data provider, and the connection string is parsed during the attempt to open a connection. Connection strings used by the Entity Framework contain information used to connect to the underlying ADO.NET data provider that supports the Entity Framework. They also contain information about the required model and mapping files. The connection string is used by the EntityClient provider when accessing model and mapping metadata and connecting to the data source. The connection string can be accessed or set through the ConnectionString property of EntityConnection. The EntityConnectionStringBuilder class can be used to programmatically construct or access parameters in the connection string. For more information, see How to: Build an EntityConnection Connection String. The Entity Data Model tools generate a connection string that is stored in the application's configuration file. ObjectContext retrieves this connection information automatically when creating object queries. The EntityConnection used by an ObjectContext instance can be accessed from the Connection property. For more information, see Managing Connections and Transactions. Connection String SyntaxTo learn about the general syntax for connection strings, see Connection string syntax | Connection Strings in ADO.NET. Connection String ParametersThe following table lists the valid names for keyword values in the ConnectionString.
The following is an example of a connection string for the AdventureWorks Sales Model stored in the application configuration file: Model and Mapping File LocationsThe Metadata parameter contains a list of locations for the EntityClient provider to search for model and mapping files. Model and mapping files are often deployed in the same directory as the application executable file. These files can also be deployed in a specific location or included as an embedded resource in the application. Embedded resources are specified as follows: Metadata=res://<assemblyFullName>/<resourceName>. The following options are available for defining the location of an embedded resource:
Note To improve performance, embed resources in the calling assembly, except in non-Web scenarios where there is no reference to underlying mapping and metadata files in the calling assembly. The following example loads all the model and mapping files in the calling assembly, referenced assemblies, and other assemblies in the bin directory of an application. Metadata=res://*/ The following example loads the model.csdl file from the AdventureWorks assembly, and loads the model.ssdl and model.msl files from the default directory of the running application. Metadata=res://AdventureWorks, 1.0.0.0, neutral, a14f3033def15840/model.csdl|model.ssdl|model.msl The following example loads the three specified resources from the specific assembly. Metadata=res://AdventureWorks, 1.0.0.0, neutral, a14f3033def15840/model.csdl| res://AdventureWorks, 1.0.0.0, neutral, a14f3033def15840/model.ssdl| res://AdventureWorks, 1.0.0.0, neutral, a14f3033def15840/model.msl The following example loads all the embedded resources with the extensions .csdl, .msl, and .ssdl from the assembly. Metadata=res://AdventureWorks, 1.0.0.0, neutral, a14f3033def15840/ The following example loads all the resources in the relative file path plus "datadir\metadata\" from the loaded assembly location. Metadata=datadir\metadata\ The following example loads all the resources in the relative file path from the loaded assembly location. Metadata=.\ Support for the |DataDirectory| Substitution String and the Web Application Root Operator (~)DataDirectory and the ~ operator are used in the ConnectionString as part of the Metadata and Provider Connection String keywords. The EntityConnection forwards the DataDirectory and the ~ operator to MetadataWorkspace and the store provider, respectively.
DataDirectory and the ~ operator should be specified only at the beginning of a path, they are not resolved at any other position. The Entity Framework will try to resolve ~/data, but it will treat /data/~ as a physical path. A path that starts with the DataDirectory or the ~ operator cannot resolve to a physical path outside the branch of the DataDirectory and the ~ operator. For example, the following paths will resolve: ~ , ~/data , ~/bin/Model/SqlServer. The following paths will fail to resolve: ~/.., ~/../other. DataDirectory and the ~ operator can be extended to include sub-directories, as follows: |DataDirectory|\Model, ~/bin/Model The resolution of the DataDirectory substitution string and the ~ operator is non-recursive. For example, when DataDirectory includes the ~ character, an exception will occur. This prevents an infinite recursion. See also
Entity Framework Data ProvidersThis section provides information on data providers that support the Entity Framework. In This SectionEntityClient Provider for the Entity Framework SqlClient for the Entity Framework Related SectionsEntity Framework (SQL Server Compact) Third-Party Providers for the Entity Framework See alsoEntityClient Provider for the Entity FrameworkThe EntityClient provider is a data provider used by Entity Framework applications to access data described in a conceptual model. For information about conceptual models, see Modeling and Mapping. EntityClient uses other .NET Framework data providers to access the data source. For example, EntityClient uses the .NET Framework Data Provider for SQL Server (SqlClient) when accessing a SQL Server database. For information about the SqlClient provider, see SqlClient for the Entity Framework. The EntityClient provider is implemented in the System.Data.EntityClient namespace. Managing ConnectionsThe Entity Framework builds on top of storage-specific ADO.NET data providers by providing an EntityConnection to an underlying data provider and relational database. To construct an EntityConnection object, you have to reference a set of metadata that contains the necessary models and mapping, and also a storage-specific data provider name and connection string. After the EntityConnection is in place, entities can be accessed through the classes generated from the conceptual model. You can specify a connection string in app.config file. The System.Data.EntityClient also includes the EntityConnectionStringBuilder class. This class enables developers to programmatically create syntactically correct connection strings, and parse and rebuild existing connection strings, by using properties and methods of the class. For more information, see How to: Build an EntityConnection Connection String. Creating QueriesThe Entity SQL language is a storage-independent dialect of SQL that works directly with conceptual entity schemas and supports Entity Data Model concepts such as inheritance and relationships. The EntityCommand class is used to execute an Entity SQL command against an entity model. When you construct EntityCommand objects, you can specify a stored procedure name or a query text. The Entity Framework works with storage-specific data providers to translate generic Entity SQL into storage-specific queries. For more information about writing Entity SQL queries, see Entity SQL Language. The following example creates an EntityCommand object and assigns an Entity SQL query text to its EntityCommand.CommandText property. This Entity SQL query requests products ordered by the list price from the conceptual model. The following code has no knowledge of the storage model at all. EntityCommand cmd = conn.CreateCommand(); cmd.CommandText = @"SELECT VALUE p FROM AdventureWorksEntities.Product AS p ORDER BY p.ListPrice"; Executing QueriesWhen a query is executed, it is parsed and converted into a canonical command tree. All subsequent processing is performed on the command tree. The command tree is the means of communication between the System.Data.EntityClient and the underlying .NET Framework data provider, such as System.Data.SqlClient. The EntityDataReader exposes the results of executing a EntityCommand against a conceptual model. To execute the command that returns the EntityDataReader, call ExecuteReader. The EntityDataReader implements IExtendedDataRecord to describe rich structured results. Managing TransactionsIn the Entity Framework, there are two ways to use transactions: automatic and explicit. Automatic transactions use the System.Transactions namespace, and explicit transactions use the EntityTransaction class. To update data that is exposed through a conceptual model, see How to: Manage Transactions in the Entity Framework. In This SectionHow to: Build an EntityConnection Connection String How to: Execute a Query that Returns PrimitiveType Results How to: Execute a Query that Returns StructuralType Results How to: Execute a Query that Returns RefType Results How to: Execute a Query that Returns Complex Types How to: Execute a Query that Returns Nested Collections How to: Execute a Parameterized Entity SQL Query Using EntityCommand How to: Execute a Parameterized Stored Procedure Using EntityCommand How to: Execute a Polymorphic Query How to: Navigate Relationships with the Navigate Operator See alsoHow to: Build an EntityConnection Connection StringThis topic provides an example of how to build an EntityConnection. To run the code in this example
ExampleThe following example initializes the System.Data.SqlClient.SqlConnectionStringBuilder for the underlying provider, then initializes the System.Data.EntityClient.EntityConnectionStringBuilder object and passes this object to the constructor of the EntityConnection. // Specify the provider name, server and database. string providerName = "System.Data.SqlClient"; string serverName = "."; string databaseName = "AdventureWorks"; // Initialize the connection string builder for the // underlying provider. SqlConnectionStringBuilder sqlBuilder = new SqlConnectionStringBuilder(); // Set the properties for the data source. sqlBuilder.DataSource = serverName; sqlBuilder.InitialCatalog = databaseName; sqlBuilder.IntegratedSecurity = true; // Build the SqlConnection connection string. string providerString = sqlBuilder.ToString(); // Initialize the EntityConnectionStringBuilder. EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder(); //Set the provider name. entityBuilder.Provider = providerName; // Set the provider-specific connection string. entityBuilder.ProviderConnectionString = providerString; // Set the Metadata location. entityBuilder.Metadata = @"res://*/AdventureWorksModel.csdl| res://*/AdventureWorksModel.ssdl| res://*/AdventureWorksModel.msl"; Console.WriteLine(entityBuilder.ToString()); using (EntityConnection conn = new EntityConnection(entityBuilder.ToString())) { conn.Open(); Console.WriteLine("Just testing the connection."); conn.Close(); } See alsoHow to: Execute a Query that Returns PrimitiveType ResultsThis topic shows how to execute a command against a conceptual model by using an EntityCommand, and how to retrieve the PrimitiveType results by using an EntityDataReader. To run the code in this example
ExampleThis example executes a query that returns a PrimitiveType result. If you pass the following query as an argument to the ExecutePrimitiveTypeQuery function, the function displays the average list price of all Products: SELECT VALUE AVG(p.ListPrice) FROM AdventureWorksEntities.Products as p If you pass a parameterized query, like the following, EntityParameter objects to the Parameters property on the EntityCommand object. CASE WHEN AVG({@score1,@score2,@score3}) < @total THEN TRUE ELSE FALSE END static void ExecutePrimitiveTypeQuery(string esqlQuery) { if (esqlQuery.Length == 0) { Console.WriteLine("The query string is empty."); return; } using (EntityConnection conn = new EntityConnection("name=AdventureWorksEntities")) { conn.Open(); // Create an EntityCommand. using (EntityCommand cmd = conn.CreateCommand()) { cmd.CommandText = esqlQuery; // Execute the command. using (EntityDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) { // Start reading results. while (rdr.Read()) { IExtendedDataRecord record = rdr as IExtendedDataRecord; // For PrimitiveType // the record contains exactly one field. int fieldIndex = 0; Console.WriteLine("Value: " + record.GetValue(fieldIndex)); } } } conn.Close(); } } See alsoHow to: Execute a Query that Returns StructuralType ResultsThis topic shows how to execute a command against a conceptual model by using an EntityCommand object, and how to retrieve the StructuralType results by using an EntityDataReader. The EntityType, RowType and ComplexType classes derive from the StructuralType class. To run the code in this example
ExampleThis example executes a query that returns EntityType results. If you pass the following query as an argument to the ExecuteStructuralTypeQuery function, the function displays details about the Products: SELECT VALUE Product FROM AdventureWorksEntities.Products AS Product If you pass a parameterized query, like the following, add the EntityParameter objects to the Parameters property on the EntityCommand object. SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice >= @price static void ExecuteStructuralTypeQuery(string esqlQuery) { if (esqlQuery.Length == 0) { Console.WriteLine("The query string is empty."); return; } using (EntityConnection conn = new EntityConnection("name=AdventureWorksEntities")) { conn.Open(); // Create an EntityCommand. using (EntityCommand cmd = conn.CreateCommand()) { cmd.CommandText = esqlQuery; // Execute the command. using (EntityDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) { // Start reading results. while (rdr.Read()) { StructuralTypeVisitRecord(rdr as IExtendedDataRecord); } } } conn.Close(); } } static void StructuralTypeVisitRecord(IExtendedDataRecord record) { int fieldCount = record.DataRecordInfo.FieldMetadata.Count; for (int fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++) { Console.Write(record.GetName(fieldIndex) + ": "); // If the field is flagged as DbNull, the shape of the value is undetermined. // An attempt to get such a value may trigger an exception. if (record.IsDBNull(fieldIndex) == false) { BuiltInTypeKind fieldTypeKind = record.DataRecordInfo.FieldMetadata[fieldIndex]. FieldType.TypeUsage.EdmType.BuiltInTypeKind; // The EntityType, ComplexType and RowType are structural types // that have members. // Read only the PrimitiveType members of this structural type. if (fieldTypeKind == BuiltInTypeKind.PrimitiveType) { // Primitive types are surfaced as plain objects. Console.WriteLine(record.GetValue(fieldIndex).ToString()); } } } } See alsoHow to: Execute a Query that Returns RefType ResultsThis topic shows how to execute a command against a conceptual model by using an EntityCommand object, and how to retrieve the RefType results by using an EntityDataReader. To run the code in this example
ExampleThis example executes a query that returns RefType results. If you pass the following query as an argument to the ExecuteRefTypeQuery function, the function returns a reference to the entity: SELECT REF(p) FROM AdventureWorksEntities.Products as p If you pass a parameterized query, like the following, add the EntityParameter objects to the Parameters property on the EntityCommand object. SELECT REF(p) FROM AdventureWorksEntities.Products as p WHERE p.ProductID == @productID static public void ExecuteRefTypeQuery(string esqlQuery) { if (esqlQuery.Length == 0) { Console.WriteLine("The query string is empty."); return; } using (EntityConnection conn = new EntityConnection("name=AdventureWorksEntities")) { conn.Open(); // Create an EntityCommand. using (EntityCommand cmd = conn.CreateCommand()) { cmd.CommandText = esqlQuery; // Execute the command. using (EntityDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) { // Start reading results. while (rdr.Read()) { RefTypeVisitRecord(rdr as IExtendedDataRecord); } } } conn.Close(); } } static void RefTypeVisitRecord(IExtendedDataRecord record) { // For RefType the record contains exactly one field. int fieldIndex = 0; // If the field is flagged as DbNull, the shape of the value is undetermined. // An attempt to get such a value may trigger an exception. if (record.IsDBNull(fieldIndex) == false) { BuiltInTypeKind fieldTypeKind = record.DataRecordInfo.FieldMetadata[fieldIndex]. FieldType.TypeUsage.EdmType.BuiltInTypeKind; //read only fields that contain PrimitiveType if (fieldTypeKind == BuiltInTypeKind.RefType) { // Ref types are surfaced as EntityKey instances. // The containing record sees them as atomic. EntityKey key = record.GetValue(fieldIndex) as EntityKey; // Get the EntitySet name. Console.WriteLine("EntitySetName " + key.EntitySetName); // Get the Name and the Value information of the EntityKey. foreach (EntityKeyMember keyMember in key.EntityKeyValues) { Console.WriteLine(" Key Name: " + keyMember.Key); Console.WriteLine(" Key Value: " + keyMember.Value); } } } } See alsoHow to: Execute a Query that Returns Complex TypesThis topic shows how to execute an Entity SQL query that returns entity type objects that contain a property of a complex type. To run the code in this example
ExampleThe following example executes a query that returns a collection of Contact objects and displays two properties of the Contact objects: ContactID and the values of the EmailPhoneComplexType complex type. using (EntityConnection conn = new EntityConnection("name=AdventureWorksEntities")) { conn.Open(); string esqlQuery = @"SELECT VALUE contacts FROM AdventureWorksEntities.Contacts AS contacts WHERE contacts.ContactID == @id"; // Create an EntityCommand. using (EntityCommand cmd = conn.CreateCommand()) { cmd.CommandText = esqlQuery; EntityParameter param = new EntityParameter(); param.ParameterName = "id"; param.Value = 3; cmd.Parameters.Add(param); // Execute the command. using (EntityDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) { // The result returned by this query contains // Address complex Types. while (rdr.Read()) { // Display CustomerID Console.WriteLine("Contact ID: {0}", rdr["ContactID"]); // Display Address information. DbDataRecord nestedRecord = rdr["EmailPhoneComplexProperty"] as DbDataRecord; Console.WriteLine("Email and Phone Info:"); for (int i = 0; i < nestedRecord.FieldCount; i++) { Console.WriteLine(" " + nestedRecord.GetName(i) + ": " + nestedRecord.GetValue(i)); } } } } conn.Close(); } How to: Execute a Query that Returns Nested CollectionsThis shows how to execute a command against a conceptual model by using an EntityCommand object, and how to retrieve the nested collection results by using an EntityDataReader. To run the code in this example
ExampleA nested collection is a collection that is inside another collection. The following code retrieves a collection of Contacts and the nested collections of SalesOrderHeaders that are associated with each Contact. using (EntityConnection conn = new EntityConnection("name=AdventureWorksEntities")) { conn.Open(); // Create an EntityCommand. using (EntityCommand cmd = conn.CreateCommand()) { // Create a nested query. string esqlQuery = @"Select c.ContactID, c.SalesOrderHeaders From AdventureWorksEntities.Contacts as c"; cmd.CommandText = esqlQuery; // Execute the command. using (EntityDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) { // The result returned by this query contains // ContactID and a nested collection of SalesOrderHeader items. // associated with this Contact. while (rdr.Read()) { // the first column contains Contact ID. Console.WriteLine("Contact ID: {0}", rdr["ContactID"]); // The second column contains a collection of SalesOrderHeader // items associated with the Contact. DbDataReader nestedReader = rdr.GetDataReader(1); while (nestedReader.Read()) { Console.WriteLine(" SalesOrderID: {0} ", nestedReader["SalesOrderID"]); Console.WriteLine(" OrderDate: {0} ", nestedReader["OrderDate"]); } } } } conn.Close(); } See alsoHow to: Execute a Parameterized Entity SQL Query Using EntityCommandThis topic shows how to execute an Entity SQL query that has parameters by using an EntityCommand object. To run the code in this example
ExampleThe following example shows how to construct a query string with two parameters. It then creates an EntityCommand, adds two parameters to the EntityParameter collection of that EntityCommand, and iterates through the collection of Contact items. using (EntityConnection conn = new EntityConnection("name=AdventureWorksEntities")) { conn.Open(); // Create a query that takes two parameters. string esqlQuery = @"SELECT VALUE Contact FROM AdventureWorksEntities.Contacts AS Contact WHERE Contact.LastName = @ln AND Contact.FirstName = @fn"; using (EntityCommand cmd = new EntityCommand(esqlQuery, conn)) { // Create two parameters and add them to // the EntityCommand's Parameters collection EntityParameter param1 = new EntityParameter(); param1.ParameterName = "ln"; param1.Value = "Adams"; EntityParameter param2 = new EntityParameter(); param2.ParameterName = "fn"; param2.Value = "Frances"; cmd.Parameters.Add(param1); cmd.Parameters.Add(param2); using (DbDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) { // Iterate through the collection of Contact items. while (rdr.Read()) { Console.WriteLine(rdr["FirstName"]); Console.WriteLine(rdr["LastName"]); } } } conn.Close(); } See alsoHow to: Execute a Parameterized Stored Procedure Using EntityCommandThis topic shows how to execute a parameterized stored procedure by using the EntityCommand class. To run the code in this example
ExampleThe following code executes the GetStudentGrades stored procedure where StudentId is a required parameter. The results are then read by an EntityDataReader. using (EntityConnection conn = new EntityConnection("name=SchoolEntities")) { conn.Open(); // Create an EntityCommand. using (EntityCommand cmd = conn.CreateCommand()) { cmd.CommandText = "SchoolEntities.GetStudentGrades"; cmd.CommandType = CommandType.StoredProcedure; EntityParameter param = new EntityParameter(); param.Value = 2; param.ParameterName = "StudentID"; cmd.Parameters.Add(param); // Execute the command. using (EntityDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) { // Read the results returned by the stored procedure. while (rdr.Read()) { Console.WriteLine("ID: {0} Grade: {1}", rdr["StudentID"], rdr["Grade"]); } } } conn.Close(); } See alsoHow to: Execute a Polymorphic QueryThis topic shows how to execute a polymorphic Entity SQL query using the OFTYPE operator. To run the code in this example
ExampleThe following example uses an OFTYPE operator to get and display a collection of only OnsiteCourses from a collection of Courses. using (EntityConnection conn = new EntityConnection("name=SchoolEntities")) { conn.Open(); // Create a query that specifies to // get a collection of only OnsiteCourses. string esqlQuery = @"SELECT VAlUE onsiteCourse FROM OFTYPE(SchoolEntities.Courses, SchoolModel.OnsiteCourse) AS onsiteCourse"; using (EntityCommand cmd = new EntityCommand(esqlQuery, conn)) { // Execute the command. using (DbDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) { // Start reading. while (rdr.Read()) { // Display OnsiteCourse's location. Console.WriteLine("CourseID: {0} ", rdr["CourseID"]); Console.WriteLine("Location: {0} ", rdr["Location"]); } } } } See alsoHow to: Navigate Relationships with the Navigate OperatorThis topic shows how to execute a command against a conceptual model by using an EntityCommand object, and how to retrieve the RefType results by using an EntityDataReader. To run the code in this example
ExampleThe following example shows how to navigate relationships in Entity SQL by using the NAVIGATE operator. The Navigate operator takes the following parameters: an instance of an entity, the relationship type, the end of the relationship, and the beginning of the relationship. Optionally, you can pass only an instance of an entity and the relationship type to the Navigate operator. using (EntityConnection conn = new EntityConnection("name=AdventureWorksEntities")) { conn.Open(); // Create an EntityCommand. using (EntityCommand cmd = conn.CreateCommand()) { // Create an Entity SQL query. string esqlQuery = @"SELECT address.AddressID, (SELECT VALUE DEREF(soh) FROM NAVIGATE(address, AdventureWorksModel.FK_SalesOrderHeader_Address_BillToAddressID) AS soh) FROM AdventureWorksEntities.Addresses AS address"; cmd.CommandText = esqlQuery; // Execute the command. using (DbDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) { // Start reading. while (rdr.Read()) { Console.WriteLine(rdr["AddressID"]); } } } conn.Close(); } See alsoSqlClient for the Entity FrameworkThis section describes the .NET Framework Data Provider for SQL Server (SqlClient), which enables the Entity Framework to work over Microsoft SQL Server. Provider Schema AttributeProvider is an attribute of the Schema element in store schema definition language (SSDL). To use SqlClient, assign the string "System.Data.SqlClient" to the Provider attribute of the Schema element. ProviderManifestToken Schema AttributeProviderManifestToken is a required attribute of the Schema element in SSDL. This token is used to load the provider manifest for offline scenarios. For more information about ProviderManifestToken attribute, see Schema Element (SSDL). SqlClient can be used as a data provider for different versions of SQL Server. These versions have different capabilities. For example, SQL Server 2000 does not support varchar(max) and nvarchar(max) types that were introduced with SQL Server 2005. SqlClient produces and accepts the following provider manifest tokens for different versions of SQL Server.
Note Starting with Visual Studio 2010, the ADO.NET Entity Data Model Tools do not support SQL Server 2000. Provider Namespace NameAll providers must specify a namespace. This property tells the Entity Framework which prefix is used by the provider for specific constructs, such as types and functions. The namespace for SqlClient provider manifests is SqlServer. For more information about namespaces, see Namespaces. TypesThe SqlClient provider for the Entity Framework provides mapping information between conceptual model types and SQL Server types. For more information, see SqlClient for Entity FrameworkTypes. FunctionsThe SqlClient provider for the Entity Framework defines the list of functions supported by the provider. For a list of the supported functions, see SqlClient for Entity Framework Functions. In This SectionSqlClient for Entity Framework Functions SqlClient for Entity FrameworkTypes Known Issues in SqlClient for Entity Framework See alsoSqlClient for Entity Framework FunctionsThe .NET Framework Data Provider for SQL Server (SqlClient) for the Entity Framework provides a set of functions to perform mathematical and aggregation calculations, as well as functions to perform System.DateTime and string operations. These functions are in the SQLServer namespace. For a list of functions that should work with any provider, see Canonical Functions. For information about how canonical functions map to SQL Server functions, see Conceptual Model Canonical to SQL Server Functions Mapping. In This SectionConceptual Model Canonical to SQL Server Functions Mapping See alsoConceptual Model Canonical to SQL Server Functions MappingThis topic describes how conceptual model canonical functions map to the corresponding SQL Server functions. Date and Time FunctionsThe following table describes the date and time functions mapping:
Aggregate FunctionsThe following table describes the aggregate functions mapping:
Math functionsThe following table describes the math functions mapping:
String FunctionsThe following table describes the string functions mapping:
Bitwise FunctionsThe following table describes the bitwise functions mapping:
Aggregate Functions (SqlClient for Entity Framework)The .NET Framework Data Provider for SQL Server (SqlClient) provides aggregate functions. Aggregate functions perform calculations on a set of input values and return a value. These functions are in the SqlServer namespace, which is available when you use SqlClient. A provider's namespace property allows the Entity Framework to discover which prefix is used by this provider for specific constructs, such as types and functions. The following are the SqlClient aggregate functions. AVG(expression)Returns the average of the values in a collection. Null values are ignored. Arguments An Int32, Int64, Double, and Decimal. Return Value The type of expression. Example SELECT VALUE SqlServer.AVG(p.ListPrice) FROM AdventureWorksEntities.Products as p SELECT VALUE SqlServer.AVG(p.ListPrice) FROM AdventureWorksEntities.Products AS p CHECKSUM_AGG(collection)Returns the checksum of the values in a collection. Null values are ignored. Arguments A Collection(Int32). Return Value An Int32. Example SELECT VALUE SqlServer.Checksum_Agg(cast(product.ListPrice as Int32)) FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice > cast(@price as Decimal) SELECT VALUE SqlServer.Checksum_Agg(cast(product.ListPrice AS Int32)) FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice > cast(@price AS Decimal) COUNT(expression)Returns the number of items in a collection as an Int32. Arguments A Collection<T>, where T is one of the following types:
Return Value An Int32. Example ANYELEMENT(SELECT VALUE SqlServer.COUNT(product.ProductID) FROM AdventureWorksEntities.Products AS product WHERE SqlServer.CEILING(product.ListPrice) == SqlServer.FLOOR(product.ListPrice)) [!code-sql[DP EntityServices Concepts#SQLSERVER_COUNT](~/samples/snippets/tsql/VS_Snippets_Data/dp entityservices concepts/tsql/entitysql.sql#sqlserver_count) COUNT_BIG(expression)Returns the number of items in a collection as a bigint. Arguments A Collection(T), where T is one of the following types:
Return Value An Int64. Example ANYELEMENT(SELECT VALUE SqlServer.COUNT_BIG(product.ProductID) FROM AdventureWorksEntities.Products AS product WHERE SqlServer.CEILING(product.ListPrice) == SqlServer.FLOOR(product.ListPrice)) ANYELEMENT(SELECT VALUE SqlServer.COUNT_BIG(product.ProductID) FROM AdventureWorksEntities.Products AS product WHERE SqlServer.CEILING(product.ListPrice) == SqlServer.FLOOR(product.ListPrice)) MAX(expression)Returns the maximum value the collection. Arguments A Collection(T), where T is one of the following types:
Return Value The type of expression. Example SELECT VALUE SqlServer.MAX(p.ListPrice) FROM AdventureWorksEntities.Products as p SELECT VALUE SqlServer.MAX(p.ListPrice) FROM AdventureWorksEntities.Products AS p MIN(expression)Returns the minimum value in a collection. Arguments A Collection(T), where T is one of the following types:
Return Value The type of expression. Example SELECT VALUE SqlServer.MIN(p.ListPrice) FROM AdventureWorksEntities.Products as p SELECT VALUE SqlServer.MIN(p.ListPrice) FROM AdventureWorksEntities.Products AS p STDEV(expression)Returns the statistical standard deviation of all values in the specified expression. Arguments A Collection(Double). Return Value A Double. Example SELECT VALUE SqlServer.STDEV(product.ListPrice) FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice > cast(@price as Decimal) SELECT VALUE SqlServer.STDEV(product.ListPrice) FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice > cast(@price AS Decimal) STDEVP(expression)Returns the statistical standard deviation for the population for all values in the specified expression. Arguments A Collection(Double). Return Value A Double. Example SELECT VALUE SqlServer.STDEVP(product.ListPrice) FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice > cast(@price as Decimal) SELECT VALUE SqlServer.STDEVP(product.ListPrice) FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice > cast(@price AS Decimal) SUM(expression)Returns the sum of all the values in the collection. Arguments A Collection(T) where T is one of the following types: Int32, Int64, Double, Decimal. Return Value The type of expression. Example SELECT VALUE SqlServer.SUM(p.ListPrice) FROM AdventureWorksEntities.Products as p SELECT VALUE SqlServer.SUM(p.ListPrice) FROM AdventureWorksEntities.Products AS p VAR(expression)Returns the statistical variance of all values in the specified expression. Arguments A Collection(Double). Return Value A Double. Example SELECT VALUE SqlServer.VAR(product.ListPrice) FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice > cast(@price as Decimal) SELECT VALUE SqlServer.VAR(product.ListPrice) FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice > cast(@price AS Decimal) VARP(expression)Returns the statistical variance for the population for all values in the specified expression. Arguments A Collection(Double). Return Value A Double. Example SELECT VALUE SqlServer.VARP(product.ListPrice) FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice > cast(@price as Decimal) SELECT VALUE SqlServer.VARP(product.ListPrice) FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice > cast(@price AS Decimal) See alsoFor more information about the aggregate functions that SqlClient supports, see the documentation for the SQL Server version that you specified in the SqlClient provider manifest:
Date and Time FunctionsThe .NET Framework Data Provider for SQL Server (SqlClient) provides date and time functions that perform operations on a System.DateTime input value and return a string, numeric, or System.DateTime value result. These functions are in the SqlServer namespace, which is available when you use SqlClient. A provider's namespace property allows the Entity Framework to discover which prefix is used by this provider for specific constructs, such as types and functions. The following table shows the SqlClient date and time functions.
For more information about the date and time functions that SqlClient supports, see the documentation for the SQL Server version that you specified in the SqlClient provider manifest:
See alsoMathematical FunctionsThe .NET Framework Data Provider for SQL Server (SqlClient) provides math functions that perform calculations on input values that are provided as arguments, and return a numeric value result. These functions are in the SqlServer namespace, which is available when you use SqlClient. A provider's namespace property allows the Entity Framework to discover which prefix is used by this provider for specific constructs, such as types and functions. The following table describes the SqlClient math functions. ABS(expression)Performs the absolute value function. Arguments expression: An Int32, Int64, Double, or Decimal. Return Value The absolute value of the specified expression. Example SqlServer.ABS(-2) ACOS(expression)Returns the arccosine value of the specified expression. Arguments expression: A Double. Return Value A Double. Example SqlServer.ACOS(.9) ASIN(expression)Returns the arcsine value of the specified expression. Arguments expression: A Double. Return Value A Double. Example SqlServer.ASIN(.9) ATAN(expression)Returns the arctangent value of the specified numeric expression. Arguments expression: A Double. Return Value A Double. Example SqlServer.ATAN(9) ATN2(expression, expression)Returns the angle, in radians, whose tangent is between the two specified numeric expressions. Arguments expression: A Double. Return Value A Double. Example SqlServer.ATN2(9, 8) CEILING(expression)Converts the specified expression to the smallest integer that is greater than or equal to it. Arguments expression: An Int32, Int64, Double, or Decimal. Return Value An Int32, Int64, Double, or Decimal. Example SELECT VALUE product FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice == SqlServer.CEILING(product.ListPrice) SELECT VALUE product FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice == SqlServer.CEILING(product.ListPrice) COS(expression)Calculates the trigonometric cosine of the specified angle in radians. Arguments expression: A Double. Return Value A Double. Example SqlServer.COS(45) COT(expression)Calculates the trigonometric cotangent of the specified angle in radians. Arguments expression: A Double. Return Value A Double. Example SqlServer.COT(60) DEGREES(radians)Returns the corresponding angle in degrees. Arguments expression: An Int32, Int64, Double, or Decimal. Return Value An Int32, Int64, Double, or Decimal. Example SqlServer.DEGREES(3.1) EXP(expression)Calculates the exponential value of a specified numeric expression. Arguments expression: A Double. Return Value A Double. Example SqlServer.EXP(1) FLOOR(expression)Converts the specified expression to the largest integer less than or equal to it. Arguments expression: A Double. Return Value A Double. Example SELECT VALUE product FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice == SqlServer.FLOOR(product.ListPrice) SELECT VALUE product FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice == SqlServer.FLOOR(product.ListPrice) LOG(expression)Calculates the natural logarithm of the specified float expression. Arguments expression: A Double. Return Value A Double. Example SqlServer.LOG(100) LOG10(expression)Returns the base-10 logarithm of the specified Double expression. Arguments expression: A Double. Return Value A Double. Example SqlServer.LOG10(100) PI()Returns the constant value of pi as a Double. Return Value A Double. Example SqlServer.PI() POWER(numeric_expression, power_expression)Calculates the value of a specified expression to a specified power. Arguments
Return Value The value of the specified numeric_expression to the specified power_expression. Example SqlServer.POWER(2,7) RADIANS(expression)Converts degrees to radians. Arguments expression: An Int32, Int64, Double, or Decimal. Return Value An Int32, Int64, Double, or Decimal. Example SqlServer.RADIANS(360.0) RAND([seed])Returns a random value from 0 through 1. Arguments The seed value as an Int32. If the seed is not specified, the SQL Server Database Engine assigns a seed value at random. For a specified seed value, the result returned is always the same. Return Value A random Double value from 0 through 1. Example SqlServer.RAND() ROUND(numeric_expression, length[,function])Returns a numeric expression, rounded to the specified length or precision. Arguments
Return Value The value of the specified numeric_expression to the specified power_expression. Example SqlServer.ROUND(748.58, -3) SIGN(expression)Returns the positive (+1), zero (0), or negative (-1) sign of the specified expression. Arguments expression: Int32, Int64, Double, or Decimal Return Value An Int32, Int64, Double, or Decimal. Example SqlServer.SIGN(-10) SIN(expression)Calculates the trigonometric sine of the specified angle in radians, and returns a Double expression. Arguments expression: A Double. Return Value A Double. Example SqlServer.SIN(20) SQRT(expression)Returns the square root of the specified expression. Arguments expression: A Double. Return Value A Double. Example SqlServer.SQRT(3600) SQUARE(expression)Returns the square of the specified expression. Arguments expression: A Double. Return Value A Double. Example SqlServer.SQUARE(25) TAN(expression)Calculates the tangent of a specified expression. Arguments expression: Double Return Value Double Example SqlServer.TAN(45.0) See alsoFor more information about the mathematical functions that SqlClient supports, see the documentation for the SQL Server version that you specified in the SqlClient provider manifest:
String FunctionsThe .NET Framework Data Provider for SQL Server (SqlClient) provides String functions that perform operations on an input String and return a String or numeric value result. These functions are in the SqlServer namespace, which is available when you use SqlClient. A provider's namespace property allows the Entity Framework to discover which prefix is used by this provider for specific constructs, such as types and functions. The following table shows the SqlClient String functions.
For more information about the String functions that SqlClient supports, see the documentation for the SQL Server version that you specified in the SqlClient provider manifest:
See alsoSystem FunctionsThe .NET Framework Data Provider for SQL Server (SqlClient) provides the following system functions:
For more information about the string functions that SqlClient supports, see the documentation for the SQL Server version that you specified in the SqlClient provider manifest:
See alsoSqlClient for Entity FrameworkTypesThe .NET Framework Data Provider for SQL Server (SqlClient) provider manifest file includes the list of the provider primitive types, facets for each type, the mappings between the conceptual and storage model primitive types, and the promotion and conversion rules between the conceptual and storage model primitive types. The following table describes types for SQL Server 2008, SQL Server 2005, and SQL Server 2000 databases and how these types map to conceptual model types. Some new types were introduced in later versions of SQL Server are not supported in the older versions of SQL Server. These types are noted in the table below.
See alsoKnown Issues in SqlClient for Entity FrameworkThis section describes known issues related to the .NET Framework Data Provider for SQL Server (SqlClient). Trailing Spaces in String FunctionsSQL Server ignores trailing spaces in string values. Therefore, passing trailing spaces in the string can lead to unpredictable results, even failures. If you have to have trailing spaces in your string, you should consider appending a white space character at the end, so that SQL Server does not trim the string. If the trailing spaces are not required, they should be trimmed before they are passed down the query pipeline. RIGHT FunctionIf a non-null value is passed as a first argument and 0 is passed as a second argument to RIGHT(nvarchar(max), 0) or RIGHT(varchar(max), 0), a NULL value will be returned instead of an empty string. CROSS and OUTER APPLY OperatorsCROSS and OUTER APPLY operators were introduced in SQL Server 2005. In some cases the query pipeline might produce a Transact-SQL statement that contains CROSS APPLY and/or OUTER APPLY operators. Because some backend providers, including versions of SQL Server earlier than SQL Server 2005, do not support these operators, such queries cannot be executed on these backend providers. The following are some typical scenarios that might lead to the presence of CROSS APPLY and/or OUTER APPLY operators in the output query:
SKIP OperatorIf you are using SQL Server 2000, using SKIP with ORDER BY on non-key columns might return incorrect results. More than the specified number of rows might be skipped if the non-key column has duplicate data in it. This is due to how SKIP is translated for SQL Server 2000. For example, in the following query, more than five rows might be skipped if E.NonKeyColumn has duplicate values: SELECT [E] FROM Container.EntitySet AS [E] ORDER BY [E].[NonKeyColumn] DESC SKIP 5L Targeting the Correct SQL Server VersionThe Entity Framework targets the Transact-SQL query based on the SQL Server version that is specified in the ProviderManifestToken attribute of the Schema element in the storage model (.ssdl) file. This version might differ from the version of the actual SQL Server you are connected to. For example, if you are using SQL Server 2005, but your ProviderManifestToken attribute is set to 2008, the generated Transact-SQL query might not execute on the server. For example, a query that uses the new date time types that were introduced in SQL Server 2008 will not execute on earlier versions of the SQL Server. If you are using SQL Server 2005, but your ProviderManifestToken attribute is set to 2000, the generated Transact-SQL query might be less optimized, or you might get an exception that says that the query is not supported. For more information, see the CROSS and OUTER APPLY Operators section, earlier in this topic. Certain database behaviors depend on the compatibility level set to the database. If your ProviderManifestToken attribute is set to 2005 and your SQL Server version is 2005, but the compatibility level of a database is set to "80" (SQL Server 2000), the generated Transact-SQL will be targeting SQL Server 2005, but might not execute as expected due to the compatibility level setting. For example, you might lose ordering information if a column name in the ORDER BY list matches a column name in the selector. Nested Queries in ProjectionNested queries in a projection clause might get translated into Cartesian product queries on the server. On some back-end servers, including SLQ Server, this can cause the TempDB table to get quite large. This can decrease server performance. The following is an example of a nested query in a projection clause: SELECT c, (SELECT c, (SELECT c FROM AdventureWorksModel.Vendor AS c ) As Inner2 FROM AdventureWorksModel.JobCandidate AS c ) As Inner1 FROM AdventureWorksModel.EmployeeDepartmentHistory AS c Server Generated GUID Identity ValuesThe Entity Framework supports server-generated GUID type identity values, but the provider must support returning the server-generated identity value after a row was inserted. Starting with SQL Server 2005, you can return the server-generated GUID type in a SQL Server database through the OUTPUT clause . See alsoWriting an Entity Framework Data ProviderThis section discusses how to write an Entity Framework provider to support a data source other than SQL Server. The Entity Framework includes a provider that supports SQL Server. Introducing the Entity Framework Provider ModelThe Entity Framework is database independent, and you can write a provider by using the ADO.NET Provider Model to connect to a diverse set of data sources. The Entity Framework data provider (built using the ADO.NET Data Provider model) performs the following functions:
SampleSee the Entity Framework Sample Provider for a sample of an Entity Framework provider that supports a data source other than SQL Server. In This SectionProvider Manifest Specification See alsoSQL GenerationWhen you write a provider for the Entity Framework, you must translate Entity Framework command trees into SQL that a specific database can understand, such as Transact-SQL for SQL Server or PL/SQL for Oracle. In this section, you will learn how to develop a SQL generation component (for SELECT queries) for an Entity Framework provider. For information about insert, update, and delete queries, see Modification SQL Generation. To understand this section, you should be familiar with the Entity Framework and the ADO.NET Provider Model. You should also understand command trees and DbExpression. The Role of the SQL Generation ModuleThe SQL generation module of an Entity Framework provider translates a given query command tree into a single SQL SELECT statement that targets a SQL:1999-compliant database. The generated SQL should have as few nested queries as possible. The SQL generation module should not simplify the output query command tree. The Entity Framework will do this, for example by eliminating joins and collapsing consecutive filter nodes. The DbProviderServices class is the starting point for accessing the SQL generation layer to convert command trees into DbCommand. In This SectionThe Shape of the Command Trees Generating SQL from Command Trees - Best Practices SQL Generation in the Sample Provider See alsoThe Shape of the Command TreesThe SQL generation module is responsible for generating a backend specific SQL query based on a given input query command tree expression. This section discusses the characteristics, properties, and structure of the query command trees. Query Command Trees OverviewA query command tree is an object model representation of a query. Query command trees serve two purposes:
Query command trees support richer semantics than SQL:1999 compliant queries, including support for working with nested collections and type operations, like checking whether an entity is of a particular type, or filtering sets based on a type. The DBQueryCommandTree.Query property is the root of the expression tree that describes the query logic. The DBQueryCommandTree.Parameters property contains a list of parameters that are used in the query. The expression tree is composed of DbExpression objects. A DbExpression object represents some computation. Several kinds of expressions are provided by the Entity Framework for composing query expressions, including constants, variables, functions, constructors, and standard relational operators like filter and join. Every DbExpression object has a ResultType property that represents the type of the result produced by that expression. This type is expressed as a TypeUsage. Shapes of the Output Query Command TreeOutput query command trees closely represent relational (SQL) queries and adhere to much stricter rules than those that apply to query command trees. They typically contain constructs that are easily translated to SQL. Input command trees are expressed against the conceptual model, which supports navigation properties, associations among entities, and inheritance. Output command trees are expressed against the storage model. Input command trees allow you to project nested collections, but output command trees do not. Output query command trees are built using a subset of the available DbExpression objects and even some expressions in that subset have restricted usage. Type operations, like checking whether a given expression is of a particular type or filtering sets based on a type, are not present in output command trees. In output command trees, only expressions that return Boolean values are used for projections and only for predicates in expressions requiring a predicate, like a filter or a case statement. The root of an output query command trees is a DbProjectExpression object. Expression Types Not Present in Output Query Command TreesThe following expression types are not valid in an output query command tree and do not need to be handled by providers:
Expression Restrictions and NotesMany expressions can only be used in a restricted manner in output query command trees: DbFunctionExpressionThe following function types can be passed:
Canonical functions (see Canonical Functions for more information) are specified as part of the Entity Framework, and providers should supply implementations for canonical functions based on those specifications. Store functions are based on the specifications in the corresponding provider manifest. User defined functions are based on specifications in the SSDL. Also, functions having the NiladicFunction attribute have no arguments and should be translated without the parenthesis at the end. That is, to <functionName> instead of <functionName>(). DbNewInstanceExpressionDbNewInstanceExpression can only occur in the following two cases:
DbVariableReferenceExpressionA DbVariableReferenceExpression has to be a child of DbPropertyExpression node. DbGroupByExpressionThe Aggregates property of a DbGroupByExpression can only have elements of type DbFunctionAggregate. There are no other aggregate types. DbLimitExpressionThe property Limit can only be a DbConstantExpression or a DbParameterReferenceExpression. Also property WithTies is always false as of version 3.5 of the .NET Framework. DbScanExpressionWhen used in output command trees, the DbScanExpression effectively represents a scan over a table, a view, or a store query, represented by EntitySetBase::Target. If the metadata property "Defining Query" of the target is non-null, then it represents a query, the query text for which is provided in that metadata property in the provider’s specific language (or dialect) as specified in the store schema definition. Otherwise, the target represents a table or a view. Its schema prefix is either in the "Schema" metadata property, if not null, otherwise is the entity container name. The table or view name is either the "Table" metadata property, if not null, otherwise the Name property of the entity set base. All these properties originate from the definition of the corresponding EntitySet in the store schema definition file (the SSDL). Using Primitive TypesWhen primitive types are referenced in output command trees, they are typically referenced in the conceptual model's primitive types. However, for certain expressions, providers need the corresponding store primitive type. Examples of such expressions include DbCastExpression and possibly DbNullExpression, if the provider needs to cast the null to the corresponding type. In these cases, providers should do the mapping to the provider type based on the primitive type kind and its facets. See alsoGenerating SQL from Command Trees - Best PracticesOutput query command trees closely model queries expressible in SQL. However, there are certain common challenges for provider writers when generating SQL from an output command tree. This topic discusses these challenges. In the next topic, the sample provider shows how to address these challenges. Group DbExpression Nodes in a SQL SELECT StatementA typical SQL statement has a nested structure of the following shape: SELECT … FROM … WHERE … GROUP BY … ORDER BY … One or more clauses may be empty. A nested SELECT statement could occur in any of the lines. A possible translation of a query command tree into a SQL SELECT statement would produce one subquery for every relational operator. However, that would lead to unnecessary nested subqueries that would be difficult to read. On some data stores, the query may perform poorly. As an example, consider the following query command tree Project ( a.x, a = Filter( b.y = 5, b = Scan("TableA") ) ) An inefficient translation would produce: SELECT a.x FROM ( SELECT * FROM TableA as b WHERE b.y = 5) as a Note that every relational expression node becomes a new SQL SELECT statement. Therefore, it is important to aggregate as many expression nodes as possible into a single SQL SELECT statement while preserving correctness. The result of such aggregation for the example presented above would be: SELECT b.x FROM TableA as b WHERE b.y = 5 Flatten Joins in a SQL SELECT StatementOne case of aggregating multiple nodes into a single SQL SELECT statement is aggregating multiple join expressions into a single SQL SELECT statement. DbJoinExpression represents a single join between two inputs. However, as part of a single SQL SELECT statement, more than one join can be specified. In that case the joins are performed in the order specified. Left spine joins, (joins that appear as a left child of another join) can be more easily flattened into a single SQL SELECT statement. For example, consider the following query command tree: InnerJoin( a = LeftOuterJoin( b = Extent("TableA") c = Extent("TableB") ON b.y = c.x ), d = Extent("TableC") ON a.b.y = d.z ) This can be correctly translated into: SELECT * FROM TableA as b LEFT OUTER JOIN TableB as c ON b.y = c.x INNER JOIN TableC as d ON b.y = d.z However, non-left spine joins cannot easily be flattened, and you should not try to flatten them. For example, the joins in the following query command tree: InnerJoin( a = Extent("TableA") b = LeftOuterJoin( c = Extent("TableB") d = Extent("TableC") ON c.y = d.x), ON a.z = b.c.y ) Would be translated to a SQL SELECT statement with a sub-query. SELECT * FROM TableA as a INNER JOIN (SELECT * FROM TableB as c LEFT OUTER JOIN TableC as d ON c.y = d.x) as b ON b.y = d.z Input Alias RedirectingTo explain input alias redirecting, consider the structure of the relational expressions, such as DbFilterExpression, DbProjectExpression, DbCrossJoinExpression, DbJoinExpression, DbSortExpression, DbGroupByExpression, DbApplyExpression, and DbSkipExpression. Each of these types has one or more Input properties that describe an input collection, and a binding variable corresponding to each input is used to represent each element of that input during a collection traversal. The binding variable is used when referring to the input element, for example in the Predicate property of a DbFilterExpression or the Projection property of a DbProjectExpression. When aggregating more relational expression nodes into a single SQL SELECT statement, and evaluating an expression that is part of a relational expression (for example part of the Projection property of a DbProjectExpression) the binding variable that it uses may not be the same as the alias of the input, as multiple expression bindings would have to be redirected to a single extent. This problem is called alias renaming. Consider the first example in this topic. If doing the naïve translation and translating the Projection a.x (DbPropertyExpression(a, x)), it is correct to translate it into a.x because we have aliased the input as "a" to match the binding variable. However, when aggregating both the nodes into a single SQL SELECT statement, you need to translate the same DbPropertyExpression into b.x, as the input has been aliased with "b". Join Alias FlatteningUnlike any other relational expression in an output command tree, the DbJoinExpression outputs a result type that is a row consisting of two columns, each of which corresponds to one of the inputs. When a DbPropertyExpression is built to access a scalar property originating from a join, it is over another DbPropertyExpression. Examples include "a.b.y" in example 2 and "b.c.y" in example 3. However in the corresponding SQL statements these are referred as "b.y". This re-aliasing is called join alias flattening. Column Name and Extent Alias RenamingIf a SQL SELECT query that has a join has to be completed with a projection, when enumerating all the participating columns from the inputs, a name collision may occur, as more than one input may have the same column name. Use a different name for the column to avoid the collision. Also, when flattening joins, participating tables (or subqueries) may have colliding aliases in which case these need to be renamed. Avoid SELECT *Do not use SELECT * to select from base tables. The storage model in an Entity Framework application may only include a subset of the columns that are in the database table. In this case, SELECT * may produce an incorrect result. Instead, you should specify all participating columns by using the column names from the result type of the participating expressions. Reuse of ExpressionsExpressions may be reused in the query command tree passed by the Entity Framework. Do not assume that each expression appears only once in the query command tree. Mapping Primitive TypesWhen mapping conceptual (EDM) types to provider types, you should map to the widest type (Int32) so that all possible values fit. Also, avoid mapping to types that cannot be used for many operations, like BLOB types (for example, ntext in SQL Server). See alsoSQL Generation in the Sample ProviderThe Entity Framework Sample Provider demonstrates the new components of ADO.NET Data Providers that support the Entity Framework. It works with a SQL Server 2005 database and is implemented as a wrapper for the System.Data.SqlClient ADO.NET 2.0 Data Provider. The SQL Generation module of the Sample Provider (located under the SQL Generation folder, except for the file DmlSqlGenerator.cs) takes an input DbQueryCommandTree and produces a single SQL SELECT statement. See alsoArchitecture and DesignThe SQL generation module in the Sample Provider is implemented as a visitor on the expression tree that represents the command tree. The generation is done in a single pass over the expression tree. The nodes of the tree are processed from the bottom up. First, an intermediate structure is produced: SqlSelectStatement or SqlBuilder, both implementing ISqlFragment. Next, the string SQL statement is produced from that structure. There are two reasons for the intermediate structure:
In the first phase, while visiting the expression tree, expressions are grouped into SqlSelectStatements, joins are flattened, and join aliases are flattened. During this pass, Symbol objects represent columns or input aliases that may be renamed. In the second phase, while producing the actual string, aliases are renamed. Data StructuresThis section discusses the types used in the Sample Provider that you use to build a SQL statement. ISqlFragmentThis section covers the classes that implement the ISqlFragment interface, which serves two purposes:
internal interface ISqlFragment { void WriteSql(SqlWriter writer, SqlGenerator sqlGenerator); } SqlBuilderSqlBuilder is a gathering device for the final SQL string, similar to StringBuilder. It consists of the strings that make up the final SQL, along with ISqlFragments that can be converted into strings. internal sealed class SqlBuilder : ISqlFragment { public void Append(object s) public void AppendLine() public bool IsEmpty } SqlSelectStatementSqlSelectStatement represents a canonical SQL SELECT statement of the shape "SELECT … FROM .. WHERE … GROUP BY … ORDER BY". Each of the SQL clauses is represented by a StringBuilder. In addition, it tracks whether Distinct has been specified and whether the statement is topmost. If the statement is not topmost, the ORDER BY clause is omitted unless the statement also has a TOP clause. FromExtents contains the list of inputs for the SELECT statement. There is usually just one element in this. SELECT statements for joins may temporarily have more than one element. If the SELECT statement is created by a Join node, SqlSelectStatement maintains a list of all the extents that have been flattened in the join in AllJoinExtents. OuterExtents represents outer references of the SqlSelectStatement and is used for input alias renaming. internal sealed class SqlSelectStatement : ISqlFragment { internal bool IsDistinct { get, set }; internal bool IsTopMost internal List<Symbol> AllJoinExtents { get, set }; internal List<Symbol> FromExtents { get}; internal Dictionary<Symbol, bool> OuterExtents { get}; internal TopClause Top { get, set }; internal SqlBuilder Select {get}; internal SqlBuilder From internal SqlBuilder Where internal SqlBuilder GroupBy public SqlBuilder OrderBy } TopClauseTopClause represents the TOP expression in a SqlSelectStatement. The TopCount property indicates how many TOP rows should be selected. When WithTies is true, the TopClause was built from a DbLimitExpression. class TopClause : ISqlFragment { internal bool WithTies {get} internal ISqlFragment TopCount {get} internal TopClause(ISqlFragment topCount, bool withTies) internal TopClause(int topCount, bool withTies) } SymbolsThe Symbol-related classes and the symbol table perform input alias renaming, join alias flattening, and column alias renaming. The Symbol class represents an extent, a nested SELECT statement, or a column. It is used instead of an actual alias to allow for renaming after it has been used and it also carries additional information for the artifact it represents (like the type). class Symbol : ISqlFragment { internal Dictionary<string, Symbol> Columns {get} internal bool NeedsRenaming {get, set} internal bool IsUnnest {get, set} //not used public string Name{get} public string NewName {get,set} internal TypeUsage Type {get, set} public Symbol(string name, TypeUsage type) } Name stores the original alias for the represented extent, nested SELECT statement, or a column. NewName stores the alias that will be used in the SQL SELECT statement. It is originally set to Name, and only renamed if needed when generating the final string query. Type is only useful for symbols representing extents and nested SELECT statements. SymbolPairThe SymbolPair class addresses record flattening. Consider a property expression D(v, "j3.j2.j1.a.x") where v is a VarRef, j1, j2, j3 are joins, a is an extent, and x is a columns. This has to be translated eventually into {j'}.{x'}. The source field represents the outermost SqlStatement, representing a join expression (say j2); this is always a Join symbol. The column field moves from one join symbol to the next until it stops at a non-join symbol. This is returned when visiting a DbPropertyExpression but is never added to a SqlBuilder. class SymbolPair : ISqlFragment { public Symbol Source; public Symbol Column; public SymbolPair(Symbol source, Symbol column) } JoinSymbolA Join symbol is a Symbol that represents a nested SELECT statement with a join or a join input. internal sealed class JoinSymbol : Symbol { internal List<Symbol> ColumnList {get, set} internal List<Symbol> ExtentList {get} internal List<Symbol> FlattenedExtentList {get, set} internal Dictionary<string, Symbol> NameToExtent {get} internal bool IsNestedJoin {get, set} public JoinSymbol(string name, TypeUsage type, List<Symbol> extents) } ColumnList represents the list of columns in the SELECT clause if this symbol represents a SQL SELECT statement. ExtentList is the list of extents in the SELECT clause. If the join has multiple extents flattened at the top level, FlattenedExtentList tracks the extents to ensure that extent aliases are renamed correctly. NameToExtent has all the extents in ExtentList as a dictionary. IsNestedJoin is used to determine whether a JoinSymbol is an ordinary join symbol or one that has a corresponding SqlSelectStatement. All the lists are set exactly once and then used for lookups or enumeration. SymbolTableSymbolTable is used to resolve variable names to Symbols. SymbolTable is implemented as a stack with a new entry for each scope. Lookups search from the top of the stack to the bottom until an entry is found. internal sealed class SymbolTable { internal void EnterScope() internal void ExitScope() internal void Add(string name, Symbol value) internal Symbol Lookup(string name) } There is only one SymbolTable per one instance of the Sql Generation module. Scopes are entered and exited for each relational node. All symbols in earlier scopes are visible to later scopes unless hidden by other symbols with the same name. Global State for the VisitorTo assist in renaming of aliases and columns, maintain a list of all the column names (AllColumnNames) and extent aliases (AllExtentNames) that have been used in the first pass over the query tree. The symbol table resolves variable names to Symbols. IsVarRefSingle is only used for verification purposes, it is not strictly necessary. The two stacks used via CurrentSelectStatement and IsParentAJoin are used to pass "parameters" from parent to child nodes, since the visitor pattern does not allow us to pass parameters. internal Dictionary<string, int> AllExtentNames {get} internal Dictionary<string, int> AllColumnNames {get} SymbolTable symbolTable = new SymbolTable(); bool isVarRefSingle = false; Stack<SqlSelectStatement> selectStatementStack; private SqlSelectStatement CurrentSelectStatement{get} Stack<bool> isParentAJoinStack; private bool IsParentAJoin{get} Common ScenariosThis section discusses common provider scenarios. Grouping Expression Nodes into SQL StatementsA SqlSelectStatement is created when the first relational node is encountered (typically a DbScanExpression extent) when visiting the tree from the bottom up. To produce a SQL SELECT statement with as few nested queries as possible, aggregate as many of its parent nodes as possible in that SqlSelectStatement. The decision of whether a given (relational) node can be added to the current SqlSelectStatement (the one returned when visiting the input) or if a new statement needs to be started is computed by the method IsCompatible and depends on what is already in the SqlSelectStatement, which depends on what nodes were below the given node. Typically, if SQL statement clauses are evaluated after clauses where the nodes being considered for merging are not empty, the node cannot be added to the current statement. For example, if the next node is a Filter, that node can be incorporated into the current SqlSelectStatement only if the following is true:
This does not apply to non-relational nodes like DbConstantExpression or arithmetic expressions, because these are always included as part of an existing SqlSelectStatement. Also, when encountering the root of join tree (a join node that does not have a join parent), a new SqlSelectStatement is started. All of its left spine join children are aggregated into that SqlSelectStatement. Whenever a new SqlSelectStatement is started, and the current one is added to the input, the current SqlSelectStatement may need to be completed by adding projection columns (a SELECT clause) if one does not exist. This is done with the method AddDefaultColumns, which looks at the FromExtents of the SqlSelectStatement and adds all the columns that the list of extents represented by FromExtents brings in scope to the list of projected columns. This is done, because at that point, it is unknown which columns are referenced by the other nodes. This can be optimized to only project the columns that can later be used. Join FlatteningThe IsParentAJoin property helps determine whether a given join can be flattened. In particular, IsParentAJoin returns true only for the left child of a join and for each DbScanExpression that is an immediate input to a join, in which case that child node reuses the same SqlSelectStatement that the parent would later use. For more information, see "Join Expressions". Input Alias RedirectingInput alias redirecting is accomplished with the symbol table. To explain input alias redirecting, refer to the first example in Generating SQL from Command Trees - Best Practices. There "a" needed to be redirected to "b" in the projection. When a SqlSelectStatement object is created, the extent that is the input to the node is put in the From property of the SqlSelectStatement. A Symbol (<symbol_b>) is created based on the input binding name ("b") to represent that extent and "AS " + <symbol_b> is appended to the From Clause. The symbol is also added to the FromExtents property. The symbol is also added to the symbol table to link the input binding name to it ("b", <symbol_b>). If a subsequent node reuses that SqlSelectStatement, it adds an entry to the symbol table to link its input binding name to that symbol. In our example, the DbProjectExpression with the input binding name of "a" would reuse the SqlSelectStatement and add ("a", < symbol_b>) to the table. When expressions reference the input binding name of the node that is reusing the SqlSelectStatement, that reference is resolved using the symbol table to the correct redirected symbol. When "a" from "a.x" is resolved while visiting the DbVariableReferenceExpression representing "a" it will resolve to the Symbol <symbol_b>. Join Alias FlatteningJoin alias flattening is achieved when visiting a DbPropertyExpression as described in the section titled DbPropertyExpression. Column Name and Extent Alias RenamingThe issue of column name and extent alias renaming is addressed by using symbols that only get substituted with aliases in the second phase of the generation described in the section titled Second Phase of SQL Generation: Generating the String Command. First Phase of the SQL Generation: Visiting the Expression TreeThis section describes the first phase of SQL generation, when the expression representing the query is visited and an intermediate structure is produced, either a SqlSelectStatement or a SqlBuilder. This section describes the principles of visiting different expression node categories, and details of visiting specific expression types. Relational (Non-Join) NodesThe following expression types support non-join nodes:
Visiting these nodes follows the following pattern:
DbSkipExpression not have a direct equivalent in SQL. Logically, it is translated into: SELECT Y.x1, Y.x2, ..., Y.xn FROM ( SELECT X.x1, X.x2, ..., X.xn, row_number() OVER (ORDER BY sk1, sk2, ...) AS [row_number] FROM input as X ) as Y WHERE Y.[row_number] > count ORDER BY sk1, sk2, ... Join ExpressionsThe following are considered join expressions and they are processed in a common way, by the VisitJoinExpression method:
The following are the visit steps: First, before visiting the children, IsParentAJoin is invoked to check whether the join node is a child of a join along a left spine. If it returns false, a new SqlSelectStatement is started. In that sense, joins are visited differently from the rest of the nodes, as the parent (the join node) creates the SqlSelectStatement for the children to possibly use. Second, process the inputs one at a time. For each input:
Third, the join condition (if any) is visited. Set OperationsThe set operations DbUnionAllExpression, DbExceptExpression, and DbIntersectExpression are processed by the method VisitSetOpExpression. It creates a SqlBuilder of the shape <leftSqlSelectStatement> <setOp> <rightSqlSelectStatement> Where <leftSqlSelectStatement> and <rightSqlSelectStatement> are SqlSelectStatements obtained by visiting each of the inputs, and <setOp> is the corresponding operation (UNION ALL for example). DbScanExpressionIf visited in a join context (as an input to a join that is a left child of another join), DbScanExpression returns a SqlBuilder with the target SQL for the corresponding target, which is either a defining query, table, or a view. Otherwise, a new SqlSelectStatement is created with the FROM field set to correspond to the corresponding target. DbVariableReferenceExpressionThe visit of a DbVariableReferenceExpression returns the Symbol corresponding to that variable reference expression based on a look up in the symbol table. DbPropertyExpressionJoin alias flattening is identified and processed when visiting a DbPropertyExpression. The Instance property is first visited and the result is a Symbol, a JoinSymbol, or a SymbolPair. Here is how these three cases are handled:
DbNewInstanceExpressionWhen used as the Projection property of DbProjectExpression, DbNewInstanceExpression produces a comma-separated list of the arguments to represent the projected columns. When DbNewInstanceExpression has a collection return type, and defines a new collection of the expressions provided as arguments, the following three cases are handled separately:
If DbNewInstanceExpression has no arguments (represents an empty table), DbNewInstanceExpression is translated into: SELECT CAST(NULL AS <primitiveType>) as X FROM (SELECT 1) AS Y WHERE 1=0 Otherwise DbNewInstanceExpression builds a union-all ladder of the arguments: SELECT <visit-result-arg1> as X UNION ALL SELECT <visit-result-arg2> as X UNION ALL … UNION ALL SELECT <visit-result-argN> as X DbFunctionExpressionCanonical and built-in functions are processed the same way: if they need special handling (TRIM(string) to LTRIM(RTRIM(string), for example), the appropriate handler is invoked. Otherwise they are translated to FunctionName(arg1, arg2, ..., argn). Dictionaries are used to keep track of which functions need special handling and their appropriate handlers. User-defined functions are translated to NamespaceName.FunctionName(arg1, arg2, ..., argn). DbElementExpressionThe method that visits DbElementExpression is only invoked for visiting a DbElementExpression when used to represent a scalar subquery. Therefore, DbElementExpression translates into a complete SqlSelectStatement and adds brackets around it. DbQuantifierExpressionDepending on the expression type (Any or All), DbQuantifierExpression is translated it as: Any(input, x) => Exists(Filter(input,x)) All(input, x) => Not Exists(Filter(input, not(x)) DbNotExpressionIn some cases it is possible to collapse the translation of DbNotExpression with its input expression. For example: Not(IsNull(a)) => "a IS NOT NULL" Not(All(input, x) => Not (Not Exists(Filter(input, not(x))) => Exists(Filter(input, not(x)) The reason the second collapse is performed is because inefficiencies were introduced by the provider when translating DbQuantifierExpression of type All. Thus the Entity Framework could not have done the simplification. DbIsEmptyExpressionDbIsEmptyExpression is translated as: IsEmpty(input) = Not Exists(input) Second Phase of SQL Generation: Generating the String CommandWhen generating a string SQL command, the SqlSelectStatement produces actual aliases for the symbols, which addresses the issue of column name and extent alias renaming. Extent alias renaming occurs while writing the SqlSelectStatement object into a string. First create a list of all the aliases used by the outer extents. Each symbol in the FromExtents (or AllJoinExtents if it is non-null), gets renamed if it collides with any of the outer extents. If renaming is needed, it will not conflict with any of the extents collected in AllExtentNames. Column renaming occurs while writing a Symbol object to a string. AddDefaultColumns in the first phase has determined if a certain column symbol has to be renamed. In the second phase only the rename occurs making sure that the name produced does not conflict with any name used in AllColumnNames To produce unique names both for extent aliases and for columns, use <existing_name>_n where n is the smallest alias that has not been used yet. The global list of all aliases increases the need for cascading renames. See alsoWalkthrough: SQL GenerationThis topic illustrates how SQL generation occurs in the Sample Provider. The following Entity SQL query uses the model that is included with the sample provider: SELECT j1.ProductId, j1.ProductName, j1.CategoryName, j2.ShipCountry, j2.ProductId FROM ( SELECT P.ProductName, P.ProductId, P.Category.CategoryName FROM NorthwindEntities.Products AS P) as j1 INNER JOIN (SELECT OD.ProductId, OD.Order.ShipCountry as ShipCountry FROM NorthwindEntities.OrderDetails AS OD) as j2 ON j1.ProductId == j2.ProductId The query produces the following output command tree that is passed to the provider: DbQueryCommandTree |_Parameters |_Query : Collection{Record['C1'=Edm.Int32, 'ProductID'=Edm.Int32, 'ProductName'=Edm.String, 'CategoryName'=Edm.String, 'ShipCountry'=Edm.String, 'ProductID1'=Edm.Int32]} |_Project |_Input : 'Join4' | |_InnerJoin | |_Left : 'Join1' | | |_LeftOuterJoin | | |_Left : 'Extent1' | | | |_Scan : dbo.Products | | |_Right : 'Extent2' | | | |_Scan : dbo.Categories | | |_JoinCondition | | |_ | | |_Var(Extent1).CategoryID | | |_= | | |_Var(Extent2).CategoryID | |_Right : 'Join3' | | |_LeftOuterJoin | | |_Left : 'Extent3' | | | |_Scan : dbo.OrderDetails | | |_Right : 'Join2' | | | |_LeftOuterJoin | | | |_Left : 'Extent4' | | | | |_Scan : dbo.Orders | | | |_Right : 'Extent5' | | | | |_Scan : dbo.InternationalOrders | | | |_JoinCondition | | | |_ | | | |_Var(Extent4).OrderID | | | |_= | | | |_Var(Extent5).OrderID | | |_JoinCondition | | |_ | | |_Var(Extent3).OrderID | | |_= | | |_Var(Join2).Extent4.OrderID | |_JoinCondition | |_ | |_Var(Join1).Extent1.ProductID | |_= | |_Var(Join3).Extent3.ProductID |_Projection |_NewInstance : Record['C1'=Edm.Int32, 'ProductID'=Edm.Int32, 'ProductName'=Edm.String, 'CategoryName'=Edm.String, 'ShipCountry'=Edm.String, 'ProductID1'=Edm.Int32] |_Column : 'C1' | |_1 |_Column : 'ProductID' | |_Var(Join4).Join1.Extent1.ProductID |_Column : 'ProductName' | |_Var(Join4).Join1.Extent1.ProductName |_Column : 'CategoryName' | |_Var(Join4).Join1.Extent2.CategoryName |_Column : 'ShipCountry' | |_Var(Join4).Join3.Join2.Extent4.ShipCountry |_Column : 'ProductID1' |_Var(Join4).Join3.Extent3.ProductID This topic describes how to translate this output command tree into the following SQL statements. SELECT 1 AS [C1], [Extent1].[ProductID] AS [ProductID], [Extent1].[ProductName] AS [ProductName], [Extent2].[CategoryName] AS [CategoryName], [Join3].[ShipCountry] AS [ShipCountry], [Join3].[ProductID] AS [ProductID1] FROM [dbo].[Products] AS [Extent1] LEFT OUTER JOIN [dbo].[Categories] AS [Extent2] ON [Extent1].[CategoryID] = [Extent2].[CategoryID] INNER JOIN (SELECT [Extent3].[OrderID] AS [OrderID1], [Extent3].[ProductID] AS [ProductID], [Extent3].[UnitPrice] AS [UnitPrice], [Extent3].[Quantity] AS [Quantity], [Extent3].[Discount] AS [Discount], [Join2].[OrderID2], [Join2].[CustomerID], [Join2].[EmployeeID], [Join2].[OrderDate], [Join2].[RequiredDate], [Join2].[ShippedDate], [Join2].[Freight], [Join2].[ShipName], [Join2].[ShipAddress], [Join2].[ShipCity], [Join2].[ShipRegion], [Join2].[ShipPostalCode], [Join2].[ShipCountry], [Join2].[OrderID3], [Join2].[CustomsDescription], [Join2].[ExciseTax] FROM [dbo].[OrderDetails] AS [Extent3] LEFT OUTER JOIN (SELECT [Extent4].[OrderID] AS [OrderID2], [Extent4].[CustomerID] AS [CustomerID], [Extent4].[EmployeeID] AS [EmployeeID], [Extent4].[OrderDate] AS [OrderDate], [Extent4].[RequiredDate] AS [RequiredDate], [Extent4].[ShippedDate] AS [ShippedDate], [Extent4].[Freight] AS [Freight], [Extent4].[ShipName] AS [ShipName], [Extent4].[ShipAddress] AS [ShipAddress], [Extent4].[ShipCity] AS [ShipCity], [Extent4].[ShipRegion] AS [ShipRegion], [Extent4].[ShipPostalCode] AS [ShipPostalCode], [Extent4].[ShipCountry] AS [ShipCountry], [Extent5].[OrderID] AS [OrderID3], [Extent5].[CustomsDescription] AS [CustomsDescription], [Extent5].[ExciseTax] AS [ExciseTax] FROM [dbo].[Orders] AS [Extent4] LEFT OUTER JOIN [dbo].[InternationalOrders] AS [Extent5] ON [Extent4].[OrderID] = [Extent5].[OrderID] ) AS [Join2] ON [Extent3].[OrderID] = [Join2].[OrderID2] ) AS [Join3] ON [Extent1].[ProductID] = [Join3].[ProductID] First Phase of SQL Generation: Visiting the Expression TreeThe following figure illustrates the initial empty state of the visitor. Throughout this topic, only the properties relevant to the walkthrough explanation are shown. When the Project node is visited, VisitInputExpression is called over its input (Join4), which triggers the visit of Join4 by the method VisitJoinExpression. Because this is a topmost join, IsParentAJoin returns false and a new SqlSelectStatement (SelectStatement0) is created and pushed on the SELECT statement stack. Also, a new scope (scope0) is entered in the symbol table. Before the first (left) input of the join is visited, 'true' is pushed on the IsParentAJoin stack. Right before Join1, which is the left input of Join4, is visited, the state of the visitor is as shown in the next figure. When the join visit method is invoked over Join4, IsParentAJoin is true, thus it reuses the current select statement SelectStatement0. A new scope is entered (scope1). Before visiting its left child, Extent1, another true is pushed on the IsParentAJoin stack. When Extent1 is visited, because IsParentAJoin returns true, it returns a SqlBuilder containing "[dbo].[Products]". The control returns to the method visiting Join4. An entry is popped from IsParentAJoin, and ProcessJoinInputResult is called, which appends the result of visiting Extent1 to the From clause of SelectStatement0. A new from symbol, symbol_Extent1, for the input binding name "Extent1" is created, added to the FromExtents of SelectStatement0, and also "As" and symbol_Extent1 are appended to the from clause. A new entry is added to AllExtentNames for "Extent1" with the value of 0. A new entry is added to the current scope in the symbol table to associate "Extent1" with its symbol symbol_Extent1. Symbol_Extent1 is also added to the AllJoinExtents of the SqlSelectStatement. Before the right input of Join1 is visited, "LEFT OUTER JOIN" is added to the From clause of SelectStatement0. Because the right input is a Scan expression, true is again pushed to the IsParentAJoin stack. The state before visiting the right input as shown in the next figure. The right input is processed in the same way as the left input. The state after visiting the right input is shown in the next figure. Next "false" is pushed on the IsParentAJoin stack and the join condition Var(Extent1).CategoryID == Var(Extent2).CategoryID is processed. Var(Extent1) is resolved to <symbol_Extent1> after a look up in the symbol table. Because the instance is resolved to a simple Symbol, as a result of processing Var(Extent1).CategoryID, a SqlBuilder with <symbol1>."CategoryID" is returned. Similarly the other side of the comparison is processed, and the result of visiting the join condition is appended to the FROM clause of SelectStatement1 and the value "false" is popped from the IsParentAJoin stack. With this, Join1 has completely been processed, and a scope is popped from the symbol table. Control returns to processing Join4, the parent of Join1. Because the child reused the Select statement, the Join1 extents are replaced with a single Join symbol <joinSymbol_Join1>. Also a new entry is added to the symbol table to associate Join1 with <joinSymbol_Join1>. The next node to be processed is Join3, the second child of Join4. As it is a right child, "false" is pushed to the IsParentAJoin stack. The state of the visitor at this point is illustrated in the next figure. For Join3, IsParentAJoin returns false and needs to start a new SqlSelectStatement (SelectStatement1) and push it on the stack. Processing continues as it did with the previous the previous joins, a new scope is pushed on the stack and the children are processed. The left child is an Extent (Extent3) and the right child is a join (Join2) which also needs to start a new SqlSelectStatement: SelectStatement2. The children on Join2 are Extents as well and are aggregated into SelectStatement2. The state of the visitor right after Join2 is visited, but before its post-processing (ProcessJoinInputResult) is done is shown in the next figure: In the previous figure, SelectStatement2 is shown as free floating because it was popped out of the stack, but not yet post processed by the parent. It needs to be added to the FROM part of the parent, but it is not a complete SQL statement without a SELECT clause. So, at this point, the default columns (all the columns produced by its inputs) are added to the select list by the method AddDefaultColumns. AddDefaultColumns iterates over the symbols in FromExtents and for each symbol adds all the columns brought in scope. For a simple symbol, it looks at the symbol type to retrieve all its properties to be added. It also populates the AllColumnNames dictionary with the column names. The completed SelectStatement2 is appended to the FROM clause of SelectStatement1. Next, a new join symbol is created to represent Join2, it is marked as a nested join and added to the AllJoinExtents of SelectStatement1 and added to the symbol table. Now the join condition of Join3, Var(Extent3).OrderID = Var(Join2).Extent4.OrderID, needs to be processed. Processing of the left hand side is similar to the join condition of Join1. However, the processing of the right and side "Var(Join2).Extent4.OrderID" is different because join flattening is required. The next figure shows the state of the visitor right before the DbPropertyExpression "Var(Join2).Extent4.OrderID" is processed. Consider how "Var(Join2).Extent4.OrderID" is visited. First, the instance property "Var(Join2).Extent4" is visited, which is another DbPropertyExpression and first visits its instance "Var(Join2)". In the top most scope in the symbol table, "Join2" resolves to <joinSymbol_join2>. In the visit method for DbPropertyExpression processing "Var(Join2).Extent4" notice that a join symbol was returned when visiting the instance and flattening is required. Since it is a nested join, we look up the property "Extent4" in the NameToExtent dictionary of the join symbol, resolve it to <symbol_Extent4> and return a new SymbolPair(<joinSymbol_join2>, <symbol_Extent4>). Since a symbol pair is returned from the processing of the instance of "Var(Join2).Extent4.OrderID", the property "OrderID" is resolved from the ColumnPart of that symbol pair (<symbol_Extent4>), which has a list of the columns of the extent it represents. So, "Var(Join2).Extent4.OrderID" is resolved to { <joinSymbol_Join2>, ".", <symbol_OrderID>}. The join condition of Join4 is similarly processed. The control returns to the VisitInputExpression method that processed the top most project. Looking at the FromExtents of the returned SelectStatement0, the input is identified as a join, and removes the original extents and replaces them with a new extent with just the Join symbol. The symbol table is also updated and next the projection part of the Project is processed. The resolving of the properties and the flattening of the join extents is as described earlier. Finally, the following SqlSelectStatement is produced: SELECT: "1", " AS ", "[C1]", <symbol_Extent1>, ".", "[ProductID]", " AS ", "[ProductID]", <symbol_Extent1>, ".", "[ProductName]", " AS ", "[ProductName]", <symbol_Extent2>, ".", "[CategoryName]", " AS ", "[CategoryName]", <joinSymbol_Join3>, ".", <symbol_ShipCountry>, " AS ", "[ShipCountry]", <joinSymbol_Join3>, ".", <symbol_ProductID>, " AS ", "[ProductID1]" FROM: "[dbo].[Products]", " AS ", <symbol_Extent1>, "LEFT OUTER JOIN ""[dbo].[Categories]", " AS ", <symbol_Extent2>, " ON ", <symbol_Extent1>, ".", "[CategoryID]", " = ", <symbol_Extent2>, ".", "[CategoryID]", "INNER JOIN ", " (", SELECT: <symbol_Extent3>, ".", "[OrderID]", " AS ", <symbol_OrderID>, ", <symbol_Extent3>, ".", "[ProductID]", " AS ", <symbol_ProductID>, ..., <joinSymbol_Join2>, ".", <symbol_OrderID_2>, ", ", <joinSymbol_Join2>, ".", <symbol_CustomerID>, ...., <joinSymbol_Join2>, ".", <symbol_OrderID_3>, <joinSymbol_Join2>, ".", <symbol_CustomsDescription>, <joinSymbol_Join2>, ".", <symbol_ExciseTax> FROM: "[dbo].[OrderDetails]", " AS ", <symbol_Extent3>, "LEFT OUTER JOIN ", " (", SELECT: <symbol_Extent4>, ".", "[OrderID]", " AS ", <symbol_OrderID_2>, <symbol_Extent4>, ".", "[CustomerID]", " AS ", <symbol_CustomerID>, ... <symbol_Extent5>, ".", "[OrderID]", " AS ", <symbol_OrderID_3>, <symbol_Extent5>, ".", "[CustomsDescription]", " AS ", <symbol_CustomsDescription>, <symbol_Extent5>, ".", "[ExciseTax]", " AS ", <symbol_ExciseTax> FROM: "[dbo].[Orders]", " AS ", <symbol_Extent4>, "LEFT OUTER JOIN ", , "[dbo].[InternationalOrders]", " AS ", <symbol_Extent5>, " ON ", <symbol_Extent4>, ".", "[OrderID]", " = ", , <symbol_Extent5>, ".", "[OrderID]" " )", " AS ", <joinSymbol_Join2>, " ON ", , , <symbol_Extent3>, ".", "[OrderID]", " = ", , <joinSymbol_Join2>, ".", <symbol_OrderID_2> " )", " AS ", <joinSymbol_Join3>, " ON ", , , <symbol_Extent1>, ".", "[ProductID]", " = ", , <joinSymbol_Join3>, ".", <symbol_ProductID> Second Phase of SQL Generation: Generating the String CommandThe second phase produces actual names for the symbols, and we only focus on the symbols representing columns named "OrderID", as in this case a conflict needs to be resolved. These are highlighted in the SqlSelectStatement. Note that the suffixes used in the figure are only to emphasize that these are different instances, not to represent any new names, as at this stage their final names (possibly different form the original names) have not been assigned yet. The first symbol found that needs to be renamed is <symbol_OrderID>. Its new name is assigned as "OrderID1", 1 is marked as the last used suffix for "OrderID" and the symbol is marked as not needing renaming. Next, the first usage of <symbol_OrderID_2> is found. It is renamed to use the next available suffix ("OrderID2") and again marked as not needing renaming, so that next time it is used it does not get renamed. This is done for <symbol_OrderID_3> too. At the end of the second phase, the final SQL statement is generated. See alsoModification SQL GenerationThis section discusses how to develop a modification SQL generation module for your (SQL:1999-compliant database) provider. This module is responsible for translating a modification command tree into the appropriate SQL INSERT, UPDATE or DELETE statements. For information about SQL generation for select statements, see SQL Generation. Overview of Modification Command TreesThe modification SQL generation module generates database-specific modification SQL statements based on a given input DbModificationCommandTree. A DbModificationCommandTree is an object model representation of a modification DML operation (an insert, an update, or a delete operation), inheriting from DbCommandTree. There are three implementations of DbModificationCommandTree:
DbModificationCommandTree and its implementations that are produced by the Entity Framework always represent a single row operation. This section describes these types with their constraints in the .NET Framework version 3.5. DbModificationCommandTree has a Target property that represents the target set for the modification operation. The Target’s Expression property, which defines the input set is always DbScanExpression. A DbScanExpression can either represent a table or a view, or a set of data defined with a query if the metadata property "Defining Query" of its Target is non-null. A DbScanExpression that represents a query could only reach a provider as a target of modification if the set was defined by using a defining query in the model but no function was provided for the corresponding modification operation. Providers may not be able to support such a scenario (SqlClient, for example, does not). DbInsertCommandTree represents a single row insert operation expressed as a command tree. public sealed class DbInsertCommandTree : DbModificationCommandTree { public IList<DbModificationClause> SetClauses { get } public DbExpression Returning { get } } DbUpdateCommandTree represents a single-row update operation expressed as a command tree. DbDeleteCommandTree represents a single row delete operation expressed as a command tree. Restrictions on Modification Command Tree PropertiesThe following information and restrictions apply to the modification command tree properties. Returning in DbInsertCommandTree and DbUpdateCommandTreeWhen non-null, Returning indicates that the command returns a reader. Otherwise, the command should return a scalar value indicating the number of rows affected (inserted or updated). The Returning value specifies a projection of results to be returned based on the inserted or the updated row. It can only be of type DbNewInstanceExpression representing a row, with each of its arguments being a DbPropertyExpression over a DbVariableReferenceExpression representing a reference to the Target of the corresponding DbModificationCommandTree. The properties represented by the DbPropertyExpressions used in the property Returning are always store generated or computed values. In DbInsertCommandTree, Returning is not null when at least one property of the table in which the row is being inserted is specified as store generated or computed (marked as StoreGeneratedPattern.Identity or StoreGeneratedPattern.Computed in the ssdl). In DbUpdateCommandTrees, Returning is not null when at least one property of the table in which the row is being updated is specified as store computed (marked as StoreGeneratedPattern.Computed in the ssdl). SetClauses in DbInsertCommandTree and DbUpdateCommandTreeSetClauses specifies the list of insert or update set clauses that define the insert or update operation. The elements of the list are specified as type DbModificationClause, which specifies a single clause in an insert or update modification operation. DbSetClause inherits from DbModificationClause and specifies the clause in a modification operation that sets the value of a property. Beginning in version 3.5 of the .NET Framework, all elements in SetClauses are of type SetClause. Property specifies the property that should be updated. It is always a DbPropertyExpression over a DbVariableReferenceExpression, which represents a reference to the Target of the corresponding DbModificationCommandTree. Value specifies the new value with which to update the property. It is either of type DbConstantExpression or DbNullExpression. Predicate in DbUpdateCommandTree and DbDeleteCommandTreePredicate specifies the predicate used to determine which members of the target collection should be updated or deleted. It is an expression tree built of the following subset of DbExpressions:
Modification SQL Generation in the Sample ProviderThe Entity Framework Sample Provider demonstrates the components of ADO.NET Data Providers that support the Entity Framework. It targets a SQL Server 2005 database and is implemented as a wrapper on top of System.Data.SqlClient ADO.NET 2.0 Data Provider. The modification SQL generation module of the sample provider (located in the file SQL Generation\DmlSqlGenerator.cs) takes an input DbModificationCommandTree and produces a single modification SQL statement possibly followed by a select statement to return a reader if specified by the DbModificationCommandTree. Note that the shape of the commands generated is affected by the target SQL Server database. Helper Classes: ExpressionTranslatorExpressionTranslator serves as a common lightweight translator for all modification command tree properties of type DbExpression. It supports translation of only the expression types to which the properties of the modification command tree are constrained and is built with the particular constraints in mind. The following information discusses visiting specific expression types (nodes with trivial translations are omitted). DbComparisonExpressionWhen the ExpressionTranslator is constructed with preserveMemberValues = true, and when the constant to the right is a DbConstantExpression (instead of DbNullExpression), it associates the left operand (a DbPropertyExpressions) with that DbConstantExpression. That is used if a return Select statement needs to be generated to identify the affected row. DbConstantExpressionFor each visited constant a parameter is created. DbPropertyExpressionGiven that the Instance of the DbPropertyExpression always represents the input table, unless the generation has created an alias (which only happens in update scenarios when a table variable is used), no alias needs to be specified for the input; the translation defaults to the property name. Generating an Insert SQL CommandFor a given DbInsertCommandTree in the sample provider, the generated insert command follows one of the two insert templates below. The first template has a command to perform the insert given the values in the list of SetClauses, and a SELECT statement to return the properties specified in the Returning property for the inserted row if the Returning property was not null. The predicate element "@@ROWCOUNT > 0" is true if a row was inserted. The predicate element "keyMemberI = keyValueI | scope_identity()" takes the shape "keyMemberI = scope_identity()" only if keyMemberI is a store-generated key, because scope_identity() returns the last identity value inserted into an identity (store-generated) column. -- first insert Template INSERT <target> [ (setClauseProperty0, .. setClausePropertyN)] VALUES (setClauseValue0, .. setClauseValueN) | DEFAULT VALUES [SELECT <returning> FROM <target> WHERE @@ROWCOUNT > 0 AND keyMember0 = keyValue0 AND .. keyMemberI = keyValueI | scope_identity() .. AND keyMemberN = keyValueN] The second template is needed if the insert specifies inserting a row where the primary key is store-generated but is not an integer type and therefore can't be used with scope_identity()). It is also used if there is a compound store-generated key. -- second insert template DECLARE @generated_keys TABLE [(keyMember0, … keyMemberN) INSERT <target> [ (setClauseProperty0, .. setClausePropertyN)] OUTPUT inserted.KeyMember0, …, inserted.KeyMemberN INTO @generated_keys VALUES (setClauseValue0, .. setClauseValueN) | DEFAULT VALUES [SELECT <returning_over_t> FROM @generated_keys AS g JOIN <target> AS t ON g.KeyMember0 = t.KeyMember0 AND … g.KeyMemberN = t.KeyMemberN WHERE @@ROWCOUNT > 0 The following is an example that uses the model that is included with the sample provider. It generates an insert command from a DbInsertCommandTree. The following code inserts a Category: using (NorthwindEntities northwindContext = new NorthwindEntities()) { Category c = new Category(); c.CategoryName = "Test Category"; c.Description = "A new category for testing"; northwindContext.AddObject("Categories", c); northwindContext.SaveChanges(); } This code produces the following command tree, which is passed to the provider: DbInsertCommandTree |_Parameters |_Target : 'target' | |_Scan : dbo.Categories |_SetClauses | |_DbSetClause | | |_Property | | | |_Var(target).CategoryName | | |_Value | | |_'Test Category' | |_DbSetClause | | |_Property | | | |_Var(target).Description | | |_Value | | |_'A new category for testing' | |_DbSetClause | |_Property | | |_Var(target).Picture | |_Value | |_null |_Returning |_NewInstance : Record['CategoryID'=Edm.Int32] |_Column : 'CategoryID' |_Var(target).CategoryID The store command that the sample provider produces is the following SQL statement: insert [dbo].[Categories]([CategoryName], [Description], [Picture]) values (@p0, @p1, null) select [CategoryID] from [dbo].[Categories] where @@ROWCOUNT > 0 and [CategoryID] = scope_identity() Generating an Update SQL CommandFor a given DbUpdateCommandTree, the generated update command is based on the following template: -- UPDATE Template UPDATE <target> SET setClauseProperty0 = setClauseValue0, .. setClausePropertyN = setClauseValueN | @i = 0 WHERE <predicate> [SELECT <returning> FROM <target> WHERE @@ROWCOUNT > 0 AND keyMember0 = keyValue0 AND .. keyMemberI = keyValueI | scope_identity() .. AND keyMemberN = keyValueN] The set clause has the fake set clause ("@i = 0") only if no set clauses are specified. This is to ensure that any store-computed columns are recomputed. Only if the Returning property is not null, a select statement is generated to return the properties specified in the Returning property. The following example uses the model that is included with the sample provider to generate an update command. The following user code updates a Category: using (NorthwindEntities northwindContext = new NorthwindEntities()) { Category c = northwindContext.Categories.Where(i => i.CategoryName == "Test Category").First(); c.CategoryName = "New test name"; northwindContext.SaveChanges(); } This user code produces the following command tree, which is passed to the provider: DbUpdateCommandTree |_Parameters |_Target : 'target' | |_Scan : dbo.Categories |_SetClauses | |_DbSetClause | |_Property | | |_Var(target).CategoryName | |_Value | |_'New test name' |_Predicate | |_ | |_Var(target).CategoryID | |_= | |_10 |_Returning The sample provider produces the following store command: update [dbo].[Categories] set [CategoryName] = @p0 where ([CategoryID] = @p1) Generating a Delete SQL CommandFor a given DbDeleteCommandTree, the generated DELETE command is based on the following template: -- DELETE Template DELETE <target> WHERE <predicate> The following example uses the model that is included with the sample provider to generate a delete command. The following user code deletes a Category: using (NorthwindEntities northwindContext = new NorthwindEntities()) { Category c = northwindContext.Categories.Where(i => i.CategoryName == "New test name").First(); northwindContext.DeleteObject(c); northwindContext.SaveChanges(); } This user code produces the following command tree, which is passed to the provider. DbDeleteCommandTree |_Parameters |_Target : 'target' | |_Scan : dbo.Categories |_Predicate |_ |_Var(target).CategoryID |_= |_10 The following store command is produced by the sample provider: delete [dbo].[Categories] where ([CategoryID] = @p0) See alsoProvider Manifest SpecificationThis section discusses how a data store provider can support the types and functions in the data store. Entity Services operates independently of a specific data store provider yet still allows a data provider to explicitly define how models, mappings, and queries interact with an underlying data store. Without a layer of abstraction, Entity Services could only be targeted at a specific data store or data provider. Types that the provider supports are directly or indirectly supported by the underlying database. These types are not necessarily the exact store types, but the types the provider uses to support the Entity Framework. Provider/store types are described in the Entity Data Model (EDM) terms. Parameter and return types for the functions supported by the data store are specified in EDM terms. RequirementsThe Entity Framework and the data store need to be able to pass data back and forth in known types without any data loss or truncation. The provider manifest must be loadable by tools at design time without having to open a connection to the data store. The Entity Framework is case sensitive, but the underlying data store may not be. When EDM artifacts (identifiers and type names, for example) are defined and used in the manifest, they must use the Entity Framework case sensitivity. If data store elements that may be case sensitive appear in the provider manifest, that casing needs to be maintained in the provider manifest. The Entity Framework requires a provider manifest for all data providers. If you try to use a provider that does not have a provider manifest with the Entity Framework, you will get an error. The following table describes the kinds of exceptions the Entity Framework would throw when exceptions arise through provider interaction:
ScenariosA provider should support the following scenarios: Writing a Provider with Symmetric Type MappingYou can write a provider for the Entity Framework where each store type maps to a single EDM type, regardless of the mapping direction. For a provider type that has very simple mapping that corresponds with an EDM type, you can use a symmetric solution because the type system is simple or matches EDM types. You can use the simplicity of their domain and produce a static declarative provider manifest. You write an XML file that has two sections:
Writing a Provider with Asymmetric Type MappingWhen writing a data store provider for the Entity Framework, the EDM-to-provider type mapping for some types may be different from provider-to-EDM type mapping. For instance, unbounded EDM PrimitiveTypeKind.String may map to nvarchar(4000) on the provider, while nvarchar(4000) maps to the EDM PrimitiveTypeKind.String(MaxLength=4000). You write an XML file that has two sections:
Provider Manifest DiscoverabilityThe manifest is used indirectly by several component types in Entity Services (for example Tools or Query) but more directly leveraged by metadata through the use of the data store metadata loader. However, a given provider may support different stores or different versions of the same store. Therefore, a provider must report a different manifest for each supported data store. Provider Manifest TokenWhen a data store connection is opened, the provider can query for information to return the right manifest. This may not be possible in offline scenarios where connection information is not available or when it is not possible to connect to the store. Identify the manifest by using the ProviderManifestToken attribute of the Schema element in the .ssdl file. There is no required format for this attribute; the provider chooses the minimum information needed to identify a manifest without opening a connection to the store. For example: <Schema Namespace="Northwind" Provider="System.Data.SqlClient" ProviderManifestToken="2005" xmlns:edm="http://schemas.microsoft.com/ado/2006/04/edm/ssdl" xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl"> Provider Manifest Programming ModelProviders derive from DbXmlEnabledProviderManifest, which allows them to specify their manifests declaratively. The following illustration shows the class hierarchy of a provider: Discoverability APIThe provider manifest is loaded by the Store Metadata loader (StoreItemCollection), either by using a data store connection or a provider manifest token. Using a Data Store ConnectionWhen the data store connection is available, call DbProviderServices.GetProviderManifestToken to return the token that is passed to the GetProviderManifest method, which returns DbProviderManifest. This method delegates to the provider's implementation of GetDbProviderManifestToken. public string GetProviderManifestToken(DbConnection connection); public DbProviderManifest GetProviderManifest(string manifestToken); Using a Provider Manifest TokenFor the offline scenario, the token is picked from SSDL representation. The SSDL allows you to specify a ProviderManifestToken (see Schema Element (SSDL) for more information). For example, if a connection cannot be opened, the SSDL has a provider manifest token that specifies information about the manifest. public DbProviderManifest GetProviderManifest(string manifestToken); Provider Manifest SchemaThe schema of information defined for each provider contains the static information to be consumed by metadata: <?xml version="1.0" encoding="utf-8"?> <xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://schemas.microsoft.com/ado/2006/04/edm/providermanifest" xmlns:pm="http://schemas.microsoft.com/ado/2006/04/edm/providermanifest"> <xs:element name="ProviderManifest"> <xs:complexType> <xs:sequence> <xs:element name="Types" type="pm:TTypes" minOccurs="1" maxOccurs="1" /> <xs:element name="Functions" type="pm:TFunctions" minOccurs="0" maxOccurs="1"/> </xs:sequence> <xs:attribute name="Namespace" type="xs:string" use="required"/> </xs:complexType> </xs:element> <xs:complexType name="TVersion"> <xs:attribute name="Major" type="xs:int" use="required" /> <xs:attribute name="Minor" type="xs:int" use="required" /> <xs:attribute name="Build" type="xs:int" use="required" /> <xs:attribute name="Revision" type="xs:int" use="required" /> </xs:complexType> <xs:complexType name="TIntegerFacetDescription"> <xs:attribute name="Minimum" type="xs:int" use="optional" /> <xs:attribute name="Maximum" type="xs:int" use="optional" /> <xs:attribute name="DefaultValue" type="xs:int" use="optional" /> <xs:attribute name="Constant" type="xs:boolean" default="false" /> </xs:complexType> <xs:complexType name="TBooleanFacetDescription"> <xs:attribute name="DefaultValue" type="xs:boolean" use="optional" /> <xs:attribute name="Constant" type="xs:boolean" default="true" /> </xs:complexType> <xs:complexType name="TDateTimeFacetDescription"> <xs:attribute name="Constant" type="xs:boolean" default="false" /> </xs:complexType> <xs:complexType name="TFacetDescriptions"> <xs:choice maxOccurs="unbounded"> <xs:element name="Precision" minOccurs="0" maxOccurs="1" type="pm:TIntegerFacetDescription"/> <xs:element name="Scale" minOccurs="0" maxOccurs="1" type="pm:TIntegerFacetDescription"/> <xs:element name="MaxLength" minOccurs="0" maxOccurs="1" type="pm:TIntegerFacetDescription"/> <xs:element name="Unicode" minOccurs="0" maxOccurs="1" type="pm:TBooleanFacetDescription"/> <xs:element name="FixedLength" minOccurs="0" maxOccurs="1" type="pm:TBooleanFacetDescription"/> </xs:choice> </xs:complexType> <xs:complexType name="TType"> <xs:sequence> <xs:element name="FacetDescriptions" type="pm:TFacetDescriptions" minOccurs="0" maxOccurs="1"/> </xs:sequence> <xs:attribute name="Name" type="xs:string" use="required"/> <xs:attribute name="PrimitiveTypeKind" type="pm:TPrimitiveTypeKind" use="required" /> </xs:complexType> <xs:complexType name="TTypes"> <xs:sequence> <xs:element name="Type" type="pm:TType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:attributeGroup name="TFacetAttribute"> <xs:attribute name="Precision" type="xs:int" use="optional"/> <xs:attribute name="Scale" type="xs:int" use="optional"/> <xs:attribute name="MaxLength" type="xs:int" use="optional"/> <xs:attribute name="Unicode" type="xs:boolean" use="optional"/> <xs:attribute name="FixedLength" type="xs:boolean" use="optional"/> </xs:attributeGroup> <xs:complexType name="TFunctionParameter"> <xs:attribute name="Name" type="xs:string" use="required" /> <xs:attribute name="Type" type="xs:string" use="required" /> <xs:attributeGroup ref="pm:TFacetAttribute" /> <xs:attribute name="Mode" type="pm:TParameterDirection" use="required" /> </xs:complexType> <xs:complexType name="TReturnType"> <xs:attribute name="Type" type="xs:string" use="required" /> <xs:attributeGroup ref="pm:TFacetAttribute" /> </xs:complexType> <xs:complexType name="TFunction"> <xs:choice minOccurs="0" maxOccurs ="unbounded"> <xs:element name ="ReturnType" type="pm:TReturnType" minOccurs="0" maxOccurs="1" /> <xs:element name="Parameter" type="pm:TFunctionParameter" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> <xs:attribute name="Name" type="xs:string" use="required" /> <xs:attribute name="Aggregate" type="xs:boolean" use="optional" /> <xs:attribute name="BuiltIn" type="xs:boolean" use="optional" /> <xs:attribute name="StoreFunctionName" type="xs:string" use="optional" /> <xs:attribute name="NiladicFunction" type="xs:boolean" use="optional" /> <xs:attribute name="ParameterTypeSemantics" type="pm:TParameterTypeSemantics" use="optional" default="AllowImplicitConversion" /> </xs:complexType> <xs:complexType name="TFunctions"> <xs:sequence> <xs:element name="Function" type="pm:TFunction" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:simpleType name="TPrimitiveTypeKind"> <xs:restriction base="xs:string"> <xs:enumeration value="Binary"/> <xs:enumeration value="Boolean"/> <xs:enumeration value="Byte"/> <xs:enumeration value="Decimal"/> <xs:enumeration value="DateTime"/> <xs:enumeration value="Time"/> <xs:enumeration value="DateTimeOffset"/> <xs:enumeration value="Double"/> <xs:enumeration value="Guid"/> <xs:enumeration value="Single"/> <xs:enumeration value="SByte"/> <xs:enumeration value="Int16"/> <xs:enumeration value="Int32"/> <xs:enumeration value="Int64"/> <xs:enumeration value="String"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="TParameterDirection"> <xs:restriction base="xs:string"> <xs:enumeration value="In"/> <xs:enumeration value="Out"/> <xs:enumeration value="InOut"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="TParameterTypeSemantics"> <xs:restriction base="xs:string"> <xs:enumeration value="ExactMatchOnly" /> <xs:enumeration value="AllowImplicitPromotion" /> <xs:enumeration value="AllowImplicitConversion" /> </xs:restriction> </xs:simpleType> </xs:schema> Types NodeThe Types node in the provider manifest contains information about the Types that are supported natively by the data store or through the provider. Type NodeEach Type node defines a provider type in terms of EDM. The Type node describes the name of the provider type, and information related to the model type it maps to and facets to describe that type mapping. In order to express this type information in the provider manifest, each TypeInformation declaration must define several facet descriptions for each Type:
Function NodeEach Function defines a single function available through the provider.
Parameters Node Each function has a collection of one or more Parameter nodes.
Namespace AttributeEach data store provider must define a namespace or group of namespaces for information defined in the manifest. This namespace can be used in Entity SQL queries to resolve names of functions and types. For instance: SqlServer. That namespace must be different from the canonical namespace, EDM, defined by Entity Services for standard functions to be supported by Entity SQL queries. See alsoDevelopment and Deployment ConsiderationsTopics in this section address issues to consider when developing or deploying an application that is based on the ADO.NET Entity Framework. In This SectionSee alsoSecurity ConsiderationsThis topic describes security considerations that are specific to developing, deploying, and running Entity Framework applications. You should also follow recommendations for creating secure .NET Framework applications. For more information, see Security Overview. General Security ConsiderationsThe following security considerations apply to all applications that use the Entity Framework. Use only trusted data source providers.To communicate with the data source, a provider must do the following:
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. Encrypt your connection to protect sensitive data.The Entity Framework does not directly handle data encryption. If users access data over a public network, your application should establish an encrypted connection to the data source to increase security. For more information, see the security-related documentation for your data source. For a SQL Server data source, see Encrypting Connections to SQL Server. Secure the connection string.Protecting access to your data source is one of the most important goals when securing an application. A connection string presents a potential vulnerability if it is not secured or if it is improperly constructed. When you store connection information in plain text or persist it in memory, you risk compromising your entire system. The following are the recommended methods for securing connection strings:
For more information, see Protecting Connection Information. Do not expose an EntityConnection to untrusted users.An EntityConnection object exposes the connection string of the underlying connection. A user with access to an EntityConnection object can also change the ConnectionState of the underlying connection. The EntityConnection class is not thread safe. Do not pass connections outside the security context.After a connection has been established, you must not pass it outside the security context. For example, one thread with permission to open a connection should not store the connection in a global location. If the connection is available in a global location, then another malicious thread can use the open connection without having that permission explicitly granted to it. 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. Grant users only the necessary permissions in the data source.A data source administrator should grant only the necessary permissions to users. Even though Entity SQL does not support DML statements that modify data, such as INSERT, UPDATE, or DELETE, users can still access the connection to the data source. A malicious user could use this connection to execute DML statements in the native language of the data source. Run applications with the minimum permissions.When you allow a managed application to run with full-trust permission, the .NET Framework does not limit the application's access to your computer. This may enable a security vulnerability in your application to compromise the entire system. To use code access security and other security mechanisms in the .NET Framework, you should run applications by using partial-trust permissions and with the minimum set of permissions that are needed to enable the application to function. The following code access permissions are the minimum permissions your Entity Framework application needs:
For more information, see Code Access Security and ADO.NET. Do not install untrusted applications.The Entity Framework does not enforce any security permissions and will invoke any user-supplied data object code in process regardless of whether it is trusted or not. Ensure that authentication and authorization of the client is performed by the data store and by your application. Restrict access to all configuration files.An administrator must restrict write access to all files that specify configuration for an application, including to enterprisesec.config, security.config, machine.conf, and the application configuration file <application>.exe.config. 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. Restrict permissions to the model and mapping files.An administrator must restrict write access to the model and mapping files (.edmx, .csdl, .ssdl, and .msl) to only users who modify the model or mappings. The Entity Framework only requires read access to these files at run time. An administrator should also restrict access to object layer and pre-compiled view source code files that are generated by the Entity Data Model tools. Security Considerations for QueriesThe following security considerations apply when querying a conceptual model. These considerations apply to Entity SQL queries using EntityClient and to object queries using LINQ, Entity SQL, and query builder methods. Prevent SQL injection attacks.Applications frequently take external input (from a user or another external agent) and perform actions based on that input. Any input that is directly or indirectly derived from the user or an external agent might have content that uses the syntax of the target language in order to perform unauthorized actions. When the target language is a Structured Query Language (SQL), such as Transact-SQL, this manipulation is known as a SQL injection attack. A malicious user can inject commands directly into the query and drop a database table, cause a denial of service, or otherwise change the nature of the operation being performed.
Prevent very large result sets.A very large result set could cause the client system to shut down if the client is performing operations that consume resources proportional to the size of the result set. Unexpectedly large result sets can occur under the following 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. Avoid Returning IQueryable Results When Exposing Methods to Potentially Untrusted Callers.Avoid returning IQueryable<T> types from methods that are exposed to potentially untrusted callers for the following reasons:
Security Considerations for EntitiesThe following security considerations apply when generating and working with entity types. Do not share an ObjectContext across application domains.Sharing an ObjectContext with more than one application domain may expose information in the connection string. Instead, you should transfer serialized objects or object graphs to the other application domain and then attach those objects to an ObjectContext in that application domain. For more information, see Serializing Objects. Prevent type safety violations.If type safety is violated, the Entity Framework cannot guarantee the integrity of data in objects. Type safety violations could occur if you allow untrusted applications to run with full-trust code access security. Handle exceptions.Access methods and properties of an ObjectContext within a try-catch block. Catching exceptions prevents unhandled exceptions from exposing entries in the ObjectStateManager or model information (such as table names) to users of your application. Security Considerations for ASP.NET ApplicationsYou should consider the following 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. Do not make assumptions about resolved path names.Although the values to which the root operator (~) and the DataDirectory substitution string resolve should remain constant during the application's runtime, the Entity Framework does not restrict the host from modifying these values. Verify the path length before deployment.Before deploying an Entity Framework application, you should ensure that the values of the root operator (~) and DataDirectory substitution string do not exceed the limits of the path length in the operating system. ADO.NET data providers do not ensure that the path length is within valid limits. Security Considerations for ADO.NET MetadataThe following security considerations apply when generating and working with model and mapping files. Do not expose sensitive information through logging.ADO.NET metadata service components do not log any private information. If there are results that cannot be returned because of access restrictions, database management systems and file systems should return zero results instead of raising an exception that could contain sensitive information. Do not accept MetadataWorkspace objects from untrusted sources.Applications should not accept instances of the MetadataWorkspace class from untrusted sources. Instead, you should explicitly construct and populate a workspace from such a source. See alsoPerformance ConsiderationsThis topic describes performance characteristics of the ADO.NET Entity Framework and provides some considerations to help improve the performance of Entity Framework applications. Stages of Query ExecutionIn 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 a conceptual model and returns data as objects. The following table describes this series of operations.
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 ConsiderationsThe following are other considerations that may affect the performance of Entity Framework applications. Query ExecutionBecause queries can be resource intensive, consider at what point in your code and on what computer a query is executed. Deferred versus immediate executionWhen you create an ObjectQuery<T> or LINQ query, the query may not be executed immediately. Query execution is deferred until the results are needed, such as during a foreach (C#) or For Each (Visual Basic) enumeration or when it is assigned to fill a List<T> collection. Query execution begins immediately when you call the Execute method on an ObjectQuery<T> or when you call a LINQ method that returns a singleton query, such as First or Any. For more information, see Object Queries and Query Execution (LINQ to Entities). Client-side execution of LINQ queriesAlthough the execution of a LINQ query occurs on the computer that hosts the data source, some parts of a LINQ query may be evaluated on the client computer. For more information, see the Store Execution section of Query Execution (LINQ to Entities). Query and Mapping ComplexityThe complexity of individual queries and of the mapping in the entity model will have a significant effect on query performance. Mapping complexityModels 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 complexityQueries 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:
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. RelationshipsFor 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 PathsBy default, when you execute an ObjectQuery<T>, related objects are not returned (although objects that represent the relationships themselves are). You can load related objects in one of three ways:
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 Loading Related Objects. Using query pathsQuery 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<T>. For more information, see How to: View the Store Commands. 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. Explicitly loading related objectsYou can explicitly load related objects by calling the Load method on a navigation property that returns an EntityCollection<TEntity> or EntityReference<TEntity>. Explicitly loading objects requires a round-trip to the database every time Load is called. 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. You can also use the LoadProperty method when there is no EntityCollection<TEntity> or EntityReference<TEntity> properties on entities. This is useful when you are using POCO entities. 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 ChangesWhen 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 conceptual model. Distributed TransactionsOperations 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 is used when one or more operations are executed inside a System.Transactions transaction. For more information, see Managing Connections and Transactions. Strategies for Improving PerformanceYou can improve the overall performance of queries in the Entity Framework by using the following strategies. Pre-generate viewsGenerating 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. You could also use the Text Template Transformation Toolkit to generate pre-compiled views. 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. When working with very large models, the following consideration applies: The .NET metadata format limits the number of user string characters in a given binary to 16,777,215 (0xFFFFFF). If you are generating views for a very large model and the view file reaches this size limit, you will get the "No logical space left to create more user strings." compile error. This size limitation applies to all managed binaries. For more information see the blog that demonstrates how to avoid the error when working with large and complex models. Consider using the NoTracking merge option for queriesThere is a cost required to track returned objects in the object context. Detecting changes to objects and ensuring that multiple requests for the same logical entity return the same object instance requires that objects be attached to an ObjectContext instance. If you do not plan to make updates or deletes to objects and do not require identity management, consider using the NoTracking merge options when you execute queries. Return the correct amount of dataIn some scenarios, specifying a query path using the Include method is much faster because it requires fewer round trips to the database. However, in other scenarios, additional round trips to the database to load related objects may be faster because the simpler queries with fewer joins result in less redundancy of data. Because of this, we recommend that you test the performance of various ways to retrieve related objects. For more information, see Loading Related Objects. 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. Limit the scope of the ObjectContextIn most cases, you should create an ObjectContext instance within a using statement (Using…End Using in Visual Basic). This can increase performance by ensuring that the resources associated with the object context are disposed automatically when the code exits the statement block. However, when controls are bound to objects managed by the object context, the ObjectContext instance should be maintained as long as the binding is needed and disposed of manually. For more information, see Managing Connections and Transactions. Consider opening the database connection manuallyWhen your application executes a series of object queries or frequently calls SaveChanges to persist create, update, and delete operations to the data source, the Entity Framework must continuously open and close the connection to the data source. In these situations, consider manually opening the connection at the start of these operations and either closing or disposing of the connection when the operations are complete. For more information, see Managing Connections and Transactions. Performance DataSome performance data for the Entity Framework is published in the following posts on the ADO.NET team blog:
See alsoDeployment ConsiderationsThis topic provides information about deploying applications that use the ADO.NET Entity Framework for data access. For more information about the Entity Framework, see Getting Started. The Entity Framework provides a set of tools that integrate with and make it easier to develop in Visual Studio. For more information, see ADO.NET 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:
See alsoEntity Framework ResourcesThe following external resources provide information and support for creating Entity Framework applications. Data Developer Center ADO.NET Team Blog Entity Framework Design Blog Data Platform How Do I? Videos: Entity Framework Series Entity Framework FAQ See also
Entity Framework TerminologyThis topic defines terms frequently referenced in Entity Framework documentation. Links are provided to relevant topics where additional information is available.
See alsoGetting StartedThe ADO.NET Entity Framework supports data-centric applications and services, and provides a platform for programming against data that raises the level of abstraction from the logical relational level to the conceptual level. By enabling developers to work with data at a greater level of abstraction, the Entity Framework supports code that is independent of any particular data storage engine or relational schema. For more information, see Entity Framework Overview. To quickly start using the latest version of the Entity Framework, see Get Started See alsoGetting Started with the Entity Framework[This page is specific to the latest version of the Entity Framework. The latest version is available as the 'Entity Framework' NuGet package. For more information, see Entity Framework Releases and Versioning.] The msdn.com/data/ef site is now the main location for the Entity Framework content. The content for this topic is now available on the following page: Get Started. See AlsoConceptsOther ResourcesEntity Framework Resources Get started with Entity Framework 6This guide contains a collection of links to selected documentation articles, walkthroughs and videos that can help you get started quickly. Fundamentals
Code First resources
EF Designer resources
Other resources
Entity SQL Language ReferenceThis section provides detailed documentation LINQ to Entities, Entity SQL, and the modeling and mapping languages used by the Entity Framework. In This SectionCSDL, SSDL, and MSL Specifications Related SectionsADO.NET Entity Data Model Tools See alsoLINQ to EntitiesLINQ to Entities provides Language-Integrated Query (LINQ) support that enables developers to write queries against the Entity Framework conceptual model using Visual Basic or Visual C#. Queries against the Entity Framework are represented by command tree queries, which execute against the object context. LINQ to Entities converts Language-Integrated Queries (LINQ) queries to command tree queries, executes the queries against the Entity Framework, and returns objects that can be used by both the Entity Framework and LINQ. The following is the process for creating and executing a LINQ to Entities query:
Constructing an ObjectQuery InstanceThe ObjectQuery<T> generic class represents a query that returns a collection of zero or more typed entities. An object query is typically constructed from an existing object context, instead of being manually constructed, and always belongs to that object context. This context provides the connection and metadata information that is required to compose and execute the query. The ObjectQuery<T> generic class implements the IQueryable<T> generic interface, whose builder methods enable LINQ queries to be incrementally built. You can also let the compiler infer the type of entities by using the C# var keyword (Dim in Visual Basic, with local type inference enabled). Composing the QueriesInstances of the ObjectQuery<T> generic class, which implements the generic IQueryable<T> interface, serve as the data source for LINQ to Entities queries. In a query, you specify exactly the information that you want to retrieve from the data source. A query can also specify how that information should be sorted, grouped, and shaped before it is returned. In LINQ, a query is stored in a variable. This query variable takes no action and returns no data; it only stores the query information. After you create a query you must execute that query to retrieve any data. LINQ to Entities queries can be composed in two different syntaxes: query expression syntax and method-based query syntax. Query expression syntax and method-based query syntax are new in C# 3.0 and Visual Basic 9.0. For more information, see Queries in LINQ to Entities. Query ConversionTo execute a LINQ to Entities query against the Entity Framework, the LINQ query must be converted to a command tree representation that can be executed against the Entity Framework. LINQ to Entities queries are comprised of LINQ standard query operators (such as Select, Where, and GroupBy) and expressions (x > 10, Contact.LastName, and so on). LINQ operators are not defined by a class, but rather are methods on a class. In LINQ, expressions can contain anything allowed by types within the System.Linq.Expressions namespace and, by extension, anything that can be represented in a lambda function. This is a superset of the expressions that are allowed by the Entity Framework, which are by definition restricted to operations allowed on the database, and supported by ObjectQuery<T>. In the Entity Framework, both operators and expressions are represented by a single type hierarchy, which are then placed in a command tree. The command tree is used by the Entity Framework to execute the query. If the LINQ query cannot be expressed as a command tree, an exception will be thrown when the query is being converted. The conversion of LINQ to Entities queries involves two sub-conversions: the conversion of the standard query operators, and the conversion of the expressions. There are a number of LINQ standard query operators that do not have a valid translation in LINQ to Entities. Attempts to use these operators will result in an exception at query translation time. For a list of supported LINQ to Entities operators, see Supported and Unsupported LINQ Methods (LINQ to Entities). For more information about using the standard query operators in LINQ to Entities, see Standard Query Operators in LINQ to Entities Queries. In general, expressions in LINQ to Entities are evaluated on the server, so the behavior of the expression should not be expected to follow CLR semantics. For more information, see Expressions in LINQ to Entities Queries. For information about how CLR method calls are mapped to canonical functions in the data source, see CLR Method to Canonical Function Mapping. For information about how to call canonical, database, and custom functions from within LINQ to Entities queries, see Calling Functions in LINQ to Entities Queries. Query ExecutionAfter the LINQ query is created by the user, it is converted to a representation that is compatible with the Entity Framework (in the form of command trees), which is then executed against the data source. At query execution time, all query expressions (or components of the query) are evaluated on the client or on the server. This includes expressions that are used in result materialization or entity projections. For more information, see Query Execution. For information on how to improve performance by compiling a query once and then executing it several times with different parameters, see Compiled Queries (LINQ to Entities). MaterializationMaterialization is the process of returning query results back to the client as CLR types. In LINQ to Entities, query results data records are never returned; there is always a backing CLR type, defined by the user or by the Entity Framework, or generated by the compiler (anonymous types). All object materialization is performed by the Entity Framework. Any errors that result from an inability to map between the Entity Framework and the CLR will cause exceptions to be thrown during object materialization. Query results are usually returned as one of the following:
For more information, see Query Results. In This SectionExpressions in LINQ to Entities Queries Calling Functions in LINQ to Entities Queries Compiled Queries (LINQ to Entities) Standard Query Operators in LINQ to Entities Queries CLR Method to Canonical Function Mapping Supported and Unsupported LINQ Methods (LINQ to Entities) Known Issues and Considerations in LINQ to Entities See also
Queries in LINQ to EntitiesA query is an expression that retrieves data from a data source. Queries are usually expressed in a specialized query language, such as SQL for relational databases and XQuery for XML. Therefore, developers have had to learn a new query language for each type of data source or data format that they query. Language-Integrated Query (LINQ) offers a simpler, consistent model for working with data across various kinds of data sources and formats. In a LINQ query, you always work with programming objects. A LINQ query operation consists of three actions: obtain the data source or sources, create the query, and execute the query. Data sources that implement the IEnumerable<T> generic interface or the IQueryable<T> generic interface can be queried through LINQ. Instances of the generic ObjectQuery<T> class, which implements the generic IQueryable<T> interface, serve as the data source for LINQ to Entities queries. The ObjectQuery<T> generic class represents a query that returns a collection of zero or more typed objects. You can also let the compiler infer the type of an entity by using the C# keyword var (Dim in Visual Basic). In the query, you specify exactly the information that you want to retrieve from the data source. A query can also specify how that information should be sorted, grouped, and shaped before it is returned. In LINQ, a query is stored in a variable. If the query returns a sequence of values, the query variable itself must be a queryable type. This query variable takes no action and returns no data; it only stores the query information. After you create a query you must execute that query to retrieve any data. Query SyntaxLINQ to Entities queries can be composed in two different syntaxes: query expression syntax and method-based query syntax. Query expression syntax is new in C# 3.0 and Visual Basic 9.0, and it consists of a set of clauses written in a declarative syntax similar to Transact-SQL or XQuery. However, the .NET Framework common language runtime (CLR) cannot read the query expression syntax itself. Therefore, at compile time, query expressions are translated to something that the CLR does understand: method calls. These methods are known as the standard query operators. As a developer, you have the option of calling them directly by using method syntax, instead of using query syntax. For more information, see Query Syntax and Method Syntax in LINQ. Query Expression SyntaxQuery expressions are a declarative query syntax. This syntax enables a developer to write queries in a high-level language that is formatted similar to Transact-SQL. By using query expression syntax, you can perform even complex filtering, ordering, and grouping operations on data sources with minimal code. For more information, Basic Query Operations (Visual Basic). For examples that demonstrate how to use the query expression syntax, see the following topics: Method-Based Query SyntaxAnother way to compose LINQ to Entities queries is by using method-based queries. The method-based query syntax is a sequence of direct method calls to LINQ operator methods, passing lambda expressions as the parameters. For more information, see Lambda Expressions. For examples that demonstrate how to use method-based syntax, see the following topics: See also
Method-Based Query Syntax Examples: ProjectionThe examples in this topic demonstrate how to use the Select and SelectMany methods to query the AdventureWorks Sales Model using method-based query syntax. The AdventureWorks Sales Model used in these examples is built from the Contact, Address, Product, SalesOrderHeader, and SalesOrderDetail tables in the AdventureWorks sample database. The examples in this topic use the following using/Imports statements: using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Globalization; using System.Data.EntityClient; using System.Data.SqlClient; using System.Data.Common; SelectExampleThe following example uses the Select method to project the Product.Name and Product.ProductID properties into a sequence of anonymous types. using (AdventureWorksEntities context = new AdventureWorksEntities()) { var query = context.Products .Select(product => new { ProductId = product.ProductID, ProductName = product.Name }); Console.WriteLine("Product Info:"); foreach (var productInfo in query) { Console.WriteLine("Product Id: {0} Product name: {1} ", productInfo.ProductId, productInfo.ProductName); } } ExampleThe following example uses the Select method to return a sequence of only product names. using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<string> productNames = context.Products .Select(p => p.Name); Console.WriteLine("Product Names:"); foreach (String productName in productNames) { Console.WriteLine(productName); } } SelectManyExampleThe following example uses the SelectMany method to select all orders where TotalDue is less than 500.00. decimal totalDue = 500.00M; using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Contact> contacts = context.Contacts; ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = contacts.SelectMany( contact => orders.Where(order => (contact.ContactID == order.Contact.ContactID) && order.TotalDue < totalDue) .Select(order => new { ContactID = contact.ContactID, LastName = contact.LastName, FirstName = contact.FirstName, OrderID = order.SalesOrderID, Total = order.TotalDue })); foreach (var smallOrder in query) { Console.WriteLine("Contact ID: {0} Name: {1}, {2} Order ID: {3} Total Due: ${4} ", smallOrder.ContactID, smallOrder.LastName, smallOrder.FirstName, smallOrder.OrderID, smallOrder.Total); } } ExampleThe following example uses the SelectMany method to select all orders where the order was made on October 1, 2002 or later. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Contact> contacts = context.Contacts; ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = contacts.SelectMany( contact => orders.Where(order => (contact.ContactID == order.Contact.ContactID) && order.OrderDate >= new DateTime(2002, 10, 1)) .Select(order => new { ContactID = contact.ContactID, LastName = contact.LastName, FirstName = contact.FirstName, OrderID = order.SalesOrderID, OrderDate = order.OrderDate })); foreach (var order in query) { Console.WriteLine("Contact ID: {0} Name: {1}, {2} Order ID: {3} Order date: {4:d} ", order.ContactID, order.LastName, order.FirstName, order.OrderID, order.OrderDate); } } See alsoMethod-Based Query Syntax Examples: FilteringThe examples in this topic demonstrate how to use the Where and Where…Contains methods to query the AdventureWorks Sales Model using method-based query syntax. Note, Where…Contains cannot be used as a part of a compiled query. The AdventureWorks Sales model used in these examples is built from the Contact, Address, Product, SalesOrderHeader, and SalesOrderDetail tables in the AdventureWorks sample database. The examples in this topic use the following using/Imports statements: using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Globalization; using System.Data.EntityClient; using System.Data.SqlClient; using System.Data.Common; WhereExampleThe following example returns all online orders. using (AdventureWorksEntities context = new AdventureWorksEntities()) { var onlineOrders = context.SalesOrderHeaders .Where(order => order.OnlineOrderFlag == true) .Select(s => new { s.SalesOrderID, s.OrderDate, s.SalesOrderNumber }); foreach (var onlineOrder in onlineOrders) { Console.WriteLine("Order ID: {0} Order date: {1:d} Order number: {2}", onlineOrder.SalesOrderID, onlineOrder.OrderDate, onlineOrder.SalesOrderNumber); } } ExampleThe following example returns the orders where the order quantity is greater than 2 and less than 6. int orderQtyMin = 2; int orderQtyMax = 6; using (AdventureWorksEntities context = new AdventureWorksEntities()) { var query = context.SalesOrderDetails .Where(order => order.OrderQty > orderQtyMin && order.OrderQty < orderQtyMax) .Select(s => new { s.SalesOrderID, s.OrderQty }); foreach (var order in query) { Console.WriteLine("Order ID: {0} Order quantity: {1}", order.SalesOrderID, order.OrderQty); } } ExampleThe following example returns all red colored products. String color = "Red"; using (AdventureWorksEntities context = new AdventureWorksEntities()) { var query = context.Products .Where(product => product.Color == color) .Select(p => new { p.Name, p.ProductNumber, p.ListPrice }); foreach (var product in query) { Console.WriteLine("Name: {0}", product.Name); Console.WriteLine("Product number: {0}", product.ProductNumber); Console.WriteLine("List price: ${0}", product.ListPrice); Console.WriteLine(""); } } ExampleThe following example uses the Where method to find orders that were made after December 1, 2003 and then uses the order.SalesOrderDetail navigation property to get the details for each order. using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<SalesOrderHeader> query = context.SalesOrderHeaders .Where(order => order.OrderDate >= new DateTime(2003, 12, 1)); Console.WriteLine("Orders that were made after December 1, 2003:"); foreach (SalesOrderHeader order in query) { Console.WriteLine("OrderID {0} Order date: {1:d} ", order.SalesOrderID, order.OrderDate); foreach (SalesOrderDetail orderDetail in order.SalesOrderDetails) { Console.WriteLine(" Product ID: {0} Unit Price {1}", orderDetail.ProductID, orderDetail.UnitPrice); } } } Where…ContainsExampleThe following example uses an array as part of a Where…Contains clause to find all products that have a ProductModelID that matches a value in the array. using (AdventureWorksEntities AWEntities = new AdventureWorksEntities()) { int?[] productModelIds = { 19, 26, 118 }; var products = AWEntities.Products. Where(p => productModelIds.Contains(p.ProductModelID)); foreach (var product in products) { Console.WriteLine("{0}: {1}", product.ProductModelID, product.ProductID); } } Note As part of the predicate in a Where…Contains clause, you can use an Array, a List<T>, or a collection of any type that implements the IEnumerable<T> interface. You can also declare and initialize a collection within a LINQ to Entities query. See the next example for more information. ExampleThe following example declares and initializes arrays in a Where…Contains clause to find all products that have a ProductModelID or a Size that matches a value in the arrays. using (AdventureWorksEntities AWEntities = new AdventureWorksEntities()) { var products = AWEntities.Products. Where(p => (new int?[] { 19, 26, 18 }).Contains(p.ProductModelID) || (new string[] { "L", "XL" }).Contains(p.Size)); foreach (var product in products) { Console.WriteLine("{0}: {1}, {2}", product.ProductID, product.ProductModelID, product.Size); } } See alsoMethod-Based Query Syntax Examples: OrderingThe examples in this topic demonstrate how to use the ThenBy method to query the AdventureWorks Sales Model using method-based query syntax. The AdventureWorks Sales Model used in these examples is built from the Contact, Address, Product, SalesOrderHeader, and SalesOrderDetail tables in the AdventureWorks sample database. The examples in this topic use the following using/Imports statements: using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Globalization; using System.Data.EntityClient; using System.Data.SqlClient; using System.Data.Common; ThenByExampleThe following example in method-based query syntax uses OrderBy and ThenBy to return a list of contacts ordered by last name and then by first name. using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<Contact> sortedContacts = context.Contacts .OrderBy(c => c.LastName) .ThenBy(c => c.FirstName); Console.WriteLine("The list of contacts sorted by last name then by first name:"); foreach (Contact sortedContact in sortedContacts) { Console.WriteLine(sortedContact.LastName + ", " + sortedContact.FirstName); } } ThenByDescendingExampleThe following example uses the OrderBy and ThenByDescending methods to first sort by list price, and then perform a descending sort of the product names. using (AdventureWorksEntities context = new AdventureWorksEntities()) { IOrderedQueryable<Product> query = context.Products .OrderBy(product => product.ListPrice) .ThenByDescending(product => product.Name); foreach (Product product in query) { Console.WriteLine("Product ID: {0} Product Name: {1} List Price {2}", product.ProductID, product.Name, product.ListPrice); } } See alsoMethod-Based Query Syntax Examples: Aggregate OperatorsThe examples in this topic demonstrate how to use the Aggregate, Average, Count, LongCount, Max, Min, and Sum methods to query the AdventureWorks Sales Model using method-based query syntax. The AdventureWorks Sales Model used in these examples is built from the Contact, Address, Product, SalesOrderHeader, and SalesOrderDetail tables in the AdventureWorks sample database. The examples in this topic use the following using/Imports statements: using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Globalization; using System.Data.EntityClient; using System.Data.SqlClient; using System.Data.Common; AverageExampleThe following example uses the Average method to find the average list price of the products. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Product> products = context.Products; Decimal averageListPrice = products.Average(product => product.ListPrice); Console.WriteLine("The average list price of all the products is ${0}", averageListPrice); } ExampleThe following example uses the Average method to find the average list price of the products of each style. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Product> products = context.Products; var query = from product in products group product by product.Style into g select new { Style = g.Key, AverageListPrice = g.Average(product => product.ListPrice) }; foreach (var product in query) { Console.WriteLine("Product style: {0} Average list price: {1}", product.Style, product.AverageListPrice); } } ExampleThe following example uses the Average method to find the average total due. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; Decimal averageTotalDue = orders.Average(order => order.TotalDue); Console.WriteLine("The average TotalDue is {0}.", averageTotalDue); } ExampleThe following example uses the Average method to get the average total due for each contact ID. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = from order in orders group order by order.Contact.ContactID into g select new { Category = g.Key, averageTotalDue = g.Average(order => order.TotalDue) }; foreach (var order in query) { Console.WriteLine("ContactID = {0} \t Average TotalDue = {1}", order.Category, order.averageTotalDue); } } ExampleThe following example uses the Average method to get the orders with the average total due for each contact. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = from order in orders group order by order.Contact.ContactID into g let averageTotalDue = g.Average(order => order.TotalDue) select new { Category = g.Key, CheapestProducts = g.Where(order => order.TotalDue == averageTotalDue) }; foreach (var orderGroup in query) { Console.WriteLine("ContactID: {0}", orderGroup.Category); foreach (var order in orderGroup.CheapestProducts) { Console.WriteLine("Average total due for SalesOrderID {1} is: {0}", order.TotalDue, order.SalesOrderID); } Console.Write("\n"); } } CountExampleThe following example uses the Count method to return the number of products in the Product table. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Product> products = context.Products; int numProducts = products.Count(); Console.WriteLine("There are {0} products.", numProducts); } ExampleThe following example uses the Count method to return a list of contact IDs and how many orders each has. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Contact> contacts = context.Contacts; //Can't find field SalesOrderContact var query = from contact in contacts select new { CustomerID = contact.ContactID, OrderCount = contact.SalesOrderHeaders.Count() }; foreach (var contact in query) { Console.WriteLine("CustomerID = {0} \t OrderCount = {1}", contact.CustomerID, contact.OrderCount); } } ExampleThe following example groups products by color and uses the Count method to return the number of products in each color group. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Product> products = context.Products; var query = from product in products group product by product.Color into g select new { Color = g.Key, ProductCount = g.Count() }; foreach (var product in query) { Console.WriteLine("Color = {0} \t ProductCount = {1}", product.Color, product.ProductCount); } } LongCountExampleThe following example gets the contact count as a long integer. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Contact> contacts = context.Contacts; long numberOfContacts = contacts.LongCount(); Console.WriteLine("There are {0} Contacts", numberOfContacts); } MaxExampleThe following example uses the Max method to get the largest total due. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; Decimal maxTotalDue = orders.Max(w => w.TotalDue); Console.WriteLine("The maximum TotalDue is {0}.", maxTotalDue); } ExampleThe following example uses the Max method to get the largest total due for each contact ID. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = from order in orders group order by order.Contact.ContactID into g select new { Category = g.Key, maxTotalDue = g.Max(order => order.TotalDue) }; foreach (var order in query) { Console.WriteLine("ContactID = {0} \t Maximum TotalDue = {1}", order.Category, order.maxTotalDue); } } ExampleThe following example uses the Max method to get the orders with the largest total due for each contact ID. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = from order in orders group order by order.Contact.ContactID into g let maxTotalDue = g.Max(order => order.TotalDue) select new { Category = g.Key, CheapestProducts = g.Where(order => order.TotalDue == maxTotalDue) }; foreach (var orderGroup in query) { Console.WriteLine("ContactID: {0}", orderGroup.Category); foreach (var order in orderGroup.CheapestProducts) { Console.WriteLine("MaxTotalDue {0} for SalesOrderID {1}: ", order.TotalDue, order.SalesOrderID); } Console.Write("\n"); } } MinExampleThe following example uses the Min method to get the smallest total due. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; Decimal smallestTotalDue = orders.Min(totalDue => totalDue.TotalDue); Console.WriteLine("The smallest TotalDue is {0}.", smallestTotalDue); } ExampleThe following example uses the Min method to get the smallest total due for each contact ID. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = from order in orders group order by order.Contact.ContactID into g select new { Category = g.Key, smallestTotalDue = g.Min(order => order.TotalDue) }; foreach (var order in query) { Console.WriteLine("ContactID = {0} \t Minimum TotalDue = {1}", order.Category, order.smallestTotalDue); } } ExampleThe following example uses the Min method to get the orders with the smallest total due for each contact. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = from order in orders group order by order.Contact.ContactID into g let minTotalDue = g.Min(order => order.TotalDue) select new { Category = g.Key, smallestTotalDue = g.Where(order => order.TotalDue == minTotalDue) }; foreach (var orderGroup in query) { Console.WriteLine("ContactID: {0}", orderGroup.Category); foreach (var order in orderGroup.smallestTotalDue) { Console.WriteLine("Mininum TotalDue {0} for SalesOrderID {1}: ", order.TotalDue, order.SalesOrderID); } Console.Write("\n"); } } SumExampleThe following example uses the Sum method to get the total number of order quantities in the SalesOrderDetail table. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderDetail> orders = context.SalesOrderDetails; double totalOrderQty = orders.Sum(o => o.OrderQty); Console.WriteLine("There are a total of {0} OrderQty.", totalOrderQty); } ExampleThe following example uses the Sum method to get the total due for each contact ID. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = from order in orders group order by order.Contact.ContactID into g select new { Category = g.Key, TotalDue = g.Sum(order => order.TotalDue) }; foreach (var order in query) { Console.WriteLine("ContactID = {0} \t TotalDue sum = {1}", order.Category, order.TotalDue); } } See alsoMethod-Based Query Syntax Examples: PartitioningThe examples in this topic demonstrate how to use the Skip, and Take methods to query the AdventureWorks Sales Model using query expression syntax. The AdventureWorks Sales Model used in these examples is built from the Contact, Address, Product, SalesOrderHeader, and SalesOrderDetail tables in the AdventureWorks sample database. The examples in this topic use the following using/Imports statements: using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Globalization; using System.Data.EntityClient; using System.Data.SqlClient; using System.Data.Common; SkipExampleThe following example uses the Skip method to get all but the first five contacts of the Contact table. using (AdventureWorksEntities context = new AdventureWorksEntities()) { // LINQ to Entities only supports Skip on ordered collections. IOrderedQueryable<Product> products = context.Products .OrderBy(p => p.ListPrice); IQueryable<Product> allButFirst3Products = products.Skip(3); Console.WriteLine("All but first 3 products:"); foreach (Product product in allButFirst3Products) { Console.WriteLine("Name: {0} \t ID: {1}", product.Name, product.ProductID); } } ExampleThe following example uses the Skip method to get all but the first two addresses in Seattle. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Address> addresses = context.Addresses; ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; //LINQ to Entities only supports Skip on ordered collections. var query = ( from address in addresses from order in orders where address.AddressID == order.Address.AddressID && address.City == "Seattle" orderby order.SalesOrderID select new { City = address.City, OrderID = order.SalesOrderID, OrderDate = order.OrderDate }).Skip(2); Console.WriteLine("All but first 2 orders in Seattle:"); foreach (var order in query) { Console.WriteLine("City: {0} Order ID: {1} Total Due: {2:d}", order.City, order.OrderID, order.OrderDate); } TakeExampleThe following example uses the Take method to get only the first five contacts from the Contact table. using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<Contact> first5Contacts = context.Contacts.Take(5); Console.WriteLine("First 5 contacts:"); foreach (Contact contact in first5Contacts) { Console.WriteLine("Title = {0} \t FirstName = {1} \t Lastname = {2}", contact.Title, contact.FirstName, contact.LastName); } } ExampleThe following example uses the Take method to get the first three addresses in Seattle. String city = "Seattle"; using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Address> addresses = context.Addresses; ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = ( from address in addresses from order in orders where address.AddressID == order.Address.AddressID && address.City == city select new { City = address.City, OrderID = order.SalesOrderID, OrderDate = order.OrderDate }).Take(3); Console.WriteLine("First 3 orders in Seattle:"); foreach (var order in query) { Console.WriteLine("City: {0} Order ID: {1} Total Due: {2:d}", order.City, order.OrderID, order.OrderDate); } } See alsoMethod-Based Query Syntax Examples: ConversionThe examples in this topic demonstrate how to use the ToArray, ToDictionary and ToList methods to query the AdventureWorks Sales Model using method-based query syntax. The AdventureWorks Sales Model used in these examples is built from the Contact, Address, Product, SalesOrderHeader, and SalesOrderDetail tables in the AdventureWorks sample database. The examples in this topic use the following using/Imports statements: using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Globalization; using System.Data.EntityClient; using System.Data.SqlClient; using System.Data.Common; ToArrayExampleThe following example uses the ToArray method to immediately evaluate a sequence into an array. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Product> products = context.Products; Product[] prodArray = ( from product in products orderby product.ListPrice descending select product).ToArray(); Console.WriteLine("Every price from highest to lowest:"); foreach (Product product in prodArray) { Console.WriteLine(product.ListPrice); } } ToDictionaryExampleThe following example uses the ToDictionary method to immediately evaluate a sequence and a related key expression into a dictionary. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Product> products = context.Products; Dictionary<String, Product> scoreRecordsDict = products. ToDictionary(record => record.Name); Console.WriteLine("Top Tube's ProductID: {0}", scoreRecordsDict["Top Tube"].ProductID); } ToListExampleThe following example uses the ToList method to immediately evaluate a sequence into a List<T>, where T is of type DataRow. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Product> products = context.Products; List<Product> query = (from product in products orderby product.Name select product).ToList(); Console.WriteLine("The product list, ordered by product name:"); foreach (Product product in query) { Console.WriteLine(product.Name.ToLower(CultureInfo.InvariantCulture)); } } See alsoMethod-Based Query Syntax Examples: Join OperatorsThe examples in this topic demonstrate how to use the Join and GroupJoin methods to query the AdventureWorks Sales Model using method-based query syntax. The AdventureWorks Sales Model used in these examples is built from the Contact, Address, Product, SalesOrderHeader, and SalesOrderDetail tables in the AdventureWorks sample database. The examples in this topic use the following using/Imports statements: using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Globalization; using System.Data.EntityClient; using System.Data.SqlClient; using System.Data.Common; GroupJoinExampleThe following example performs a GroupJoin over the SalesOrderHeader and SalesOrderDetail tables to find the number of orders per customer. A group join is the equivalent of a left outer join, which returns each element of the first (left) data source, even if no correlated elements are in the other data source. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; ObjectSet<SalesOrderDetail> details = context.SalesOrderDetails; var query = orders.GroupJoin(details, order => order.SalesOrderID, detail => detail.SalesOrderID, (order, orderGroup) => new { CustomerID = order.SalesOrderID, OrderCount = orderGroup.Count() }); foreach (var order in query) { Console.WriteLine("CustomerID: {0} Orders Count: {1}", order.CustomerID, order.OrderCount); } } ExampleThe following example performs a GroupJoin over the Contact and SalesOrderHeader tables to find the number of orders per contact. The order count and IDs for each contact are displayed. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Contact> contacts = context.Contacts; ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = contacts.GroupJoin(orders, contact => contact.ContactID, order => order.Contact.ContactID, (contact, contactGroup) => new { ContactID = contact.ContactID, OrderCount = contactGroup.Count(), Orders = contactGroup }); foreach (var group in query) { Console.WriteLine("ContactID: {0}", group.ContactID); Console.WriteLine("Order count: {0}", group.OrderCount); foreach (var orderInfo in group.Orders) { Console.WriteLine(" Sale ID: {0}", orderInfo.SalesOrderID); } Console.WriteLine(""); } } JoinExampleThe following example performs a join over the Contact and SalesOrderHeader tables. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Contact> contacts = context.Contacts; ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = contacts.Join( orders, order => order.ContactID, contact => contact.Contact.ContactID, (contact, order) => new { ContactID = contact.ContactID, SalesOrderID = order.SalesOrderID, FirstName = contact.FirstName, Lastname = contact.LastName, TotalDue = order.TotalDue }); foreach (var contact_order in query) { Console.WriteLine("ContactID: {0} " + "SalesOrderID: {1} " + "FirstName: {2} " + "Lastname: {3} " + "TotalDue: {4}", contact_order.ContactID, contact_order.SalesOrderID, contact_order.FirstName, contact_order.Lastname, contact_order.TotalDue); } } ExampleThe following example performs a join over the Contact and SalesOrderHeader tables, grouping the results by contact ID. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Contact> contacts = context.Contacts; ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = contacts.Join( orders, order => order.ContactID, contact => contact.Contact.ContactID, (contact, order) => new { ContactID = contact.ContactID, SalesOrderID = order.SalesOrderID, FirstName = contact.FirstName, Lastname = contact.LastName, TotalDue = order.TotalDue }) .GroupBy(record => record.ContactID); foreach (var group in query) { foreach (var contact_order in group) { Console.WriteLine("ContactID: {0} " + "SalesOrderID: {1} " + "FirstName: {2} " + "Lastname: {3} " + "TotalDue: {4}", contact_order.ContactID, contact_order.SalesOrderID, contact_order.FirstName, contact_order.Lastname, contact_order.TotalDue); } } } See alsoMethod-Based Query Syntax Examples: Element OperatorsThe examples in this topic demonstrate how to use the First method to query the AdventureWorks Sales Model using method-based query syntax. The AdventureWorks Sales Model used in these examples is built from the Contact, Address, Product, SalesOrderHeader, and SalesOrderDetail tables in the AdventureWorks sample database. The example in this topic uses the following using/Imports statements: using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Globalization; using System.Data.EntityClient; using System.Data.SqlClient; using System.Data.Common; FirstExampleThe following example uses the First method to find the first email address that starts with 'caroline'. string name = "caroline"; using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Contact> contacts = context.Contacts; Contact query = contacts.First(contact => contact.EmailAddress.StartsWith(name)); Console.WriteLine("An email address starting with 'caroline': {0}", query.EmailAddress); } See alsoMethod-Based Query Syntax Examples: GroupingThe examples in this topic show you how to use the GroupBy method to query the AdventureWorks Sales Model using method-based query syntax. The AdventureWorks Sales Model that is used in these examples is built from the Contact, Address, Product, SalesOrderHeader, and SalesOrderDetail tables in the AdventureWorks sample database. The examples in this topic use the following using/Imports statements: using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Globalization; using System.Data.EntityClient; using System.Data.SqlClient; using System.Data.Common; ExampleThe following example uses the GroupBy method to return Address objects that are grouped by postal code. The results are projected into an anonymous type. using (AdventureWorksEntities context = new AdventureWorksEntities()) { var query = context.Addresses .GroupBy( address => address.PostalCode); foreach (IGrouping<string, Address> addressGroup in query) { Console.WriteLine("Postal Code: {0}", addressGroup.Key); foreach (Address address in addressGroup) { Console.WriteLine("\t" + address.AddressLine1 + address.AddressLine2); } } } ExampleThe following example uses the GroupBy method to return Contact objects that are grouped by the first letter of the contact's last name. The results are also sorted by the first letter of the last name and projected into an anonymous type. using (AdventureWorksEntities context = new AdventureWorksEntities()) { var query = context.Contacts .GroupBy(c => c.LastName.Substring(0,1)) .OrderBy(c => c.Key); foreach (IGrouping<string, Contact> group in query) { Console.WriteLine("Last names that start with the letter '{0}':", group.Key); foreach (Contact contact in group) { Console.WriteLine(contact.LastName); } } } ExampleThe following example uses the GroupBy method to return SalesOrderHeader objects that are grouped by customer ID. The number of sales for each customer is also returned. using (AdventureWorksEntities context = new AdventureWorksEntities()) { var query = context.SalesOrderHeaders .GroupBy(order => order.CustomerID); foreach (IGrouping<int, SalesOrderHeader> group in query) { Console.WriteLine("Customer ID: {0}", group.Key); Console.WriteLine("Order count: {0}", group.Count()); foreach (SalesOrderHeader sale in group) { Console.WriteLine(" Sale ID: {0}", sale.SalesOrderID); } Console.WriteLine(""); } } See alsoMethod-Based Query Syntax Examples: Navigating RelationshipsNavigation properties in the Entity Framework are shortcut properties used to locate the entities at the ends of an association. Navigation properties allow a user to navigate from one entity to another, or from one entity to related entities through an association set. This topic provides examples in method-based query syntax of how to navigate relationships through navigation properties in LINQ to Entities queries. The AdventureWorks Sales Model used in these examples is built from the Contact, Address, Product, SalesOrderHeader, and SalesOrderDetail tables in the AdventureWorks sample database. The examples in this topic use the following using/Imports statements: using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Globalization; using System.Data.EntityClient; using System.Data.SqlClient; using System.Data.Common; ExampleThe following example in method-based query syntax uses the SelectMany method to get all the orders of the contacts whose last name is "Zhou". The Contact.SalesOrderHeader navigation property is used to get the collection of SalesOrderHeader objects for each contact. string lastName = "Zhou"; using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<SalesOrderHeader> ordersQuery = context.Contacts .Where(c => c.LastName == lastName) .SelectMany(c => c.SalesOrderHeaders); foreach (var order in ordersQuery) { Console.WriteLine("Order ID: {0}, Order date: {1}, Total Due: {2}", order.SalesOrderID, order.OrderDate, order.TotalDue); } } ExampleThe following example in method-based query syntax uses the Select method to get all the contact IDs and the sum of the total due for each contact whose last name is "Zhou". The Contact.SalesOrderHeader navigation property is used to get the collection of SalesOrderHeader objects for each contact. The Sum method uses the Contact.SalesOrderHeader navigation property to sum the total due of all the orders for each contact. string lastName = "Zhou"; using (AdventureWorksEntities context = new AdventureWorksEntities()) { var ordersQuery = context.Contacts .Where(c => c.LastName == lastName) .Select(c => new { ContactID = c.ContactID, Total = c.SalesOrderHeaders.Sum(o => o.TotalDue) }); foreach (var contact in ordersQuery) { Console.WriteLine("Contact ID: {0} Orders total: {1}", contact.ContactID, contact.Total); } } ExampleThe following example in method-based query syntax gets all the orders of the contacts whose last name is "Zhou". The Contact.SalesOrderHeader navigation property is used to get the collection of SalesOrderHeader objects for each contact. The contact's name and orders are returned in an anonymous type. string lastName = "Zhou"; using (AdventureWorksEntities context = new AdventureWorksEntities()) { var ordersQuery = context.Contacts .Where(c => c.LastName == lastName) .Select(c => new { LastName = c.LastName, Orders = c.SalesOrderHeaders }); foreach (var order in ordersQuery) { Console.WriteLine("Name: {0}", order.LastName); foreach (SalesOrderHeader orderInfo in order.Orders) { Console.WriteLine("Order ID: {0}, Order date: {1}, Total Due: {2}", orderInfo.SalesOrderID, orderInfo.OrderDate, orderInfo.TotalDue); } Console.WriteLine(""); } } ExampleThe following example uses the SalesOrderHeader.Address and SalesOrderHeader.Contact navigation properties to get the collection of Address and Contact objects associated with each order. The last name of the contact, the street address, the sales order number, and the total due for each order to the city of Seattle are returned in an anonymous type. string city = "Seattle"; using (AdventureWorksEntities context = new AdventureWorksEntities()) { var ordersQuery = context.SalesOrderHeaders .Where(o => o.Address.City == city) .Select(o => new { ContactLastName = o.Contact.LastName, ContactFirstName = o.Contact.FirstName, StreetAddress = o.Address.AddressLine1, OrderNumber = o.SalesOrderNumber, TotalDue = o.TotalDue }); foreach (var orderInfo in ordersQuery) { Console.WriteLine("Name: {0}, {1}", orderInfo.ContactLastName, orderInfo.ContactFirstName); Console.WriteLine("Street address: {0}", orderInfo.StreetAddress); Console.WriteLine("Order number: {0}", orderInfo.OrderNumber); Console.WriteLine("Total Due: {0}", orderInfo.TotalDue); Console.WriteLine(""); } } ExampleThe following example uses the Where method to find orders that were made after December 1, 2003, and then uses the order.SalesOrderDetail navigation property to get the details for each order. using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<SalesOrderHeader> query = from order in context.SalesOrderHeaders where order.OrderDate >= new DateTime(2003, 12, 1) select order; Console.WriteLine("Orders that were made after December 1, 2003:"); foreach (SalesOrderHeader order in query) { Console.WriteLine("OrderID {0} Order date: {1:d} ", order.SalesOrderID, order.OrderDate); foreach (SalesOrderDetail orderDetail in order.SalesOrderDetails) { Console.WriteLine(" Product ID: {0} Unit Price {1}", orderDetail.ProductID, orderDetail.UnitPrice); } } } See alsoQuery Expression Syntax Examples: ProjectionThe examples in this topic demonstrate how to use the Select method and the From … From … keywords to query the AdventureWorks Sales Model using query expression syntax. From … From … is the query based equivalent of the SelectMany method. The AdventureWorks Sales model used in these examples is built from the Contact, Address, Product, SalesOrderHeader, and SalesOrderDetail tables in the AdventureWorks sample database. The examples in this topic use the following using/Imports statements: using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Globalization; using System.Data.EntityClient; using System.Data.SqlClient; using System.Data.Common; SelectExampleThe following example uses the Select method to return all the rows from the Product table and display the product names. using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<Product> productsQuery = from product in context.Products select product; Console.WriteLine("Product Names:"); foreach (var prod in productsQuery) { Console.WriteLine(prod.Name); } } ExampleThe following example uses Select to return a sequence of only product names. using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<string> productNames = from p in context.Products select p.Name; Console.WriteLine("Product Names:"); foreach (String productName in productNames) { Console.WriteLine(productName); } } ExampleThe following example uses the Select method to project the Product.Name and Product.ProductID properties into a sequence of anonymous types. using (AdventureWorksEntities context = new AdventureWorksEntities()) { var query = from product in context.Products select new { ProductId = product.ProductID, ProductName = product.Name }; Console.WriteLine("Product Info:"); foreach (var productInfo in query) { Console.WriteLine("Product Id: {0} Product name: {1} ", productInfo.ProductId, productInfo.ProductName); } } From … From … (SelectMany)ExampleThe following example uses From … From … (the equivalent of the SelectMany method) to select all orders where TotalDue is less than 500.00. decimal totalDue = 500.00M; using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Contact> contacts = context.Contacts; ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = from contact in contacts from order in orders where contact.ContactID == order.Contact.ContactID && order.TotalDue < totalDue select new { ContactID = contact.ContactID, LastName = contact.LastName, FirstName = contact.FirstName, OrderID = order.SalesOrderID, Total = order.TotalDue }; foreach (var smallOrder in query) { Console.WriteLine("Contact ID: {0} Name: {1}, {2} Order ID: {3} Total Due: ${4} ", smallOrder.ContactID, smallOrder.LastName, smallOrder.FirstName, smallOrder.OrderID, smallOrder.Total); } } ExampleThe following example uses From … From … (the equivalent of the SelectMany method) to select all orders where the order was made on October 1, 2002 or later. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Contact> contacts = context.Contacts; ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = from contact in contacts from order in orders where contact.ContactID == order.Contact.ContactID && order.OrderDate >= new DateTime(2002, 10, 1) select new { ContactID = contact.ContactID, LastName = contact.LastName, FirstName = contact.FirstName, OrderID = order.SalesOrderID, OrderDate = order.OrderDate }; foreach (var order in query) { Console.WriteLine("Contact ID: {0} Name: {1}, {2} Order ID: {3} Order date: {4:d} ", order.ContactID, order.LastName, order.FirstName, order.OrderID, order.OrderDate); } } ExampleThe following example uses a From … From … (the equivalent of the SelectMany method) to select all orders where the order total is greater than 10000.00 and uses From assignment to avoid requesting the total twice. decimal totalDue = 10000.0M; using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Contact> contacts = context.Contacts; ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = from contact in contacts from order in orders let total = order.TotalDue where contact.ContactID == order.Contact.ContactID && total >= totalDue select new { ContactID = contact.ContactID, LastName = contact.LastName, OrderID = order.SalesOrderID, total }; foreach (var order in query) { Console.WriteLine("Contact ID: {0} Last name: {1} Order ID: {2} Total: {3}", order.ContactID, order.LastName, order.OrderID, order.total); } } See alsoQuery Expression Syntax Examples: FilteringThe examples in this topic demonstrate how to use the Where and Where…Contains methods to query the AdventureWorks Sales Model using query expression syntax. Note, Where…Contains cannot be used as a part of a compiled query. The AdventureWorks Sales model used in these examples is built from the Contact, Address, Product, SalesOrderHeader, and SalesOrderDetail tables in the AdventureWorks sample database. The examples in this topic use the following using/Imports statements: using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Globalization; using System.Data.EntityClient; using System.Data.SqlClient; using System.Data.Common; WhereExampleThe following example returns all online orders. using (AdventureWorksEntities context = new AdventureWorksEntities()) { var onlineOrders = from order in context.SalesOrderHeaders where order.OnlineOrderFlag == true select new { SalesOrderID = order.SalesOrderID, OrderDate = order.OrderDate, SalesOrderNumber = order.SalesOrderNumber }; foreach (var onlineOrder in onlineOrders) { Console.WriteLine("Order ID: {0} Order date: {1:d} Order number: {2}", onlineOrder.SalesOrderID, onlineOrder.OrderDate, onlineOrder.SalesOrderNumber); } } ExampleThe following example returns the orders where the order quantity is greater than 2 and less than 6. int orderQtyMin = 2; int orderQtyMax = 6; using (AdventureWorksEntities context = new AdventureWorksEntities()) { var query = from order in context.SalesOrderDetails where order.OrderQty > orderQtyMin && order.OrderQty < orderQtyMax select new { SalesOrderID = order.SalesOrderID, OrderQty = order.OrderQty }; foreach (var order in query) { Console.WriteLine("Order ID: {0} Order quantity: {1}", order.SalesOrderID, order.OrderQty); } } ExampleThe following example returns all red colored products. String color = "Red"; using (AdventureWorksEntities context = new AdventureWorksEntities()) { var query = from product in context.Products where product.Color == color select new { Name = product.Name, ProductNumber = product.ProductNumber, ListPrice = product.ListPrice }; foreach (var product in query) { Console.WriteLine("Name: {0}", product.Name); Console.WriteLine("Product number: {0}", product.ProductNumber); Console.WriteLine("List price: ${0}", product.ListPrice); Console.WriteLine(""); } } ExampleThe following example uses the Where method to find orders that were made after December 1, 2003, and then uses the order.SalesOrderDetail navigation property to get the details for each order. using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<SalesOrderHeader> query = from order in context.SalesOrderHeaders where order.OrderDate >= new DateTime(2003, 12, 1) select order; Console.WriteLine("Orders that were made after December 1, 2003:"); foreach (SalesOrderHeader order in query) { Console.WriteLine("OrderID {0} Order date: {1:d} ", order.SalesOrderID, order.OrderDate); foreach (SalesOrderDetail orderDetail in order.SalesOrderDetails) { Console.WriteLine(" Product ID: {0} Unit Price {1}", orderDetail.ProductID, orderDetail.UnitPrice); } } } Where…ContainsExampleThe following example uses an array as part of a Where…Contains clause to find all products that have a ProductModelID that matches a value in the array. using (AdventureWorksEntities AWEntities = new AdventureWorksEntities()) { int?[] productModelIds = {19, 26, 118}; var products = from p in AWEntities.Products where productModelIds.Contains(p.ProductModelID) select p; foreach (var product in products) { Console.WriteLine("{0}: {1}", product.ProductModelID, product.ProductID); } } Note As part of the predicate in a Where…Contains clause, you can use an Array, a List<T>, or a collection of any type that implements the IEnumerable<T> interface. You can also declare and initialize a collection within a LINQ to Entities query. See the next example for more information. ExampleThe following example declares and initializes arrays in a Where…Contains clause to find all products that have a ProductModelID or Size that match values in the arrays. using (AdventureWorksEntities AWEntities = new AdventureWorksEntities()) { var products = from p in AWEntities.Products where (new int?[] { 19, 26, 18 }).Contains(p.ProductModelID) || (new string[] { "L", "XL" }).Contains(p.Size) select p; foreach (var product in products) { Console.WriteLine("{0}: {1}, {2}", product.ProductID, product.ProductModelID, product.Size); } } See alsoQuery Expression Syntax Examples: OrderingThe examples in this topic demonstrate how to use the OrderBy and OrderByDescending methods to query the AdventureWorks Sales Model using query expression syntax. The AdventureWorks Sales Model used in these examples is built from the Contact, Address, Product, SalesOrderHeader, and SalesOrderDetail tables in the AdventureWorks sample database. The examples in this topic use the following using/Imports statements: using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Globalization; using System.Data.EntityClient; using System.Data.SqlClient; using System.Data.Common; OrderByExampleThe following example uses OrderBy to return a list of contacts ordered by last name. using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<Contact> sortedNames = from n in context.Contacts orderby n.LastName select n; Console.WriteLine("The sorted list of last names:"); foreach (Contact n in sortedNames) { Console.WriteLine(n.LastName); } } ExampleThe following example uses OrderBy to sort a list of contacts by length of last name. using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<Contact> sortedNames = from n in context.Contacts orderby n.LastName.Length select n; Console.WriteLine("The sorted list of last names (by length):"); foreach (Contact n in sortedNames) { Console.WriteLine(n.LastName); } } OrderByDescendingExampleThe following example uses orderby… descending (Order By … Descending in Visual Basic), which is equivalent to the OrderByDescending method, to sort the price list from highest to lowest. using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<Decimal> sortedPrices = from p in context.Products orderby p.ListPrice descending select p.ListPrice; Console.WriteLine("The list price from highest to lowest:"); foreach (Decimal price in sortedPrices) { Console.WriteLine(price); } } ThenByExampleThe following example uses OrderBy and ThenBy to return a list of contacts ordered by last name and then by first name. using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<Contact> sortedContacts = from contact in context.Contacts orderby contact.LastName, contact.FirstName select contact; Console.WriteLine("The list of contacts sorted by last name then by first name:"); foreach (Contact sortedContact in sortedContacts) { Console.WriteLine(sortedContact.LastName + ", " + sortedContact.FirstName); } } ThenByDescendingExampleThe following example uses OrderBy… Descending, which is equivalent to the ThenByDescending method, to sort a list of products, first by name and then by list price from highest to lowest. using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<Product> query = from product in context.Products orderby product.Name, product.ListPrice descending select product; foreach (Product product in query) { Console.WriteLine("Product ID: {0} Product Name: {1} List Price {2}", product.ProductID, product.Name, product.ListPrice); } } See alsoQuery Expression Syntax Examples: Aggregate OperatorsThe examples in this topic demonstrate how to use the Average, Count, Max, Min, and Sum methods to query the AdventureWorks Sales Model using query expression syntax. The AdventureWorks Sales Model used in these examples is built from the Contact, Address, Product, SalesOrderHeader, and SalesOrderDetail tables in the AdventureWorks sample database. The examples in this topic use the following using/Imports statements: using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Globalization; using System.Data.EntityClient; using System.Data.SqlClient; using System.Data.Common; AverageExampleThe following example uses the Average method to find the average list price of the products of each style. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Product> products = context.Products; var query = from product in products group product by product.Style into g select new { Style = g.Key, AverageListPrice = g.Average(product => product.ListPrice) }; foreach (var product in query) { Console.WriteLine("Product style: {0} Average list price: {1}", product.Style, product.AverageListPrice); } } ExampleThe following example uses Average to get the average total due for each contact ID. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = from order in orders group order by order.Contact.ContactID into g select new { Category = g.Key, averageTotalDue = g.Average(order => order.TotalDue) }; foreach (var order in query) { Console.WriteLine("ContactID = {0} \t Average TotalDue = {1}", order.Category, order.averageTotalDue); } } ExampleThe following example uses Average to get the orders with the average total due for each contact. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = from order in orders group order by order.Contact.ContactID into g let averageTotalDue = g.Average(order => order.TotalDue) select new { Category = g.Key, CheapestProducts = g.Where(order => order.TotalDue == averageTotalDue) }; foreach (var orderGroup in query) { Console.WriteLine("ContactID: {0}", orderGroup.Category); foreach (var order in orderGroup.CheapestProducts) { Console.WriteLine("Average total due for SalesOrderID {1} is: {0}", order.TotalDue, order.SalesOrderID); } Console.Write("\n"); } } CountExampleThe following example uses Count to return a list of contact IDs and how many orders each has. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Contact> contacts = context.Contacts; //Can't find field SalesOrderContact var query = from contact in contacts select new { CustomerID = contact.ContactID, OrderCount = contact.SalesOrderHeaders.Count() }; foreach (var contact in query) { Console.WriteLine("CustomerID = {0} \t OrderCount = {1}", contact.CustomerID, contact.OrderCount); } } ExampleThe following example groups products by color and uses Count to return the number of products in each color group. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Product> products = context.Products; var query = from product in products group product by product.Color into g select new { Color = g.Key, ProductCount = g.Count() }; foreach (var product in query) { Console.WriteLine("Color = {0} \t ProductCount = {1}", product.Color, product.ProductCount); } } MaxExampleThe following example uses the Max method to get the largest total due for each contact ID. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = from order in orders group order by order.Contact.ContactID into g select new { Category = g.Key, maxTotalDue = g.Max(order => order.TotalDue) }; foreach (var order in query) { Console.WriteLine("ContactID = {0} \t Maximum TotalDue = {1}", order.Category, order.maxTotalDue); } } ExampleThe following example uses the Max method to get the orders with the largest total due for each contact ID. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = from order in orders group order by order.Contact.ContactID into g let maxTotalDue = g.Max(order => order.TotalDue) select new { Category = g.Key, CheapestProducts = g.Where(order => order.TotalDue == maxTotalDue) }; foreach (var orderGroup in query) { Console.WriteLine("ContactID: {0}", orderGroup.Category); foreach (var order in orderGroup.CheapestProducts) { Console.WriteLine("MaxTotalDue {0} for SalesOrderID {1}: ", order.TotalDue, order.SalesOrderID); } Console.Write("\n"); } } MinExampleThe following example uses the Min method to get the smallest total due for each contact ID. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = from order in orders group order by order.Contact.ContactID into g select new { Category = g.Key, smallestTotalDue = g.Min(order => order.TotalDue) }; foreach (var order in query) { Console.WriteLine("ContactID = {0} \t Minimum TotalDue = {1}", order.Category, order.smallestTotalDue); } } ExampleThe following example uses the Min method to get the orders with the smallest total due for each contact. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = from order in orders group order by order.Contact.ContactID into g let minTotalDue = g.Min(order => order.TotalDue) select new { Category = g.Key, smallestTotalDue = g.Where(order => order.TotalDue == minTotalDue) }; foreach (var orderGroup in query) { Console.WriteLine("ContactID: {0}", orderGroup.Category); foreach (var order in orderGroup.smallestTotalDue) { Console.WriteLine("Mininum TotalDue {0} for SalesOrderID {1}: ", order.TotalDue, order.SalesOrderID); } Console.Write("\n"); } } SumExampleThe following example uses the Sum method to get the total due for each contact ID. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = from order in orders group order by order.Contact.ContactID into g select new { Category = g.Key, TotalDue = g.Sum(order => order.TotalDue) }; foreach (var order in query) { Console.WriteLine("ContactID = {0} \t TotalDue sum = {1}", order.Category, order.TotalDue); } } See alsoQuery Expression Syntax Examples: PartitioningThe examples in this topic demonstrate how to use the Skip and Take methods to query the AdventureWorks Sales Model using query expression syntax. The AdventureWorks Sales Model used in these examples is built from the Contact, Address, Product, SalesOrderHeader, and SalesOrderDetail tables in the AdventureWorks sample database. The examples in this topic use the following using/Imports statements: using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Globalization; using System.Data.EntityClient; using System.Data.SqlClient; using System.Data.Common; SkipExampleThe following example uses the Skip method to get all but the first two addresses in Seattle. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Address> addresses = context.Addresses; ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; //LINQ to Entities only supports Skip on ordered collections. var query = ( from address in addresses from order in orders where address.AddressID == order.Address.AddressID && address.City == "Seattle" orderby order.SalesOrderID select new { City = address.City, OrderID = order.SalesOrderID, OrderDate = order.OrderDate }).Skip(2); Console.WriteLine("All but first 2 orders in Seattle:"); foreach (var order in query) { Console.WriteLine("City: {0} Order ID: {1} Total Due: {2:d}", order.City, order.OrderID, order.OrderDate); } TakeExampleThe following example uses the Take method to get the first three addresses in Seattle. String city = "Seattle"; using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Address> addresses = context.Addresses; ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = ( from address in addresses from order in orders where address.AddressID == order.Address.AddressID && address.City == city select new { City = address.City, OrderID = order.SalesOrderID, OrderDate = order.OrderDate }).Take(3); Console.WriteLine("First 3 orders in Seattle:"); foreach (var order in query) { Console.WriteLine("City: {0} Order ID: {1} Total Due: {2:d}", order.City, order.OrderID, order.OrderDate); } } See alsoQuery Expression Syntax Examples: Join OperatorsJoining is an important operation in queries that target data sources that have no navigable relationships to each other, such as relational database tables. A join of two data sources is the association of objects in one data source with objects that share a common attribute in the other data source. For more information, see Standard Query Operators Overview. The examples in this topic demonstrate how to use the GroupJoin and Join methods to query the AdventureWorks Sales Model using query expression syntax. The AdventureWorks Sales Model used in these examples is built from the Contact, Address, Product, SalesOrderHeader, and SalesOrderDetail tables in the AdventureWorks sample database. The examples in this topic use the following using/Imports statements: using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Globalization; using System.Data.EntityClient; using System.Data.SqlClient; using System.Data.Common; GroupJoinExampleThe following example performs a GroupJoin over the SalesOrderHeader and SalesOrderDetail tables to find the number of orders per customer. A group join is the equivalent of a left outer join, which returns each element of the first (left) data source, even if no correlated elements are in the other data source. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; ObjectSet<SalesOrderDetail> details = context.SalesOrderDetails; var query = from order in orders join detail in details on order.SalesOrderID equals detail.SalesOrderID into orderGroup select new { CustomerID = order.SalesOrderID, OrderCount = orderGroup.Count() }; foreach (var order in query) { Console.WriteLine("CustomerID: {0} Orders Count: {1}", order.CustomerID, order.OrderCount); } } ExampleThe following example performs a GroupJoin over the Contact and SalesOrderHeader tables to find the number of orders per contact. The order count and IDs for each contact are displayed. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Contact> contacts = context.Contacts; ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var query = from contact in contacts join order in orders on contact.ContactID equals order.Contact.ContactID into contactGroup select new { ContactID = contact.ContactID, OrderCount = contactGroup.Count(), Orders = contactGroup }; foreach (var group in query) { Console.WriteLine("ContactID: {0}", group.ContactID); Console.WriteLine("Order count: {0}", group.OrderCount); foreach (var orderInfo in group.Orders) { Console.WriteLine(" Sale ID: {0}", orderInfo.SalesOrderID); } Console.WriteLine(""); } } JoinExampleThe following example performs a join over the SalesOrderHeader and SalesOrderDetail tables to get online orders from the month of August. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; ObjectSet<SalesOrderDetail> details = context.SalesOrderDetails; var query = from order in orders join detail in details on order.SalesOrderID equals detail.SalesOrderID where order.OnlineOrderFlag == true && order.OrderDate.Month == 8 select new { SalesOrderID = order.SalesOrderID, SalesOrderDetailID = detail.SalesOrderDetailID, OrderDate = order.OrderDate, ProductID = detail.ProductID }; foreach (var order in query) { Console.WriteLine("{0}\t{1}\t{2:d}\t{3}", order.SalesOrderID, order.SalesOrderDetailID, order.OrderDate, order.ProductID); } } See alsoQuery Expression Syntax Examples: Element OperatorsThe examples in this topic demonstrate how to use the First method to query the AdventureWorks Sales Model using the query expression syntax. The AdventureWorks Sales Model used in these examples is built from the Contact, Address, Product, SalesOrderHeader, and SalesOrderDetail tables in the AdventureWorks sample database. The examples in this topic use the following using/Imports statements: using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Globalization; using System.Data.EntityClient; using System.Data.SqlClient; using System.Data.Common; FirstExampleThe following example uses the First method to return the first contact whose first name is "Brooke". string firstName = "Brooke"; using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Contact> contacts = context.Contacts; Contact query = ( from contact in contacts where contact.FirstName == firstName select contact) .First(); Console.WriteLine("ContactID: " + query.ContactID); Console.WriteLine("FirstName: " + query.FirstName); Console.WriteLine("LastName: " + query.LastName); } See alsoQuery Expression Syntax Examples: GroupingThe examples in this topic demonstrate how to use the GroupBy method to query the AdventureWorks Sales Model using query expression syntax. The AdventureWorks Sales model used in these examples is built from the Contact, Address, Product, SalesOrderHeader, and SalesOrderDetail tables in the AdventureWorks sample database. The examples in this topic use the following using/Imports statements: using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Globalization; using System.Data.EntityClient; using System.Data.SqlClient; using System.Data.Common; ExampleThe following example returns Address objects grouped by postal code. The results are projected into an anonymous type. using (AdventureWorksEntities context = new AdventureWorksEntities()) { var query = from address in context.Addresses group address by address.PostalCode into addressGroup select new { PostalCode = addressGroup.Key, AddressLine = addressGroup }; foreach (var addressGroup in query) { Console.WriteLine("Postal Code: {0}", addressGroup.PostalCode); foreach (var address in addressGroup.AddressLine) { Console.WriteLine("\t" + address.AddressLine1 + address.AddressLine2); } } } ExampleThe following example returns Contact objects grouped by the first letter of the contact's last name. The results are also sorted by the first letter of last name and projected into an anonymous type. using (AdventureWorksEntities context = new AdventureWorksEntities()) { var query = ( from contact in context.Contacts group contact by contact.LastName.Substring(0, 1) into contactGroup select new { FirstLetter = contactGroup.Key, Names = contactGroup }). OrderBy(letter => letter.FirstLetter); foreach (var contact in query) { Console.WriteLine("Last names that start with the letter '{0}':", contact.FirstLetter); foreach (var name in contact.Names) { Console.WriteLine(name.LastName); } } } ExampleThe following example returns SalesOrderHeader objects grouped by customer ID. The number of sales for each customer is also returned. using (AdventureWorksEntities context = new AdventureWorksEntities()) { var query = from order in context.SalesOrderHeaders group order by order.CustomerID into idGroup select new {CustomerID = idGroup.Key, OrderCount = idGroup.Count(), Sales = idGroup}; foreach (var orderGroup in query) { Console.WriteLine("Customer ID: {0}", orderGroup.CustomerID); Console.WriteLine("Order Count: {0}", orderGroup.OrderCount); foreach (SalesOrderHeader sale in orderGroup.Sales) { Console.WriteLine(" Sale ID: {0}", sale.SalesOrderID); } Console.WriteLine(""); } } See alsoQuery Expression Syntax Examples: Navigating RelationshipsNavigation properties in the Entity Framework are shortcut properties used to locate the entities at the ends of an association. Navigation properties allow a user to navigate from one entity to another, or from one entity to related entities through an association set. This topic provides examples in query expression syntax of how to navigate relationships through navigation properties in LINQ to Entities queries. The AdventureWorks Sales Model used in these examples is built from the Contact, Address, Product, SalesOrderHeader, and SalesOrderDetail tables in the AdventureWorks sample database. The examples in this topic use the following using/Imports statements: using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Globalization; using System.Data.EntityClient; using System.Data.SqlClient; using System.Data.Common; ExampleThe following example uses the Select method to get all the contact IDs and the sum of the total due for each contact whose last name is "Zhou". The Contact.SalesOrderHeader navigation property is used to get the collection of SalesOrderHeader objects for each contact. The Sum method uses the Contact.SalesOrderHeader navigation property to sum the total due of all the orders for each contact. string lastName = "Zhou"; using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Contact> contacts = context.Contacts; var ordersQuery = from contact in contacts where contact.LastName == lastName select new { ContactID = contact.ContactID, Total = contact.SalesOrderHeaders.Sum(o => o.TotalDue) }; foreach (var contact in ordersQuery) { Console.WriteLine("Contact ID: {0} Orders total: {1}", contact.ContactID, contact.Total); } } ExampleThe following example gets all the orders of the contacts whose last name is "Zhou". The Contact.SalesOrderHeader navigation property is used to get the collection of SalesOrderHeader objects for each contact. The contact's name and orders are returned in an anonymous type. string lastName = "Zhou"; using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Contact> contacts = context.Contacts; var ordersQuery = from contact in contacts where contact.LastName == lastName select new { LastName = contact.LastName, Orders = contact.SalesOrderHeaders }; foreach (var order in ordersQuery) { Console.WriteLine("Name: {0}", order.LastName); foreach (SalesOrderHeader orderInfo in order.Orders) { Console.WriteLine("Order ID: {0}, Order date: {1}, Total Due: {2}", orderInfo.SalesOrderID, orderInfo.OrderDate, orderInfo.TotalDue); } Console.WriteLine(""); } } ExampleThe following example uses the SalesOrderHeader.Address and SalesOrderHeader.Contact navigation properties get the collection of Address and Contact objects associated with each order. The last name of the contact, the street address, the sales order number, and the total due for each order to the city of Seattle are returned in an anonymous type. string city = "Seattle"; using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; var ordersQuery = from order in orders where order.Address.City == city select new { ContactLastName = order.Contact.LastName, ContactFirstName = order.Contact.FirstName, StreetAddress = order.Address.AddressLine1, OrderNumber = order.SalesOrderNumber, TotalDue = order.TotalDue }; foreach (var orderInfo in ordersQuery) { Console.WriteLine("Name: {0}, {1}", orderInfo.ContactLastName, orderInfo.ContactFirstName); Console.WriteLine("Street address: {0}", orderInfo.StreetAddress); Console.WriteLine("Order number: {0}", orderInfo.OrderNumber); Console.WriteLine("Total Due: {0}", orderInfo.TotalDue); Console.WriteLine(""); } } ExampleThe following example uses the Where method to find orders that were made after December 1, 2003, and then uses the order.SalesOrderDetail navigation property to get the details for each order. using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<SalesOrderHeader> query = from order in context.SalesOrderHeaders where order.OrderDate >= new DateTime(2003, 12, 1) select order; Console.WriteLine("Orders that were made after December 1, 2003:"); foreach (SalesOrderHeader order in query) { Console.WriteLine("OrderID {0} Order date: {1:d} ", order.SalesOrderID, order.OrderDate); foreach (SalesOrderDetail orderDetail in order.SalesOrderDetails) { Console.WriteLine(" Product ID: {0} Unit Price {1}", orderDetail.ProductID, orderDetail.UnitPrice); } } } See alsoExpressions in LINQ to Entities QueriesAn expression is a fragment of code that can be evaluated to a single value, object, method, or namespace. Expressions can contain a literal value, a method call, an operator and its operands, or a simple name. Simple names can be the name of a variable, type member, method parameter, namespace or type. Expressions can use operators that in turn use other expressions as parameters, or method calls whose parameters are in turn other method calls. Therefore, expressions can range from simple to very complex. In LINQ to Entities queries, expressions can contain anything allowed by the types within the System.Linq.Expressions namespace, including lambda expressions. The expressions that can be used in LINQ to Entities queries are a superset of the expressions that can be used to query the Entity Framework. Expressions that are part of queries against the Entity Framework are limited to operations supported by ObjectQuery<T> and the underlying data source. In the following example, the comparison in the Where clause is an expression: Decimal totalDue = 200; using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<int> salesInfo = from s in context.SalesOrderHeaders where s.TotalDue >= totalDue select s.SalesOrderID; Console.WriteLine("Sales order info:"); foreach (int orderNumber in salesInfo) { Console.WriteLine("Order number: " + orderNumber); } } Note Specific language constructs, such as C# unchecked, have no meaning in LINQ to Entities. In This SectionRelationships, navigation properties and foreign keys See alsoConstant ExpressionsA constant expression consists of a constant value. Constant values are directly converted to constant command tree expressions, without any translation on the client. This includes expressions that result in a constant value. Therefore, data source behavior should be expected for all expressions involving constants. This can result in behavior that differs from CLR behavior. The following example shows a constant expression that is evaluated on the server. Decimal totalDue = 200 + 3; using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<string> salesInfo = from s in context.SalesOrderHeaders where s.TotalDue >= totalDue select s.SalesOrderNumber; Console.WriteLine("Sales order numbers:"); foreach (string orderNum in salesInfo) { Console.WriteLine(orderNum); } } LINQ to Entities does not support using a user class as a constant. However, a property reference on a user class is considered a constant, and will be converted to a command tree constant expression and executed on the data source. See alsoComparison ExpressionsA comparison expression checks whether a constant value, property value, or method result is equal, not equal, greater than, or less than another value. If a particular comparison is not valid for LINQ to Entities, an exception will be thrown. All comparisons, both implicit and explicit, require that all components are comparable in the data source. Comparison expressions are frequently used in Where clauses for restricting the query results. The following example in query expression syntax shows a query that returns results where the sales order number is equal to "SO43663": string salesOrderNumber = "SO43663"; using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<SalesOrderHeader> salesInfo = from s in context.SalesOrderHeaders where s.SalesOrderNumber == salesOrderNumber select s; Console.WriteLine("Sales info-"); foreach (SalesOrderHeader sale in salesInfo) { Console.WriteLine("Sales ID: " + sale.SalesOrderID); Console.WriteLine("Ship date: " + sale.ShipDate); } } The following example in method-based query syntax shows a query that returns results where the sales order number is equal to "SO43663": string salesOrderNumber = "SO43663"; IQueryable<SalesOrderHeader> salesInfo = context.SalesOrderHeaders .Where(s => s.SalesOrderNumber == salesOrderNumber) .Select(s => s); Console.WriteLine("Sales info-"); foreach (SalesOrderHeader sale in salesInfo) { Console.WriteLine("Sales ID: " + sale.SalesOrderID); Console.WriteLine("Ship date: " + sale.ShipDate); } } The following example in query expression syntax shows a query that returns sales order information where the ship date is equal to July 8, 2001: using (AdventureWorksEntities context = new AdventureWorksEntities()) { DateTime dt = new DateTime(2001, 7, 8); IQueryable<SalesOrderHeader> salesInfo = from s in context.SalesOrderHeaders where s.ShipDate == dt select s; Console.WriteLine("Orders shipped on August 7, 2001:"); foreach (SalesOrderHeader sale in salesInfo) { Console.WriteLine("Sales ID: " + sale.SalesOrderID); Console.WriteLine("Total due: " + sale.TotalDue); Console.WriteLine(); } } The following example in method-based query syntax shows a query that returns sales order information where the ship date is equal to July 8, 2001: using (AdventureWorksEntities context = new AdventureWorksEntities()) { DateTime dt = new DateTime(2001, 7, 8); IQueryable<SalesOrderHeader> salesInfo = context.SalesOrderHeaders .Where(s => s.ShipDate == dt) .Select(s => s); Console.WriteLine("Orders shipped on August 7, 2001:"); foreach (SalesOrderHeader sale in salesInfo) { Console.WriteLine("Sales ID: " + sale.SalesOrderID); Console.WriteLine("Total due: " + sale.TotalDue); Console.WriteLine(); } } Expressions that yield a constant are converted at the server, and no attempt to do local evaluation is performed. The following example uses an expression in the Where clause that yields a constant. Decimal totalDue = 200 + 3; using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<string> salesInfo = from s in context.SalesOrderHeaders where s.TotalDue >= totalDue select s.SalesOrderNumber; Console.WriteLine("Sales order numbers:"); foreach (string orderNum in salesInfo) { Console.WriteLine(orderNum); } } LINQ to Entities does not support using a user class as a constant. However, a property reference on a user class is considered a constant, and will be converted to a command tree constant expression and executed on the data source. class AClass { public int ID;} using (AdventureWorksEntities context = new AdventureWorksEntities()) { AClass aClass = new AClass(); aClass.ID = 43663; IQueryable<SalesOrderHeader> salesInfo = from s in context.SalesOrderHeaders where s.SalesOrderID == aClass.ID select s; Console.WriteLine("Order info-"); foreach (SalesOrderHeader sale in salesInfo) { Console.WriteLine("Sales order number: " + sale.SalesOrderNumber); Console.WriteLine("Total due: " + sale.TotalDue); Console.WriteLine(); } } Methods that return a constant expression are not supported. The following example contains a method in the Where clause that returns a constant. This example will throw an exception at run time. using (AdventureWorksEntities context = new AdventureWorksEntities()) { MyClass2 myClass = new MyClass2(); //Throws a NotSupportedException IQueryable<SalesOrderHeader> salesInfo = from s in context.SalesOrderHeaders where s.SalesOrderID == myClass.returnInt() select s; Console.WriteLine("Order info-"); try { foreach (SalesOrderHeader sale in salesInfo) { Console.WriteLine("Sales order number: " + sale.SalesOrderNumber); Console.WriteLine("Total due: " + sale.TotalDue); Console.WriteLine(); } } catch (NotSupportedException ex) { Console.WriteLine("Exception: {0}", ex.Message); } } See alsoNull ComparisonsA null value in the data source indicates that the value is unknown. In LINQ to Entities queries, you can check for null values so that certain calculations or comparisons are only performed on rows that have valid, or non-null, data. CLR null semantics, however, may differ from the null semantics of the data source. Most databases use a version of three-valued logic to handle null comparisons. That is, a comparison against a null value does not evaluate to true or false, it evaluates to unknown. Often this is an implementation of ANSI nulls, but this is not always the case. By default in SQL Server, the null-equals-null comparison returns a null value. In the following example, the rows where ShipDate is null are excluded from the result set, and the Transact-SQL statement would return 0 rows. -- Find order details and orders with no ship date. SELECT h.SalesOrderID FROM Sales.SalesOrderHeader h JOIN Sales.SalesOrderDetail o ON o.SalesOrderID = h.SalesOrderID WHERE h.ShipDate IS Null This is very different from the CLR null semantics, where the null-equals-null comparison returns true. The following LINQ query is expressed in the CLR, but it is executed in the data source. Because there is no guarantee that CLR semantics will be honored at the data source, the expected behavior is indeterminate. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders; ObjectSet<SalesOrderDetail> details = context.SalesOrderDetails; var query = from order in orders join detail in details on order.SalesOrderID equals detail.SalesOrderID where order.ShipDate == null select order.SalesOrderID; foreach (var OrderID in query) { Console.WriteLine("OrderID : {0}", OrderID); } } Key SelectorsA key selector is a function used in the standard query operators to extract a key from an element. In the key selector function, an expression can be compared with a constant. CLR null semantics are exhibited if an expression is compared to a null constant or if two null constants are compared. Store null semantics are exhibited if two columns with null values in the data source are compared. Key selectors are found in many of the grouping and ordering standard query operators, such as GroupBy, and are used to select keys by which to order or group the query results. Null Property on a Null ObjectIn the Entity Framework, the properties of a null object are null. When you attempt to reference a property of a null object in the CLR, you will receive a NullReferenceException. When a LINQ query involves a property of a null object, this can result in inconsistent behavior. For example, in the following query, the cast to NewProduct is done in the command tree layer, which might result in the Introduced property being null. If the database defined null comparisons such that the DateTime comparison evaluates to true, the row will be included. using (AdventureWorksEntities context = new AdventureWorksEntities()) { DateTime dt = new DateTime(); var query = context.Products .Where(p => (p as NewProduct).Introduced > dt) .Select(x => x); } Passing Null Collections to Aggregate FunctionsIn LINQ to Entities, when you pass a collection that supports IQueryable to an aggregate function, aggregate operations are performed at the database. There might be differences in the results of a query that was performed in-memory and a query that was performed at the database. With an in-memory query, if there are no matches, the query returns zero. At the database, the same query returns null. If a null value is passed to a LINQ aggregate function, an exception will be thrown. To accept possible null values, cast the types and the properties of the types that receive query results to nullable types. See alsoInitialization ExpressionsAn initialization expression initializes a new object. Most initialization expressions are supported, including most new C# 3.0 and Visual Basic 9.0 initialization expressions. The following types can be initialized and returned by a LINQ to Entities query:
Anonymous type initialization is shown in the following example in query expression syntax: Decimal totalDue = 200; using (AdventureWorksEntities context = new AdventureWorksEntities()) { var salesInfo = from s in context.SalesOrderHeaders where s.TotalDue >= totalDue select new { s.SalesOrderNumber, s.TotalDue }; Console.WriteLine("Sales order numbers:"); foreach (var sale in salesInfo) { Console.WriteLine("Order number: " + sale.SalesOrderNumber); Console.WriteLine("Total due: " + sale.TotalDue); Console.WriteLine(""); } } The following example in method-based query syntax shows anonymous type initialization: Decimal totalDue = 200; using (AdventureWorksEntities context = new AdventureWorksEntities()) { var salesInfo = context.SalesOrderHeaders .Where(s => s.TotalDue >= totalDue) .Select(s => new { s.SalesOrderNumber, s.TotalDue }); Console.WriteLine("Sales order numbers:"); foreach (var sale in salesInfo) { Console.WriteLine("Order number: " + sale.SalesOrderNumber); Console.WriteLine("Total due: " + sale.TotalDue); Console.WriteLine(""); } } User-defined class initialization is also supported. The C# 3.0 and Visual Basic 9.0 initialization pattern is supported and assumes that the property getter and setter are symmetric. The following example in query expression syntax shows a custom class being initialized in the query: class MyOrder { public string SalesOrderNumber; public DateTime? ShipDate; } Decimal totalDue = 200; using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<MyOrder> salesInfo = from s in context.SalesOrderHeaders where s.TotalDue >= totalDue select new MyOrder { SalesOrderNumber = s.SalesOrderNumber, ShipDate = s.ShipDate }; Console.WriteLine("Sales order info:"); foreach (MyOrder order in salesInfo) { Console.WriteLine("Order number: " + order.SalesOrderNumber); Console.WriteLine("Ship date: " + order.ShipDate); Console.WriteLine(""); } } The following example in method-based query syntax shows a custom class being initialized in the query: Decimal totalDue = 200; using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<MyOrder> salesInfo = context.SalesOrderHeaders .Where(s => s.TotalDue >= totalDue) .Select(s => new MyOrder { SalesOrderNumber = s.SalesOrderNumber, ShipDate = s.ShipDate }); Console.WriteLine("Sales order info:"); foreach (MyOrder order in salesInfo) { Console.WriteLine("Order number: " + order.SalesOrderNumber); Console.WriteLine("Ship date: " + order.ShipDate); Console.WriteLine(""); } } See alsoCalling Functions in LINQ to Entities QueriesThe topics in this section describe how to call functions in LINQ to Entities queries. The EntityFunctions and SqlFunctions classes provide access to canonical and database functions as part of the Entity Framework. For more information, see How to: Call Canonical Functions and How to: Call Database Functions. The process for calling a custom function requires three basic steps:
For more information, see the topics in this section. In This SectionHow to: Call Canonical Functions How to: Call Database Functions How to: Call Custom Database Functions How to: Call Model-Defined Functions in Queries How to: Call Model-Defined Functions as Object Methods See also
How to: Call Canonical FunctionsThe EntityFunctions class contains methods that expose canonical functions to use in LINQ to Entities queries. For information about canonical functions, see Canonical Functions. Note The AsUnicode and AsNonUnicode methods in the EntityFunctions class do not have canonical function equivalents. Canonical functions that perform a calculation on a set of values and return a single value (also known as aggregate canonical functions) can be directly invoked. Other canonical functions can only be called as part of a LINQ to Entities query. To call an aggregate function directly, you must pass an ObjectQuery<T> to the function. For more information, see the second example below. You can call some canonical functions by using common language runtime (CLR) methods in LINQ to Entities queries. For a list of CLR methods that map to canonical functions, see CLR Method to Canonical Function Mapping. ExampleThe following example uses the AdventureWorks Sales Model. The example executes a LINQ to Entities query that uses the DiffDays method to return all products for which the difference between SellEndDate and SellStartDate is less than 365 days: using (AdventureWorksEntities AWEntities = new AdventureWorksEntities()) { var products = from p in AWEntities.Products where EntityFunctions.DiffDays(p.SellEndDate, p.SellStartDate) < 365 select p; foreach (var product in products) { Console.WriteLine(product.ProductID); } } ExampleThe following example uses the AdventureWorks Sales Model. The example calls the aggregate StandardDeviation method directly to return the standard deviation of SalesOrderHeader subtotals. Note that an ObjectQuery<T> is passed to the function, which allows it to be called without being part of a LINQ to Entities query. using (AdventureWorksEntities AWEntities = new AdventureWorksEntities()) { double? stdDev = EntityFunctions.StandardDeviation( from o in AWEntities.SalesOrderHeaders select o.SubTotal); Console.WriteLine(stdDev); } See alsoHow to: Call Database FunctionsThe SqlFunctions class contains methods that expose SQL Server functions to use in LINQ to Entities queries. When you use SqlFunctions methods in LINQ to Entities queries, the corresponding database functions are executed in the database. Note Database functions that perform a calculation on a set of values and return a single value (also known as aggregate database functions) can be directly invoked. Other canonical functions can only be called as part of a LINQ to Entities query. To call an aggregate function directly, you must pass an ObjectQuery<T> to the function. For more information, see the second example below. Note The methods in the SqlFunctions class are specific to SQL Server functions. Similar classes that expose database functions may be available through other providers. ExampleThe following example uses the AdventureWorks Sales Model. The example executes a LINQ to Entities query that uses the CharIndex method to return all contacts whose last name starts with "Si": using (AdventureWorksEntities AWEntities = new AdventureWorksEntities()) { // SqlFunctions.CharIndex is executed in the database. var contacts = from c in AWEntities.Contacts where SqlFunctions.CharIndex("Si", c.LastName) == 1 select c; foreach (var contact in contacts) { Console.WriteLine(contact.LastName); } } ExampleThe following example uses the AdventureWorks Sales Model. The example calls the aggregate ChecksumAggregate method directly. Note that an ObjectQuery<T> is passed to the function, which allows it to be called without being part of a LINQ to Entities query. using (AdventureWorksEntities AWEntities = new AdventureWorksEntities()) { // SqlFunctions.ChecksumAggregate is executed in the database. decimal? checkSum = SqlFunctions.ChecksumAggregate( from o in AWEntities.SalesOrderHeaders select o.SalesOrderID); Console.WriteLine(checkSum); } See alsoHow to: Call Custom Database FunctionsThis topic describes how to call custom functions that are defined in the database from within LINQ to Entities queries. Database functions that are called from LINQ to Entities queries are executed in the database. Executing functions in the database can improve application performance. The procedure below provides a high-level outline for calling a custom database function. The example that follows provides more detail about the steps in the procedure. To call custom functions that are defined in the database
ExampleThe following example demonstrates how to call a custom database function from within a LINQ to Entities query. The example uses the School model. For information about the School model, see Creating the School Sample Database and Generating the School .edmx File. The following code adds the AvgStudentGrade function to the School sample database. Note The steps for calling a custom database function are the same regardless of the database server. However, the code below is specific to creating a function in a SQL Server database. The code for creating a custom function in other database servers might differ. USE [School] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE FUNCTION [dbo].[AvgStudentGrade](@studentId INT) RETURNS DECIMAL(3,2) AS BEGIN DECLARE @avg DECIMAL(3,2); SELECT @avg = avg(Grade) FROM StudentGrade WHERE StudentID = @studentId; RETURN @avg; END ExampleNext, declare a function in the store schema definition language (SSDL) of your .edmx file. the following code declares the AvgStudentGrade function in SSDL: <Function Name="AvgStudentGrade" ReturnType="decimal" Schema="dbo" > <Parameter Name="studentId" Mode="In" Type="int" /> </Function> ExampleNow create a method and map it to the function declared in the SSDL. The method in the following class is mapped to the function defined in the SSDL (above) by using an EdmFunctionAttribute. When this method is called, the corresponding function in the database is executed. [EdmFunction("SchoolModel.Store", "AvgStudentGrade")] public static decimal? AvgStudentGrade(int studentId) { throw new NotSupportedException("Direct calls are not supported."); } ExampleFinally, call the method in a LINQ to Entities query. The following code displays students' last names and average grades to the console: using (SchoolEntities context = new SchoolEntities()) { var students = from s in context.People where s.EnrollmentDate != null select new { name = s.LastName, avgGrade = AvgStudentGrade(s.PersonID) }; foreach (var student in students) { Console.WriteLine("{0}: {1}", student.name, student.avgGrade); } } See alsoHow to: Call Model-Defined Functions in QueriesThis topic describes how to call functions that are defined in the conceptual model from within LINQ to Entities queries. The procedure below provides a high-level outline for calling a model-defined function from within a LINQ to Entities query. The example that follows provides more detail about the steps in the procedure. The procedure assumes that you have defined a function in the conceptual model. For more information, see How to: Define Custom Functions in the Conceptual Model. To call a function defined in the conceptual model
ExampleThe following example demonstrates how to call a function that is defined in the conceptual model from within a LINQ to Entities query. The example uses the School model. For information about the School model, see Creating the School Sample Database and Generating the School .edmx File. The following conceptual model function returns the number of years since an instructor was hired. For information about adding the function to a conceptual model, see How to: Define Custom Functions in the Conceptual Model.) <Function Name="YearsSince" ReturnType="Edm.Int32"> <Parameter Name="date" Type="Edm.DateTime" /> <DefiningExpression> Year(CurrentDateTime()) - Year(date) </DefiningExpression> </Function> ExampleNext, add the following method to your application and use an EdmFunctionAttribute to map it to the conceptual model function: [EdmFunction("SchoolModel", "YearsSince")] public static int YearsSince(DateTime date) { throw new NotSupportedException("Direct calls are not supported."); } ExampleNow you can call the conceptual model function from within a LINQ to Entities query. The following code calls the method to display all instructors that were hired more than ten years ago: using (SchoolEntities context = new SchoolEntities()) { // Retrieve instructors hired more than 10 years ago. var instructors = from p in context.People where YearsSince((DateTime)p.HireDate) > 10 select p; foreach (var instructor in instructors) { Console.WriteLine(instructor.LastName); } } See also
How to: Call Model-Defined Functions as Object MethodsThis topic describes how to call a model-defined function as a method on an ObjectContext object or as a static method on a custom class. A model-defined function is a function that is defined in the conceptual model. The procedures in the topic describe how to call these functions directly instead of calling them from LINQ to Entities queries. For information about calling model-defined functions in LINQ to Entities queries, see How to: Call Model-Defined Functions in Queries. Whether you call a model-defined function as an ObjectContext method or as a static method on a custom class, you must first map the method to the model-defined function with an EdmFunctionAttribute. However, when you define a method on the ObjectContext class, you must use the QueryProvider property to expose the LINQ provider, whereas when you define a static method on a custom class, you must use the Provider property to expose the LINQ provider. For more information, see the examples that follow the procedures below. The procedures below provide high-level outlines for calling a model-defined function as a method on an ObjectContext object and as a static method on a custom class. The examples that follow provide more detail about the steps in the procedures. The procedures assume that you have defined a function in the conceptual model. For more information, see How to: Define Custom Functions in the Conceptual Model. To call a model-defined function as a method on an ObjectContext object
To call a model-defined function as static method on a custom class
ExampleCalling a Model-Defined Function as a Method on an ObjectContext Object The following example demonstrates how to call a model-defined function as a method on an ObjectContext object. The example uses the AdventureWorks Sales Model. Consider the conceptual model function below that returns product revenue for a specified product. (For information about adding the function to your conceptual model, see How to: Define Custom Functions in the Conceptual Model.) <Function Name="GetProductRevenue" ReturnType="Edm.Decimal"> <Parameter Name="productID" Type="Edm.Int32" /> <DefiningExpression> SUM( SELECT VALUE((s.UnitPrice - s.UnitPriceDiscount) * s.OrderQty) FROM AdventureWorksEntities.SalesOrderDetails as s WHERE s.ProductID = productID) </DefiningExpression> </Function> ExampleThe following code adds a method to the AdventureWorksEntities class that maps to the conceptual model function above. public partial class AdventureWorksEntities : ObjectContext { [EdmFunction("AdventureWorksModel", "GetProductRevenue")] public decimal? GetProductRevenue(int productId) { return this.QueryProvider.Execute<decimal?>(Expression.Call( Expression.Constant(this), (MethodInfo)MethodInfo.GetCurrentMethod(), Expression.Constant(productId, typeof(int)))); } } ExampleThe following code calls the method above to display the product revenue for a specified product: using (AdventureWorksEntities AWEntities = new AdventureWorksEntities()) { int productId = 776; Console.WriteLine(AWEntities.GetProductRevenue(productId)); } ExampleThe following example demonstrates how to call a model-defined function that returns a collection (as an IQueryable<T> object). Consider the conceptual model function below that returns all the SalesOrderDetails for a given product ID. <Function Name="GetDetailsById" ReturnType="Collection(AdventureWorksModel.SalesOrderDetail)"> <Parameter Name="productID" Type="Edm.Int32" /> <DefiningExpression> SELECT VALUE s FROM AdventureWorksEntities.SalesOrderDetails AS s WHERE s.ProductID = productID </DefiningExpression> </Function> ExampleThe following code adds a method to the AdventureWorksEntities class that maps to the conceptual model function above. public partial class AdventureWorksEntities : ObjectContext { [EdmFunction("AdventureWorksModel", "GetDetailsById")] public IQueryable<SalesOrderDetail> GetDetailsById(int productId) { return this.QueryProvider.CreateQuery<SalesOrderDetail>(Expression.Call( Expression.Constant(this), (MethodInfo)MethodInfo.GetCurrentMethod(), Expression.Constant(productId, typeof(int)))); } } ExampleThe following code calls the method. Note that the returned IQueryable<T> query is further refined to return line totals for each SalesOrderDetail. using (AdventureWorksEntities AWEntities = new AdventureWorksEntities()) { int productId = 776; var lineTotals = AWEntities.GetDetailsById(productId).Select(d =>d.LineTotal); foreach(var lineTotal in lineTotals) { Console.WriteLine(lineTotal); } } ExampleCalling a Model-Defined Function as a Static Method on a Custom Class The next example demonstrates how to call a model-defined function as a static method on a custom class. The example uses the AdventureWorks Sales Model. Note When you call a model-defined function as a static method on a custom class, the model-defined function must accept a collection and return an aggregation of values in the collection. Consider the conceptual model function below that returns product revenue for a SalesOrderDetail collection. (For information about adding the function to your conceptual model, see How to: Define Custom Functions in the Conceptual Model.). <Function Name="GetProductRevenue" ReturnType="Edm.Decimal"> <Parameter Name="details" Type="Collection(AdventureWorksModel.SalesOrderDetail)" /> <DefiningExpression> SUM( SELECT VALUE((s.UnitPrice - s.UnitPriceDiscount) * s.OrderQty) FROM details as s) </DefiningExpression> </Function> ExampleThe following code adds a class to your application that contains a static method that maps to the conceptual model function above. public class MyClass { [EdmFunction("AdventureWorksModel", "GetProductRevenue")] public static decimal? GetProductRevenue(IQueryable<SalesOrderDetail> details) { return details.Provider.Execute<decimal?>(Expression.Call( (MethodInfo)MethodInfo.GetCurrentMethod(), Expression.Constant(details, typeof(IQueryable<SalesOrderDetail>)))); } } ExampleThe following code calls the method above to display the product revenue for a SalesOrderDetail collection: using (AdventureWorksEntities AWEntities = new AdventureWorksEntities()) { int productId = 776; var details = from s in AWEntities.SalesOrderDetails where s.ProductID == productId select s; Console.WriteLine(MyClass.GetProductRevenue(details)); } See alsoCompiled Queries (LINQ to Entities)When you have an application that executes structurally similar queries many times in the Entity Framework, you can frequently increase performance by compiling the query one time and executing it several times with different parameters. For example, an application might have to retrieve all the customers in a particular city; the city is specified at runtime by the user in a form. LINQ to Entities supports using compiled queries for this purpose. Starting with the .NET Framework 4.5, LINQ queries are cached automatically. However, you can still use compiled LINQ queries to reduce this cost in later executions and compiled queries can be more efficient than LINQ queries that are automatically cached. Note that LINQ to Entities queries that apply the Enumerable.Contains operator to in-memory collections are not automatically cached. Also parameterizing in-memory collections in compiled LINQ queries is not allowed. The CompiledQuery class provides compilation and caching of queries for reuse. Conceptually, this class contains a CompiledQuery's Compile method with several overloads. Call the Compile method to create a new delegate to represent the compiled query. The Compile methods, provided with a ObjectContext and parameter values, return a delegate that produces some result (such as an IQueryable<T> instance). The query compiles once during only the first execution. The merge options set for the query at the time of the compilation cannot be changed later. Once the query is compiled you can only supply parameters of primitive type but you cannot replace parts of the query that would change the generated SQL. For more information, see Entity Framework Merge Options and Compiled Queries The LINQ to Entities query expression that the CompiledQuery's Compile method compiles is represented by one of the generic Func delegates, such as Func<T1,T2,T3,T4,TResult>. At most, the query expression can encapsulate an ObjectContext parameter, a return parameter, and 16 query parameters. If more than 16 query parameters are required, you can create a structure whose properties represent query parameters. You can then use the properties on the structure in the query expression after you set the properties. ExampleThe following example compiles and then invokes a query that accepts a Decimal input parameter and returns a sequence of orders where the total due is greater than or equal to $200.00: static readonly Func<AdventureWorksEntities, Decimal, IQueryable<SalesOrderHeader>> s_compiledQuery2 = CompiledQuery.Compile<AdventureWorksEntities, Decimal, IQueryable<SalesOrderHeader>>( (ctx, total) => from order in ctx.SalesOrderHeaders where order.TotalDue >= total select order); static void CompiledQuery2() { using (AdventureWorksEntities context = new AdventureWorksEntities()) { Decimal totalDue = 200.00M; IQueryable<SalesOrderHeader> orders = s_compiledQuery2.Invoke(context, totalDue); foreach (SalesOrderHeader order in orders) { Console.WriteLine("ID: {0} Order date: {1} Total due: {2}", order.SalesOrderID, order.OrderDate, order.TotalDue); } } } ExampleThe following example compiles and then invokes a query that returns an ObjectQuery<T> instance: static readonly Func<AdventureWorksEntities, ObjectQuery<SalesOrderHeader>> s_compiledQuery1 = CompiledQuery.Compile<AdventureWorksEntities, ObjectQuery<SalesOrderHeader>>( ctx => ctx.SalesOrderHeaders); static void CompiledQuery1_MQ() { using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<SalesOrderHeader> orders = s_compiledQuery1.Invoke(context); foreach (SalesOrderHeader order in orders) Console.WriteLine(order.SalesOrderID); } } ExampleThe following example compiles and then invokes a query that returns the average of the product list prices as a Decimal value: static readonly Func<AdventureWorksEntities, Decimal> s_compiledQuery3MQ = CompiledQuery.Compile<AdventureWorksEntities, Decimal>( ctx => ctx.Products.Average(product => product.ListPrice)); static void CompiledQuery3_MQ() { using (AdventureWorksEntities context = new AdventureWorksEntities()) { Decimal averageProductPrice = s_compiledQuery3MQ.Invoke(context); Console.WriteLine("The average of the product list prices is $: {0}", averageProductPrice); } } ExampleThe following example compiles and then invokes a query that accepts a String input parameter and then returns a Contact whose email address starts with the specified string: static readonly Func<AdventureWorksEntities, string, Contact> s_compiledQuery4MQ = CompiledQuery.Compile<AdventureWorksEntities, string, Contact>( (ctx, name) => ctx.Contacts.First(contact => contact.EmailAddress.StartsWith(name))); static void CompiledQuery4_MQ() { using (AdventureWorksEntities context = new AdventureWorksEntities()) { string contactName = "caroline"; Contact foundContact = s_compiledQuery4MQ.Invoke(context, contactName); Console.WriteLine("An email address starting with 'caroline': {0}", foundContact.EmailAddress); } } ExampleThe following example compiles and then invokes a query that accepts DateTime and Decimal input parameters and returns a sequence of orders where the order date is later than March 8, 2003, and the total due is less than $300.00: static readonly Func<AdventureWorksEntities, DateTime, Decimal, IQueryable<SalesOrderHeader>> s_compiledQuery5 = CompiledQuery.Compile<AdventureWorksEntities, DateTime, Decimal, IQueryable<SalesOrderHeader>>( (ctx, orderDate, totalDue) => from product in ctx.SalesOrderHeaders where product.OrderDate > orderDate && product.TotalDue < totalDue orderby product.OrderDate select product); static void CompiledQuery5() { using (AdventureWorksEntities context = new AdventureWorksEntities()) { DateTime date = new DateTime(2003, 3, 8); Decimal amountDue = 300.00M; IQueryable<SalesOrderHeader> orders = s_compiledQuery5.Invoke(context, date, amountDue); foreach (SalesOrderHeader order in orders) { Console.WriteLine("ID: {0} Order date: {1} Total due: {2}", order.SalesOrderID, order.OrderDate, order.TotalDue); } } } ExampleThe following example compiles and then invokes a query that accepts a DateTime input parameter and returns a sequence of orders where the order date is later than March 8, 2004. This query returns the order information as a sequence of anonymous types. Anonymous types are inferred by the compiler, so you cannot specify type parameters in the CompiledQuery's Compile method and the type is defined in the query itself. using (AdventureWorksEntities context = new AdventureWorksEntities()) { var compiledQuery = CompiledQuery.Compile((AdventureWorksEntities ctx, DateTime orderDate) => from order in ctx.SalesOrderHeaders where order.OrderDate > orderDate select new {order.OrderDate, order.SalesOrderID, order.TotalDue}); DateTime date = new DateTime(2004, 3, 8); var results = compiledQuery.Invoke(context, date); foreach (var order in results) { Console.WriteLine("ID: {0} Order date: {1} Total due: {2}", order.SalesOrderID, order.OrderDate, order.TotalDue); } } ExampleThe following example compiles and then invokes a query that accepts a user-defined structure input parameter and returns a sequence of orders. The structure defines start date, end date, and total due query parameters, and the query returns orders shipped between March 3 and March 8, 2003 with a total due greater than $700.00. static Func<AdventureWorksEntities, MyParams, IQueryable<SalesOrderHeader>> s_compiledQuery = CompiledQuery.Compile<AdventureWorksEntities, MyParams, IQueryable<SalesOrderHeader>>( (ctx, myparams) => from sale in ctx.SalesOrderHeaders where sale.ShipDate > myparams.startDate && sale.ShipDate < myparams.endDate && sale.TotalDue > myparams.totalDue select sale); static void CompiledQuery7() { using (AdventureWorksEntities context = new AdventureWorksEntities()) { MyParams myParams = new MyParams(); myParams.startDate = new DateTime(2003, 3, 3); myParams.endDate = new DateTime(2003, 3, 8); myParams.totalDue = 700.00M; IQueryable<SalesOrderHeader> sales = s_compiledQuery.Invoke(context, myParams); foreach (SalesOrderHeader sale in sales) { Console.WriteLine("ID: {0}", sale.SalesOrderID); Console.WriteLine("Ship date: {0}", sale.ShipDate); Console.WriteLine("Total due: {0}", sale.TotalDue); } } } The structure that defines the query parameters: struct MyParams { public DateTime startDate; public DateTime endDate; public decimal totalDue; } See alsoQuery ExecutionAfter a LINQ query is created by a user, it is converted to a command tree. A command tree is a representation of a query that is compatible with the Entity Framework. The command tree is then executed against the data source. At query execution time, all query expressions (that is, all components of the query) are evaluated, including those expressions that are used in result materialization. At what point query expressions are executed can vary. LINQ queries are always executed when the query variable is iterated over, not when the query variable is created. This is called deferred execution. You can also force a query to execute immediately, which is useful for caching query results. This is described later in this topic. When a LINQ to Entities query is executed, some expressions in the query might be executed on the server and some parts might be executed locally on the client. Client-side evaluation of an expression takes place before the query is executed on the server. If an expression is evaluated on the client, the result of that evaluation is substituted for the expression in the query, and the query is then executed on the server. Because queries are executed on the data source, the data source configuration overrides the behavior specified in the client. For example, null value handling and numerical precision depend on the server settings. Any exceptions thrown during query execution on the server are passed directly up to the client. Tip For a convenient summary of query operators in table format, which lets you quickly identify an operator's execution behavior, see Classification of Standard Query Operators by Manner of Execution (C#). Deferred query executionIn a query that returns a sequence of values, the query variable itself never holds the query results and only stores the query commands. Execution of the query is deferred until the query variable is iterated over in a foreach or For Each loop. This is known as deferred execution; that is, query execution occurs some time after the query is constructed. This means that you can execute a query as frequently as you want to. This is useful when, for example, you have a database that is being updated by other applications. In your application, you can create a query to retrieve the latest information and repeatedly execute the query, returning the updated information every time. Deferred execution enables multiple queries to be combined or a query to be extended. When a query is extended, it is modified to include the new operations, and the eventual execution will reflect the changes. In the following example, the first query returns all the products. The second query extends the first by using Where to return all the products of size "L": using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<Product> productsQuery = from p in context.Products select p; IQueryable<Product> largeProducts = productsQuery.Where(p => p.Size == "L"); Console.WriteLine("Products of size 'L':"); foreach (var product in largeProducts) { Console.WriteLine(product.Name); } } After a query has been executed all successive queries will use the in-memory LINQ operators. Iterating over the query variable by using a foreach or For Each statement or by calling one of the LINQ conversion operators will cause immediate execution. These conversion operators include the following: ToList, ToArray, ToLookup, and ToDictionary. Immediate Query ExecutionIn contrast to the deferred execution of queries that produce a sequence of values, queries that return a singleton value are executed immediately. Some examples of singleton queries are Average, Count, First, and Max. These execute immediately because the query must produce a sequence to calculate the singleton result. You can also force immediate execution. This is useful when you want to cache the results of a query. To force immediate execution of a query that does not produce a singleton value, you can call the ToList method, the ToDictionary method, or the ToArray method on a query or query variable. The following example uses the ToArray method to immediately evaluate a sequence into an array. using (AdventureWorksEntities context = new AdventureWorksEntities()) { ObjectSet<Product> products = context.Products; Product[] prodArray = ( from product in products orderby product.ListPrice descending select product).ToArray(); Console.WriteLine("Every price from highest to lowest:"); foreach (Product product in prodArray) { Console.WriteLine(product.ListPrice); } } You could also force execution by putting the foreach or For Each loop immediately after the query expression, but by calling ToList or ToArray you cache all the data in a single collection object. Store ExecutionIn general, expressions in LINQ to Entities are evaluated on the server, and the behavior of the expression should not be expected to follow common language runtime (CLR) semantics, but those of the data source. There are exceptions to this, however, such as when the expression is executed on the client. This could cause unexpected results, for example when the server and client are in different time zones. Some expressions in the query might be executed on the client. In general, most query execution is expected to occur on the server. Aside from methods executed against query elements mapped to the data source, there are often expressions in the query that can be executed locally. Local execution of a query expression yields a value that can be used in the query execution or result construction. Certain operations are always executed on the client, such as binding of values, sub expressions, sub queries from closures, and materialization of objects into query results. The net effect of this is that these elements (for example, parameter values) cannot be updated during the execution. Anonymous types can be constructed inline on the data source, but should not be assumed to do so. Inline groupings can be constructed in the data source, as well, but this should not be assumed in every instance. In general, it is best not to make any assumptions about what is constructed on the server. This section describes the scenarios in which code is executed locally on the client. For more information about which types of expressions are executed locally, see Expressions in LINQ to Entities Queries. Literals and ParametersLocal variables, such as the orderID variable in the following example, are evaluated on the client. int orderID = 51987; IQueryable<SalesOrderHeader> salesInfo = from s in context.SalesOrderHeaders where s.SalesOrderID == orderID select s; Method parameters are also evaluated on the client. The orderID parameter passed into the MethodParameterExample method, below, is an example. public static void MethodParameterExample(int orderID) { using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<SalesOrderHeader> salesInfo = from s in context.SalesOrderHeaders where s.SalesOrderID == orderID select s; foreach (SalesOrderHeader sale in salesInfo) { Console.WriteLine("OrderID: {0}, Total due: {1}", sale.SalesOrderID, sale.TotalDue); } } } Casting Literals on the ClientCasting from null to a CLR type is executed on the client: IQueryable<Contact> query = from c in context.Contacts where c.EmailAddress == (string)null select c; Casting to a type, such as a nullable Decimal, is executed on the client: var weight = (decimal?)23.77; IQueryable<Product> query = from product in context.Products where product.Weight == weight select product; Constructors for LiteralsNew CLR types that can be mapped to conceptual model types are executed on the client: var weight = new decimal(23.77); IQueryable<Product> query = from product in context.Products where product.Weight == weight select product; New arrays are also executed on the client. Store ExceptionsAny store errors that are encountered during query execution are passed up to the client, and are not mapped or handled. Store ConfigurationWhen the query executes on the store, the store configuration overrides all client behaviors, and store semantics are expressed for all operations and expressions. This can result in a difference in behavior between CLR and store execution in areas such as null comparisons, GUID ordering, precision and accuracy of operations involving non-precise data types (such as floating point types or DateTime), and string operations. It is important to keep this in mind when examining query results. For example, the following are some differences in behavior between the CLR and SQL Server:
using (AdventureWorksEntities context = new AdventureWorksEntities()) { IQueryable<string> query = from p in context.Products where p.Name == "Reflector" select p.Name; IEnumerable<bool> q = query.Select(c => c.EndsWith("Reflector ")); Console.WriteLine("LINQ to Entities returns: " + q.First()); Console.WriteLine("CLR returns: " + "Reflector".EndsWith("Reflector ")); Query ResultsAfter a LINQ to Entities query is converted to command trees and executed, the query results are usually returned as one of the following:
When the query has executed against the data source, the results are materialized into CLR types and returned to the client. All object materialization is performed by the Entity Framework. Any errors that result from an inability to map between the Entity Framework and the CLR will cause exceptions to be thrown during object materialization. If the query execution returns primitive conceptual model types, the results consist of CLR types that are stand-alone and disconnected from the Entity Framework. However, if the query returns a collection of typed entity objects, represented by ObjectQuery<T>, those types are tracked by the object context. All object behavior (such as child/parent collections, change tracking, polymorphism, and so on) are as defined in the Entity Framework. This functionality can be used in its capacity, as defined in the Entity Framework. For more information, see Working with Objects. Struct types returned from queries (such as anonymous types and nullable complex types) can be of null value. An EntityCollection<TEntity> property of a returned entity can also be of null value. This can result from projecting the collection property of an entity that is of null value, such as calling FirstOrDefault on an ObjectQuery<T> that has no elements. In certain situations, a query might appear to generate a materialized result during its execution, but the query will be executed on the server and the entity object will never be materialized in the CLR. This can cause problems if you are depending on side effects of object materialization. The following example contains a custom class, MyContact, with a LastName property. When the LastName property is set, a count variable is incremented. If you execute the two following queries, the first query will increment count while the second query will not. This is because in the second query the LastName property is projected from the results and the MyContact class is never created, because it is not required to execute the query on the store. public static int count = 0; static void Main(string[] args) { using (AdventureWorksEntities AWEntities = new AdventureWorksEntities()) { var query1 = AWEntities .Contacts .Where(c => c.LastName == "Jones") .Select(c => new MyContact { LastName = c.LastName }); // Execute the first query and print the count. query1.ToList(); Console.WriteLine("Count: " + count); //Reset the count variable. count = 0; var query2 = AWEntities .Contacts .Where(c => c.LastName == "Jones") .Select(c => new MyContact { LastName = c.LastName }) .Select(my => my.LastName); // Execute the second query and print the count. query2.ToList(); Console.WriteLine("Count: " + count); } Console.WriteLine("Hit enter..."); Console.Read(); } public class MyContact { String _lastName; public string LastName { get { return _lastName; } set { _lastName = value; count++; } } } Standard Query Operators in LINQ to Entities QueriesIn a query, you specify the information that you want to retrieve from the data source. A query can also specify how that information should be sorted, grouped, and shaped before it is returned. LINQ provides a set of standard query methods that you can use in a query. Most of these methods operate on sequences; in this context, a sequence is an object whose type implements the IEnumerable<T> interface or the IQueryable<T> interface. The standard query operators query functionality includes filtering, projection, aggregation, sorting, grouping, paging, and more. Some of the more frequently used standard query operators have dedicated keyword syntax so that they can be called by using query expression syntax. A query expression is a different, more readable way to express a query than the method-based equivalent. Query expression clauses are translated into calls to the query methods at compile time. For a list of standard query operators that have equivalent query expression clauses, see Standard Query Operators Overview. Not all of the standard query operators are supported in LINQ to Entities queries. For more information, see Supported and Unsupported LINQ Methods (LINQ to Entities). This topic provides information about the standard query operators that is specific to LINQ to Entities. For more information about known issues in LINQ to Entities queries, see Known Issues and Considerations in LINQ to Entities. Projection and Filtering MethodsProjection refers to transforming the elements of a result set into a desired form. For example, you can project a subset of the properties you need from each object in the result set, you can project a property and perform a mathematical calculation on it, or you can project the entire object from the result set. The projection methods are Select and SelectMany. Filtering refers to the operation of restricting the result set to contain only those elements that match a specified condition. The filtering method is Where. Most overloads of the projection and filtering methods are supported in LINQ to Entities, with the exception of those that accept a positional argument. Join MethodsJoining is an important operation in queries that target data sources that have no navigable relationships to each other. A join of two data sources is the association of objects in one data source with objects in the other data source that share a common attribute or property. The join methods are Join and GroupJoin. Most overloads of the join methods are supported, with the exception of those that use a IEqualityComparer<T>. This is because the comparer cannot be translated to the data source. Set MethodsSet operations in LINQ are query operations that base their result sets on the presence or absence of equivalent elements within the same or in another collection (or set). The set methods are All, Any, Concat, Contains, DefaultIfEmpty, Distinct, EqualAll, Except, Intersect, and Union. Most overloads of the set methods are supported in LINQ to Entities, though there are some differences in behavior compared to LINQ to Objects. However, set methods that use an IEqualityComparer<T> are not supported because the comparer cannot be translated to the data source. Ordering MethodsOrdering, or sorting, refers to the ordering the elements of a result set based on one or more attributes. By specifying more than one sort criterion, you can break ties within a group. Most overloads of the ordering methods are supported, with the exception of those that use an IComparer<T>. This is because the comparer cannot be translated to the data source. The ordering methods are OrderBy, OrderByDescending, ThenBy, ThenByDescending, and Reverse. Because the query is executed on the data source, the ordering behavior may differ from queries executed in the CLR. This is because ordering options, such as case ordering, kanji ordering, and null ordering, can be set in the data source. Depending on the data source, these ordering options might produce different results than in the CLR. If you specify the same key selector in more than one ordering operation, a duplicate ordering will be produced. This is not valid and an exception will be thrown. Grouping MethodsGrouping refers to placing data into groups so that the elements in each group share a common attribute. The grouping method is GroupBy. Most overloads of the grouping methods are supported, with the exception of those that use an IEqualityComparer<T>. This is because the comparer cannot be translated to the data source. The grouping methods are mapped to the data source using a distinct sub-query for the key selector. The key selector comparison sub-query is executed by using the semantics of the data source, including issues related to comparing null values. Aggregate MethodsAn aggregation operation computes a single value from a collection of values. For example, calculating the average daily temperature from a month's worth of daily temperature values is an aggregation operation. The aggregate methods are Aggregate, Average, Count, LongCount, Max, Min, and Sum. Most overloads of the aggregate methods are supported. For behavior related to null values, the aggregate methods use the data source semantics. The behavior of the aggregation methods when null values are involved might be different, depending on which back-end data source is being used. Aggregate method behavior using the semantics of the data source might also be different from what is expected from CLR methods. For example, the default behavior for the Sum method on SQL Server is to ignore any null values instead of throwing an exception. Any exceptions that result from aggregation, such as an overflow from the Sum function, are thrown as data source exceptions or Entity Framework exceptions during the materialization of the query results. For those methods that involve a calculation over a sequence, such as Sum or Average, the actual calculation is performed on the server. As a result, type conversions and loss of precision might occur on the server, and the results might differ from what is expected using CLR semantics. The default behavior of the aggregate methods for null/non-null values is shown in the following table:
Type MethodsThe two LINQ methods that deal with type conversion and testing are both supported in the context of the Entity Framework. This means that the only supported types are types that map to the appropriate Entity Framework type. For a list of these types, see Conceptual Model Types (CSDL). The type methods are Convert and OfType. OfType is supported for entity types. Convert is supported for conceptual model primitive types. The C# is and as methods are also supported. Paging MethodsPaging operations return a single element or multiple elements from a sequence. The supported paging methods are First, FirstOrDefault, Single, SingleOrDefault, Skip, and Take. A number of paging methods are not supported, due either to the inability to map functions to the data source or to the lack of implicit ordering of sets on the data source. Methods that return a default value are restricted to conceptual model primitive types and reference types with null defaults. Paging methods that are executed on an empty sequence will return null. See alsoCLR Method to Canonical Function MappingThe Entity Framework provides a set of canonical functions that implement functionality that is common across many database systems, such as string manipulation and mathematical functions. This enables developers to target a broad range of database systems. When called from a querying technology, such as LINQ to Entities, these canonical functions are translated to the correct corresponding store function for the provider being used. This allows function invocations to be expressed in a common form across data sources, providing a consistent query experience across data sources. The bitwise AND, OR, NOT, and XOR operators are also mapped to canonical functions when the operand is a numeric type. For Boolean operands, the bitwise AND, OR, NOT, and XOR operators compute the logical AND, OR, NOT, and XOR operations of their operands. For more information, see Canonical Functions. For LINQ scenarios, queries against the Entity Framework involve mapping certain CLR methods to methods on the underlying data source through canonical functions. Any method calls in a LINQ to Entities query that are not explicitly mapped to a canonical function will result in a runtime NotSupportedException exception being thrown. System.String Method (Static) Mapping
System.String Method (Instance) Mapping
System.DateTime Method (Static) Mapping
System.DateTime Method (Instance) Mapping
System.DateTimeOffset Method (Instance) MappingThe mapping shown for the get methods on the listed properties.
Note The Equals method returns true if the compared DateTimeOffset objects are equal; false otherwise. The CompareTo method returns 0, 1, or -1 depending on whether the compared DateTimeOffset object is equal, greater than, or less than, respectively. System.DateTimeOffset Method (Static) MappingThe mapping shown for the get methods on the listed properties.
System.TimeSpan Method (Instance) MappingThe mapping shown for the get methods on the listed properties.
Note The Equals method returns true if the compared TimeSpan objects are equal; false otherwise. The CompareTo method returns 0, 1, or -1 depending on whether the compared TimeSpan object is equal, greater than, or less than, respectively. DatePart FunctionThe DatePart Function is mapped to one of several different canonical functions, depending on the value of Interval. The following table displays the canonical function mapping for the supported values of Interval:
Mathematical Function Mapping
Bitwise Operator Mapping
Other Mapping
See alsoSupported and Unsupported LINQ MethodsThis section provides information about the Language-Integrated Query (LINQ) standard query operators that are supported or unsupported in LINQ to Entities queries. Many of the LINQ standard query operators have an overloaded version that accepts an integer argument. The integer argument corresponds to a zero-based index in the sequence that is being operated on, an IEqualityComparer<T>, or IComparer<T>. Unless otherwise specified, these overloaded versions of the LINQ standard query operators are not supported, and attempting to use them will throw an exception. Projection and Restriction MethodsMost of the LINQ projection and restriction methods are supported in LINQ to Entities queries, with the exception of those that accept a positional argument. For more information, see Standard Query Operators in LINQ to Entities Queries. The following table lists the supported and unsupported projection and restriction methods.
Join MethodsThe LINQ join methods are supported in LINQ to Entities, with the exception of those that accept an IEqualityComparer because the comparer cannot be translated to the data source. For more information, see Standard Query Operators in LINQ to Entities Queries. The following table lists the supported and unsupported join methods.
Set MethodsMost of the LINQ set methods are supported in LINQ to Entities queries, with the exception of those that use an EqualityComparer<T>. For more information, see Standard Query Operators in LINQ to Entities Queries. The following table lists the supported and unsupported set methods.
Ordering MethodsMost of the LINQ ordering methods are supported in LINQ to Entities, with the exception of those that accept an IComparer<T>, because the comparer cannot be translated to the data source. For more information, see Standard Query Operators in LINQ to Entities Queries. The following table lists the supported and unsupported ordering methods.
Grouping MethodsMost of the LINQ grouping methods are supported in LINQ to Entities, with the exception of those that accept an IEqualityComparer<T>, because the comparer cannot be translated to the data source. For more information, see Standard Query Operators in LINQ to Entities Queries. The following table lists the supported and unsupported grouping methods.
Aggregate MethodsMost of the aggregate methods that accept primitive data types are supported in LINQ to Entities. For more information, see Standard Query Operators in LINQ to Entities Queries. The following table lists the supported and unsupported aggregate methods.
Type MethodsThe LINQ standard query operators that deal with CLR type conversion and testing are supported in the Entity Framework. Only CLR types that map to conceptual model types are supported in LINQ to Entities. For a list of conceptual model types, see Conceptual Model Types (CSDL). The following table lists the supported and unsupported type methods.
Paging MethodsA number of the LINQ paging methods are not supported in LINQ to Entities queries. For more information, see Standard Query Operators in LINQ to Entities Queries. The following table lists the supported and unsupported paging methods.
See alsoKnown Issues and Considerations in LINQ to EntitiesThis section provides information about known issues with LINQ to Entities queries. LINQ Queries That cannot be CachedStarting with .NET Framework 4.5, LINQ to Entities queries are automatically cached. However, LINQ to Entities queries that apply the Enumerable.Contains operator to in-memory collections are not automatically cached. Also parameterizing in-memory collections in compiled LINQ queries is not allowed. Ordering Information LostProjecting columns into an anonymous type will cause ordering information to be lost in some queries that are executed against a SQL Server 2005 database set to a compatibility level of "80". This occurs when a column name in the order-by list matches a column name in the selector, as shown in the following example: using (AdventureWorksEntities context = new AdventureWorksEntities()) { // Ordering information is lost when executed against a SQL Server 2005 // database running with a compatibility level of "80". var results = context.Contacts.SelectMany(c => c.SalesOrderHeaders) .OrderBy(c => c.SalesOrderDetails.Count) .Select(c => new { c.SalesOrderDetails.Count }); foreach (var result in results) Console.WriteLine(result.Count); } Unsigned Integers Not SupportedSpecifying an unsigned integer type in a LINQ to Entities query is not supported because the Entity Framework does not support unsigned integers. If you specify an unsigned integer, an ArgumentException exception will be thrown during the query expression translation, as shown in the following example. This example queries for an order with ID 48000. using (AdventureWorksEntities context = new AdventureWorksEntities()) { uint s = UInt32.Parse("48000"); IQueryable<SalesOrderDetail> query = from sale in context.SalesOrderDetails where sale.SalesOrderID == s select sale; // NotSupportedException exception is thrown here. try { foreach (SalesOrderDetail order in query) Console.WriteLine("SalesOrderID: " + order.SalesOrderID); } catch (NotSupportedException ex) { Console.WriteLine("Exception: {0}", ex.Message); } } Type Conversion ErrorsIn Visual Basic, when a property is mapped to a column of SQL Server bit type with a value of 1 using the CByte function, a SqlException is thrown with an "Arithmetic overflow error" message. The following example queries the Product.MakeFlag column in the AdventureWorks sample database and an exception is thrown when the query results are iterated over. Using context As New AdventureWorksEntities() Dim productsList = _ From product In context.Products _ Select CByte(product.MakeFlag) ' Throws an SqlException exception with a "Arithmetic overflow error ' for data type tinyint" message when a value of 1 is iterated over. For Each makeFlag In productsList Console.WriteLine(makeFlag) Next End Using Referencing Non-Scalar Variables Not SupportedReferencing a non-scalar variables, such as an entity, in a query is not supported. When such a query executes, a NotSupportedException exception is thrown with a message that states "Unable to create a constant value of type EntityType. Only primitive types ('such as Int32, String, and Guid') are supported in this context." Note Referencing a collection of scalar variables is supported. using (AdventureWorksEntities context = new AdventureWorksEntities()) { Contact contact = context.Contacts.FirstOrDefault(); // Referencing a non-scalar closure in a query will // throw an exception when the query is executed. IQueryable<string> contacts = from c in context.Contacts where c == contact select c.LastName; try { foreach (string name in contacts) { Console.WriteLine("Name: ", name); } } catch (NotSupportedException ex) { Console.WriteLine(ex.Message); } } Nested Queries May Fail with SQL Server 2000With SQL Server 2000, LINQ to Entities queries may fail if they produce nested Transact-SQL queries that are three or more levels deep. Projecting to an Anonymous TypeIf you define your initial query path to include related objects by using the Include method on the ObjectQuery<T> and then use LINQ to project the returned objects to an anonymous type, the objects specified in the include method are not included in the query results. using (AdventureWorksEntities context = new AdventureWorksEntities()) { var resultWithoutRelatedObjects = context.Contacts.Include("SalesOrderHeaders").Select(c => new { c }).FirstOrDefault(); if (resultWithoutRelatedObjects.c.SalesOrderHeaders.Count == 0) { Console.WriteLine("No orders are included."); } } To get related objects, do not project returned types to an anonymous type. using (AdventureWorksEntities context = new AdventureWorksEntities()) { var resultWithRelatedObjects = context.Contacts.Include("SalesOrderHeaders").Select(c => c).FirstOrDefault(); if (resultWithRelatedObjects.SalesOrderHeaders.Count != 0) { Console.WriteLine("Orders are included."); } } See alsoEntity SQL LanguageEntity SQL is a storage-independent query language that is similar to SQL. Entity SQL allows you to query entity data, either as objects or in a tabular form. You should consider using Entity SQL in the following cases:
Using Entity SQL with the EntityClient providerIf you want to use Entity SQL with the EntityClient provider, see the following topics for more information: EntityClient Provider for the Entity Framework How to: Build an EntityConnection Connection String How to: Execute a Query that Returns PrimitiveType Results How to: Execute a Query that Returns StructuralType Results How to: Execute a Query that Returns RefType Results How to: Execute a Query that Returns Complex Types How to: Execute a Query that Returns Nested Collections How to: Execute a Parameterized Entity SQL Query Using EntityCommand How to: Execute a Parameterized Stored Procedure Using EntityCommand How to: Execute a Polymorphic Query How to: Navigate Relationships with the Navigate Operator Using Entity SQL with object queriesIf you want to use Entity SQL with object queries, see the following topics for more information: How to: Execute a Query that Returns Entity Type Objects How to: Execute a Parameterized Query How to: Navigate Relationships Using Navigation Properties How to: Call a User-Defined Function How to: Execute a Query that Returns Anonymous Type Objects How to: Execute a Query that Returns a Collection of Primitive Types How to: Query Related Objects in an EntityCollection How to: Order the Union of Two Queries How to: Page Through Query Results In This SectionSee alsoEntity SQL OverviewEntity SQL is a SQL-like language that enables you to query conceptual models in the Entity Framework. Conceptual models represent data as entities and relationships, and Entity SQL allows you to query those entities and relationships in a format that is familiar to those who have used SQL. The Entity Framework works with storage-specific data providers to translate generic Entity SQL into storage-specific queries. The EntityClient provider supplies a way to execute an Entity SQL command against an entity model and return rich types of data including scalar results, result sets, and object graphs. When you construct EntityCommand objects, you can specify a stored procedure name or the text of a query by assigning an Entity SQL query string to its EntityCommand.CommandText property. The EntityDataReader exposes the results of executing a EntityCommand against an EDM. To execute the command that returns the EntityDataReader, call ExecuteReader. In addition to the EntityClient provider, the Entity Framework enables you to use Entity SQL to execute queries against a conceptual model and return data as strongly-typed CLR objects that are instances of entity types. For more information, see Working with Objects. This section provides conceptual information about Entity SQL. In This SectionHow Entity SQL Differs from Transact-SQL Null Literals and Type Inference Composing Nested Entity SQL Queries See alsoHow Entity SQL Differs from Transact-SQLThis topic describes the differences between Entity SQL and Transact-SQL. Inheritance and Relationships SupportEntity SQL works directly with conceptual entity schemas and supports conceptual model features such as inheritance and relationships. When working with inheritance, it is often useful to select instances of a subtype from a collection of supertype instances. The oftype operator in Entity SQL (similar to oftype in C# Sequences) provides this capability. Support for CollectionsEntity SQL treats collections as first-class entities. For example:
Support for ExpressionsTransact-SQL has subqueries (tables) and expressions (rows and columns). To support collections and nested collections, Entity SQL makes everything an expression. Entity SQL is more composable than Transact-SQL—every expression can be used anywhere. Query expressions always result in collections of the projected types and can be used anywhere a collection expression is allowed. For information about Transact-SQL expressions that are not supported in Entity SQL, see Unsupported Expressions. The following are all valid Entity SQL queries: 1+2 *3 "abc" row(1 as a, 2 as b) { 1, 3, 5} e1 union all e2 set(e1) Uniform Treatment of SubqueriesGiven its emphasis on tables, Transact-SQL performs contextual interpretation of subqueries. For example, a subquery in the from clause is considered to be a multiset (table). But the same subquery used in the select clause is considered to be a scalar subquery. Similarly, a subquery used on the left side of an in operator is considered to be a scalar subquery, while the right side is expected to be a multiset subquery. Entity SQL eliminates these differences. An expression has a uniform interpretation that does not depend on the context in which it is used. Entity SQL considers all subqueries to be multiset subqueries. If a scalar value is desired from the subquery, Entity SQL provides the anyelement operator that operates on a collection (in this case, the subquery), and extracts a singleton value from the collection. Avoiding Implicit Coercions for SubqueriesA related side effect of uniform treatment of subqueries is implicit conversion of subqueries to scalar values. Specifically, in Transact-SQL, a multiset of rows (with a single field) is implicitly converted into a scalar value whose data type is that of the field. Entity SQL does not support this implicit coercion. Entity SQL provides the ANYELEMENT operator to extract a singleton value from a collection, and a select value clause to avoid creating a row-wrapper during a query expression. Select Value: Avoiding the Implicit Row WrapperThe select clause in a Transact-SQL subquery implicitly creates a row wrapper around the items in the clause. This implies that we cannot create collections of scalars or objects. Transact-SQL allows an implicit coercion between a rowtype with one field, and a singleton value of the same data type. Entity SQL provides the select value clause to skip the implicit row construction. Only one item may be specified in a select value clause. When such a clause is used, no row wrapper is constructed around the items in the select clause, and a collection of the desired shape may be produced, for example: select value a. Entity SQL also provides the row constructor to construct arbitrary rows. select takes one or more elements in the projection and results in a data record with fields, as follows: select a, b, c Left Correlation and AliasingIn Transact-SQL, expressions in a given scope (a single clause like select or from) cannot reference expressions defined earlier in the same scope. Some dialects of SQL (including Transact-SQL) do support limited forms of these in the from clause. Entity SQL generalizes left correlations in the from clause, and treats them uniformly. Expressions in the from clause can reference earlier definitions (definitions to the left) in the same clause without the need for additional syntax. Entity SQL also imposes additional restrictions on queries involving group by clauses. Expressions in the select clause and having clause of such queries may only refer to the group by keys via their aliases. The following construct is valid in Transact-SQL but are not in Entity SQL: select t.x + t.y from T as t group by t.x + t.y To do this in Entity SQL: select k from T as t group by (t.x + t.y) as k Referencing Columns (Properties) of Tables (Collections)All column references in Entity SQL must be qualified with the table alias. The following construct (assuming that a is a valid column of table T) is valid in Transact-SQL but not in Entity SQL. select a from T The Entity SQL form is select t.a as A from T as t The table aliases are optional in the from clause. The name of the table is used as the implicit alias. Entity SQL allows the following form as well: select Tab.a from Tab Navigation Through ObjectsTransact-SQL uses the "." notation for referencing columns of (a row of) a table. Entity SQL extends this notation (borrowed from programming languages) to support navigation through properties of an object. For example, if p is an expression of type Person, the following is the Entity SQL syntax for referencing the city of the address of this person. p.Address.City No Support for *Transact-SQL supports the unqualified * syntax as an alias for the entire row, and the qualified * syntax (t.*) as a shortcut for the fields of that table. In addition, Transact-SQL allows for a special count(*) aggregate, which includes nulls. Entity SQL does not support the * construct. Transact-SQL queries of the form select * from T and select T1.* from T1, T2... can be expressed in Entity SQL as select value t from T as t and select value t1 from T1 as t1, T2 as t2..., respectively. Additionally, these constructs handle inheritance (value substitutability), while the select * variants are restricted to top-level properties of the declared type. Entity SQL does not support the count(*) aggregate. Use count(0) instead. Changes to Group ByEntity SQL supports aliasing of group by keys. Expressions in the select clause and having clause must refer to the group by keys via these aliases. For example, this Entity SQL syntax: select k1, count(t.a), sum(t.a) from T as t group by t.b + t.c as k1 ...is equivalent to the following Transact-SQL: select b + c, count(*), sum(a) from T group by b + c Collection-Based AggregatesEntity SQL supports two kinds of aggregates. Collection-based aggregates operate on collections and produce the aggregated result. These can appear anywhere in the query, and do not require a group by clause. For example: select t.a as a, count({1,2,3}) as b from T as t Entity SQL also supports SQL-style aggregates. For example: select a, sum(t.b) from T as t group by t.a as a ORDER BY Clause UsageTransact-SQL allows ORDER BY clauses to be specified only in the topmost SELECT .. FROM .. WHERE block. In Entity SQL you can use a nested ORDER BY expression and it can be placed anywhere in the query, but ordering in a nested query is not preserved. -- The following query will order the results by the last name SELECT C1.FirstName, C1.LastName FROM AdventureWorks.Contact as C1 ORDER BY C1.LastName -- In the following query ordering of the nested query is ignored. SELECT C2.FirstName, C2.LastName FROM (SELECT C1.FirstName, C1.LastName FROM AdventureWorks.Contact as C1 ORDER BY C1.LastName) as C2 IdentifiersIn Transact-SQL, identifier comparison is based on the collation of the current database. In Entity SQL, identifiers are always case insensitive and accent sensitive (that is, Entity SQL distinguishes between accented and unaccented characters; for example, 'a' is not equal to 'ấ'). Entity SQL treats versions of letters that appear the same but are from different code pages as different characters. For more information, see Input Character Set. Transact-SQL Functionality Not Available in Entity SQLThe following Transact-SQL functionality is not available in Entity SQL. DML DDL Imperative Programming Grouping Functions Analytic Functions Built-in Functions, Operators Hints Batching Query Results select * from products; select * from catagories; However, the equivalent Entity SQL is not supported: Select value p from Products as p; Select value c from Categories as c; Entity SQL only supports one result-producing query statement per command. See alsoEntity SQL Quick ReferenceThis topic provides a quick reference to Entity SQL queries. The queries in this topic are based on the AdventureWorks Sales model. LiteralsStringThere are Unicode and non-Unicode character string literals. Unicode strings are prepended with N. For example, N'hello'. The following is an example of a Non-Unicode string literal: 'hello' --same as "hello" Output:
DateTimeIn DateTime literals, both date and time parts are mandatory. There are no default values. Example: DATETIME '2006-12-25 01:01:00.000' --same as DATETIME '2006-12-25 01:01' Output:
IntegerInteger literals can be of type Int32 (123), UInt32 (123U), Int64 (123L), and UInt64 (123UL). Example: --a collection of integers {1, 2, 3} Output:
OtherOther literals supported by Entity SQL are Guid, Binary, Float/Double, Decimal, and null. Null literals in Entity SQL are considered to be compatible with every other type in the conceptual model. Type ConstructorsROWROW constructs an anonymous, structurally-typed (record) value as in: ROW(1 AS myNumber, ‘Name’ AS myName). Example: SELECT VALUE row (product.ProductID as ProductID, product.Name as ProductName) FROM AdventureWorksEntities.Product AS product Output:
MULTISETMULTISET constructs collections, such as: MULTISET(1,2,2,3) --same as-{1,2,2,3}. Example: SELECT VALUE product FROM AdventureWorksEntities.Product AS product WHERE product.ListPrice IN MultiSet (125, 300) Output:
ObjectNamed Type Constructor constructs (named) user-defined objects, such as person("abc", 12). Example: SELECT VALUE AdventureWorksModel.SalesOrderDetail (o.SalesOrderDetailID, o.CarrierTrackingNumber, o.OrderQty, o.ProductID, o.SpecialOfferID, o.UnitPrice, o.UnitPriceDiscount, o.rowguid, o.ModifiedDate) FROM AdventureWorksEntities.SalesOrderDetail AS o Output:
ReferencesREFREF creates a reference to an entity type instance. For example, the following query returns references to each Order entity in the Orders entity set: SELECT REF(o) AS OrderID FROM Orders AS o Output:
The following example uses the property extraction operator (.) to access a property of an entity. When the property extraction operator is used, the reference is automatically dereferenced. Example: SELECT VALUE REF(p).Name FROM AdventureWorksEntities.Product as p Output:
DEREFDEREF dereferences a reference value and produces the result of that dereference. For example, the following query produces the Order entities for each Order in the Orders entity set: SELECT DEREF(o2.r) FROM (SELECT REF(o) AS r FROM LOB.Orders AS o) AS o2.. Example: SELECT VALUE DEREF(REF(p)).Name FROM AdventureWorksEntities.Product as p Output:
CREATEREF AND KEYCREATEREF creates a reference passing a key. KEY extracts the key portion of an expression with type reference. Example: SELECT VALUE Key(CreateRef(AdventureWorksEntities.Product, row(p.ProductID))) FROM AdventureWorksEntities.Product as p Output:
FunctionsCanonicalThe namespace for canonical functions is Edm, as in Edm.Length("string"). You do not have to specify the namespace unless another namespace is imported that contains a function with the same name as a canonical function. If two namespaces have the same function, the user should specific the full name. Example: SELECT Length(c. FirstName) As NameLen FROM AdventureWorksEntities.Contact AS c WHERE c.ContactID BETWEEN 10 AND 12 Output:
Microsoft Provider-SpecificMicrosoft provider-specific functions are in the SqlServer namespace. Example: SELECT SqlServer.LEN(c.EmailAddress) As EmailLen FROM AdventureWorksEntities.Contact AS c WHERE c.ContactID BETWEEN 10 AND 12 Output:
NamespacesUSING specifies namespaces used in a query expression. Example: using SqlServer; LOWER('AA'); Output:
PagingPaging can be expressed by declaring a SKIP and LIMIT sub-clauses to the ORDER BY clause. Example: SELECT c.ContactID as ID, c.LastName as Name FROM AdventureWorks.Contact AS c ORDER BY c.ContactID SKIP 9 LIMIT 3; Output:
GroupingGROUPING BY specifies groups into which objects returned by a query (SELECT) expression are to be placed. Example: SELECT VALUE name FROM AdventureWorksEntities.Product as P GROUP BY P.Name HAVING MAX(P.ListPrice) > 5 Output:
NavigationThe relationship navigation operator allows you to navigate over the relationship from one entity (from end) to another (to end). NAVIGATE takes the relationship type qualified as <namespace>.<relationship type name>. Navigate returns Ref<T> if the cardinality of the to end is 1. If the cardinality of the to end is n, the Collection<Ref<T>> will be returned. Example: SELECT a.AddressID, (SELECT VALUE DEREF(v) FROM NAVIGATE(a, AdventureWorksModel.FK_SalesOrderHeader_Address_BillToAddressID) AS v) FROM AdventureWorksEntities.Address AS a Output:
SELECT VALUE AND SELECTSELECT VALUEEntity SQL provides the SELECT VALUE clause to skip the implicit row construction. Only one item can be specified in a SELECT VALUE clause. When such a clause is used, no row wrapper is constructed around the items in the SELECT clause, and a collection of the desired shape can be produced, for example: SELECT VALUE a. Example: SELECT VALUE p.Name FROM AdventureWorksEntities.Product as p Output:
SELECTEntity SQL also provides the row constructor to construct arbitrary rows. SELECT takes one or more elements in the projection and results in a data record with fields, for example: SELECT a, b, c. Example: SELECT p.Name, p.ProductID FROM AdventureWorksEntities.Product as p Output:
CASE EXPRESSIONThe case expression evaluates a set of Boolean expressions to determine the result. Example: CASE WHEN AVG({25,12,11}) < 100 THEN TRUE ELSE FALSE END Output:
See alsoType System (Entity SQL)Entity SQL supports a number of types:
This section discusses the anonymous types that are not defined in the schema explicitly but are supported by Entity SQL. For information on primitive and nominal types, see Conceptual Model Types (CSDL). RowsThe structure of a row depends on the sequence of typed and named members that the row consists of. A row type has no identity and cannot be inherited from. Instances of the same row type are equivalent if the members are respectively equivalent. Rows have no behavior beyond their structural equivalence and have no equivalent in the common language runtime. Queries can result in structures that contain rows or collections of rows. The API binding between the Entity SQL queries and the host language defines how rows are realized in the query that produced the result. For information on how to construct a row instance, see Constructing Types. CollectionsCollection types represent zero or more instances of other objects. For information on how to construct collection, see Constructing Types. ReferencesA reference is a logical pointer to a specific entity in a specific entity set. Entity SQL supports the following operators to construct, deconstruct, and navigate through references: You can navigate through a reference by using the member access (dot) operator(.). The following snippet extracts the Id property (of Order) by navigating through the r (reference) property. select o2.r.Id from (select ref(o) as r from LOB.Orders as o) as o2 If the reference value is null, or if the target of the reference does not exist, the result is null. See alsoType Definitions (Entity SQL)A type definition is used in the declaration statement of an Entity SQL Inline function. RemarksThe declaration statement for an inline function consists of the FUNCTION keyword followed by the identifier representing the function name (for example, "MyAvg") followed by a parameter definition list in parenthesis (for example, "dues Collection(Decimal)"). The parameter definition list consists of zero or more parameter definitions. Each parameter definition consists of an identifier (the name of the parameter to the function, for example, "dues") followed by a type definition (for example, "Collection(Decimal)"). The type definitions can be either:
You can also nest type definitions (for example, "Collection(Row(x Ref(AdventureWorks.Order)))"). The type definition options are:
The property definition option is IdentifierName type_definition. Supported types are any types in the current namespace. These include both primitive and entity types. Supported entity types refer to only entity types in the current namespace. They do not include primitive types. ExamplesThe following is an example of a simple type definition. USING Microsoft.Samples.Entity Function MyRound(p1 EDM.Decimal) AS ( Round(p1) ) MyRound(CAST(1.7 as EDM.Decimal)) The following is an example of a COLLECTION type definition. USING Microsoft.Samples.Entity Function MyRound(p1 Collection(EDM.Decimal)) AS ( Select Round(p1) from p1 ) MyRound({CAST(1.7 as EDM.Decimal), CAST(2.7 as EDM.Decimal)}) The following is an example of a ROW type definition. USING Microsoft.Samples.Entity Function MyRound(p1 Row(x EDM.Decimal)) AS ( Round(p1.x) ) select MyRound(row(a as x)) from {CAST(1.7 as EDM.Decimal), CAST(2.7 as EDM.Decimal)} as a The following is an example of a REF type definition. USING Microsoft.Samples.Entity Function UnReference(p1 Ref(AdventureWorks.Order)) AS ( Deref(p1) ) select Ref(x) from AdventureWorksEntities.SalesOrderHeaders as x See alsoConstructing Types (Entity SQL)Entity SQL provides three kinds of constructors: row constructors, named type constructors, and collection constructors. Row ConstructorsYou use row constructors in Entity SQL to construct anonymous, structurally typed records from one or more values. The result type of a row constructor is a row type whose field types correspond to the types of the values used to construct the row. For example, the following expression constructs a value of type Record(a int, b string, c int): ROW(1 AS a, "abc" AS b, a + 34 AS c) If you do not provide an alias for an expression in a row constructor, the Entity Framework will try to generate one. For more information, see the "Aliasing Rules" section in Identifiers. The following rules apply to expression aliasing in a row constructor:
For more information about row constructors, see ROW. Collection ConstructorsYou use collection constructors in Entity SQL to create an instance of a multiset from a list of values. All the values in the constructor must be of mutually compatible type T, and the constructor produces a collection of type Multiset<T>. For example, the following expression creates a collection of integers: Multiset(1, 2, 3) {1, 2, 3} Empty multiset constructors are not allowed because the type of the elements cannot be determined. The following is not valid: multiset() {} For more information, see MULTISET. Named Type Constructors (NamedType Initializers)Entity SQL allows type constructors (initializers) to create instances of named complex types and entity types. For example, the following expression creates an instance of a Person type. Person("abc", 12) The following expression creates an instance of a complex type. MyModel.ZipCode(‘98118’, ‘4567’) The following expression creates an instance of a nested complex type. MyModel.AddressInfo('My street address', 'Seattle', 'WA', MyModel.ZipCode('98118', '4567')) The following expression creates an instance of an entity with a nested complex type. MyModel.Person("Bill", MyModel.AddressInfo('My street address', 'Seattle', 'WA', MyModel.ZipCode('98118', '4567'))) The following example shows how to initialize a property of a complex type to null. MyModel.ZipCode(‘98118’, null) The arguments to the constructor are assumed to be in the same order as the declaration of the attributes of the type. For more information, see Named Type Constructor. See alsoQuery Plan Caching (Entity SQL)Whenever an attempt to execute a query is made, the query pipeline looks up its query plan cache to see whether the exact query is already compiled and available. If so, it reuses the cached plan rather than building a new one. If a match is not found in the query plan cache, the query is compiled and cached. A query is identified by its Entity SQL text and parameter collection (names and types). All text comparisons are case-sensitive. ConfigurationQuery plan caching is configurable through the EntityCommand. To enable or disable query plan caching through EntityCommand.EnablePlanCaching, set this property to true or false. Disabling plan caching for individual dynamic queries that are unlikely to be used more then once improves performance. You can enable query plan caching through EnablePlanCaching. Recommended PracticeDynamic queries should be avoided, in general. The following dynamic query example is vulnerable to SQL injection attacks, because it takes user input directly without any validation. "SELECT sp.SalesYTD FROM AdventureWorksEntities.SalesPerson as sp WHERE sp.EmployeeID = " + employeeTextBox.Text; If you do use dynamically generated queries, consider disabling query plan caching to avoid unnecessary memory consumption for cache entries that are unlikely to be reused. Query plan caching on static queries and parameterized queries can provide performance benefits. The following is an example of a static query: "SELECT sp.SalesYTD FROM AdventureWorksEntities.SalesPerson as sp"; For queries to be matched properly by the query plan cache, they should comply with the following requirements:
You should avoid the following query patterns, which unnecessarily consume slots in the query plan cache:
See alsoNamespaces (Entity SQL)Entity SQL introduces namespaces to avoid name conflicts for global identifiers such as type names, entity sets, functions, and so on. The namespace support in Entity SQL is similar to the namespace support in the .NET Framework. Entity SQL provides two forms of the USING clause: qualified namespaces (where a shorter alias is provided for the namespace), and unqualified namespaces, as illustrated in the following example: USING System.Data; USING tsql = System.Data; Name Resolution RulesIf an identifier cannot be resolved in the local scopes, Entity SQL tries to locate the name in the global scopes (the namespaces). Entity SQL first tries to match the identifier (prefix) with one of the qualified namespaces. If there is a match, Entity SQL tries to resolve the rest of the identifier in the specified namespace. If no match is found, an exception is thrown. Next, Entity SQL tries to search all unqualified namespaces (specified in the prolog) for the identifier. If the identifier can be located in exactly one namespace, that location is returned. If more than one namespace has a match for that identifier, an exception is thrown. If no namespace can be identified for the identifier, Entity SQL passes the name onto the next outward scope (the DbCommand or DbConnection object), as illustrated in the following example: SELECT TREAT(p AS NamespaceName.Employee) FROM ContainerName.Person AS p WHERE p IS OF (NamespaceName.Employee) Differences from the .NET FrameworkIn the .NET Framework, you can use partially qualified namespaces. Entity SQL does not allow this. ADO.NET UsageQueries are expressed through ADO.NET DbCommand objects. DbCommand objects can be built over DbConnection objects. Namespaces can also be specified as part of the DbCommand and DbConnection objects. If Entity SQL cannot resolve an identifier within the query itself, the external namespaces are probed (based on similar rules). See alsoIdentifiers (Entity SQL)Identifiers are used in Entity SQL to represent query expression aliases, variable references, properties of objects, functions, and so on. Entity SQL provides two kinds of identifiers: simple identifiers and quoted identifiers. Simple IdentifiersA simple identifier in Entity SQL is a sequence of alphanumeric and underscore characters. The first character of the identifier must be an alphabetical character (a-z or A-Z). Quoted IdentifiersA quoted identifier is any sequence of characters enclosed in square brackets ([]). Quoted identifiers let you specify identifiers with characters that are not valid in identifiers. All characters between the square brackets become part of the identifier, including all white space. A quoted identifier cannot include the following characters:
A quoted-identifier can include Unicode characters. Quoted identifiers enable you to create property name characters that are not valid in identifiers, as illustrated in the following example: SELECT c.ContactName AS [Contact Name] FROM customers AS c You can also use quoted identifiers to specify an identifier that is a reserved keyword of Entity SQL. For example, if the type Email has a property named "From", you can disambiguate it from the reserved keyword FROM by using square brackets, as follows: SELECT e.[From] FROM emails AS e You can use a quoted identifier on the right side of a dot (.) operator. SELECT t FROM ts as t WHERE t.[property] == 2 To use the square bracket in an identifier, add an extra square bracket. In the following example "abc]" is the identifier: SELECT t from ts as t WHERE t.[abc]]] == 2 For quoted identifier comparison semantics, see Input Character Set. Aliasing RulesWe recommend specifying aliases in Entity SQL queries whenever needed, including the following Entity SQL constructs:
Valid AliasesValid aliases in Entity SQL are any simple identifier or quoted identifier. Alias GenerationIf no alias is specified in an Entity SQL query expression, Entity SQL tries to generate an alias based on the following simple rules:
We recommend that you do not use implicit aliasing if you want to use the alias name later. Anytime aliases (implicit or explicit) conflict or are repeated in the same scope, there will be a compile error. An implicit alias will pass compilation even if there is an explicit or implicit alias of the same name. Implicit aliases are autogenerated based on user input. For example, the following line of code will generate NAME as an alias for both columns and therefore will conflict. SELECT product.NAME, person.NAME The following line of code, which uses explicit aliases, will also fail. However, the failure will be more apparent by reading the code. SELECT 1 AS X, 2 AS X … Scoping RulesEntity SQL defines scoping rules that determine when particular variables are visible in the query language. Some expressions or statements introduce new names. The scoping rules determine where those names can be used, and when or where a new declaration with the same name as another can hide its predecessor. When names are defined in an Entity SQL query, they are said to be defined within a scope. A scope covers an entire region of the query. All expressions or name references within a certain scope can see names that are defined within that scope. Before a scope begins and after it ends, names that are defined within the scope cannot be referenced. Scopes can be nested. Parts of Entity SQL introduce new scopes that cover entire regions, and these regions can contain other Entity SQL expressions that also introduce scopes. When scopes are nested, references can be made to names that are defined in the innermost scope, which contains the reference. References can also be made to any names that are defined in any outer scopes. Any two scopes defined within the same scope are considered sibling scopes. References cannot be made to names that are defined within sibling scopes. If a name declared in an inner scope matches a name declared in an outer scope, references within the inner scope or within scopes declared within that scope refer only to the newly declared name. The name in the outer scope is hidden. Even within the same scope, names cannot be referenced before they are defined. Global names can exist as part of the execution environment. This can include names of persistent collections or environment variables. For a name to be global, it must be declared in the outermost scope. Parameters are not in a scope. Because references to parameters include special syntax, names of parameters will never collide with other names in the query. Query ExpressionsAn Entity SQL query expression introduces a new scope. Names that are defined in the FROM clause are introduced into the from scope in order of appearance, left to right. In the join list, expressions can refer to names that were defined earlier in the list. Public properties (fields and so on) of elements identified in the FROM clause are not added to the from-scope. They must be always referenced by the alias-qualified name. Typically, all parts of the SELECT expression are considered within the from-scope. The GROUP BY clause also introduces a new sibling scope. Each group can have a group name that refers to the collection of elements in the group. Each grouping expression will also introduce a new name into the group-scope. Additionally, the nest aggregate (or the named group) is also added to the scope. The grouping expressions themselves are within the from-scope. However, when a GROUP BY clause is used, the select-list (projection), HAVING clause, and ORDER BY clause are considered to be within the group-scope, and not the from-scope. Aggregates receive special treatment, as described in the following bulleted list. The following are additional notes about scopes:
Aggregate HandlingEntity SQL supports two forms of aggregates: collection-based aggregates and group-based aggregates. Collection-based aggregates are the preferred construct in Entity SQL, and group-based aggregates are supported for SQL compatibility. When resolving an aggregate, Entity SQL first tries to treat it as a collection-based aggregate. If that fails, Entity SQL transforms the aggregate input into a reference to the nest aggregate and tries to resolve this new expression, as illustrated in the following example. AVG(t.c) becomes AVG(group..(t.c)) See alsoParameters (Entity SQL)Parameters are variables that are defined outside Entity SQL, usually through a binding API that is used by a host language. Each parameter has a name and a type. Parameter names are defined in query expressions with the at (@) symbol as a prefix. This disambiguates them from the names of properties or other names that are defined in the query. The host-language binding API provides APIs for binding parameters. Exampleselect c from LOB.Customers as c where c.Name = @name See alsoVariables (Entity SQL)VariableA variable expression is a reference to a named expression defined in the current scope. A variable reference must be a valid Entity SQL identifier, as defined in Identifiers. The following example shows the use of a variable in the expression. The c in the FROM clause is the definition of the variable. The use of c in the SELECT clause represents the variable reference. select c from LOB.customers as c See alsoUnsupported expressionsThis topic describes Transact-SQL expressions that are not supported in Entity SQL. For more information, see How Entity SQL Differs from Transact-SQL. Quantified predicatesTransact-SQL allows constructs of the following form: sal > all (select salary from employees) sal > any (select salary from employees) Entity SQL, however, does not support such constructs. Equivalent expressions can be written in Entity SQL as follows: not exists(select 0 from employees as e where sal <= e.salary) exists(select 0 from employees as e where sal > e.salary) * operatorTransact-SQL supports the use of the * operator in the SELECT clause to indicate that all columns should be projected out. This is not supported in Entity SQL. See alsoLiterals (Entity SQL)This topic describes Entity SQL support for literals. NullThe null literal is used to represent the value null for any type. A null literal is compatible with any type. Typed nulls can be created by a cast over a null literal. For more information, see CAST. For rules about where free floating null literals can be used, see Null Literals and Type Inference. BooleanBoolean literals are represented by the keywords true and false. IntegerInteger literals can be of type Int32 or Int64. An Int32 literal is a series of numeric characters. An Int64 literal is series of numeric characters followed by an uppercase L. DecimalA fixed-point number (decimal) is a series of numeric characters, a dot (.) and another series of numeric characters followed by an uppercase "M". Float, DoubleA double-precision floating point number is a series of numeric characters, a dot (.) and another series of numeric characters possibly followed by an exponent. A single-precisions floating point number (or float) is a double-precision floating point number syntax followed by the lowercase f. StringA string is a series of characters enclosed in quote marks. Quotes can be either both single-quotes (') or both double-quotes ("). Character string literals can be either Unicode or non-Unicode. To declare a character string literal as Unicode, prefix the literal with an uppercase "N". The default is non-Unicode character string literals. There can be no spaces between the N and the string literal payload, and the N must be uppercase. 'hello' -- non-Unicode character string literal N'hello' -- Unicode character string literal "x" N"This is a string!" 'so is THIS' DateTimeA datetime literal is independent of locale and is composed of a date part and a time part. Both date and time parts are mandatory and there are no default values. The date part must have the format: YYYY-MM-DD, where YYYY is a four digit year value between 0001 and 9999, MM is the month between 1 and 12 and DD is the day value that is valid for the given month MM. The time part must have the format: HH:MM[:SS[.fffffff]], where HH is the hour value between 0 and 23, MM is the minute value between 0 and 59, SS is the second value between 0 and 59 and fffffff is the fractional second value between 0 and 9999999. All value ranges are inclusive. Fractional seconds are optional. Seconds are optional unless fractional seconds are specified; in this case, seconds are required. When seconds or fractional seconds are not specified, the default value of zero will be used instead. There can be any number of spaces between the DATETIME symbol and the literal payload, but no new lines. DATETIME'2006-10-1 23:11' DATETIME'2006-12-25 01:01:00.0000000' -- same as DATETIME'2006-12-25 01:01' TimeA time literal is independent of locale and composed of a time part only. The time part is mandatory and there is no default value. It must have the format HH:MM[:SS[.fffffff]], where HH is the hour value between 0 and 23, MM is the minute value between 0 and 59, SS is the second value between 0 and 59, and fffffff is the second fraction value between 0 and 9999999. All value ranges are inclusive. Fractional seconds are optional. Seconds are optional unless fractional seconds are specified; in this case, seconds are required. When seconds or fractions are not specified, the default value of zero will be used instead. There can be any number of spaces between the TIME symbol and the literal payload, but no new lines. TIME‘23:11’ TIME‘01:01:00.1234567’ DateTimeOffsetA datetimeoffset literal is independent of locale and composed of a date part, a time part, and an offset part. All date, time, and offset parts are mandatory and there are no default values. The date part must have the format YYYY-MM-DD, where YYYY is a four digit year value between 0001 and 9999, MM is the month between 1 and 12, and DD is the day value that is valid for the given month. The time part must have the format HH:MM[:SS[.fffffff]], where HH is the hour value between 0 and 23, MM is the minute value between 0 and 59, SS is the second value between 0 and 59, and fffffff is the fractional second value between 0 and 9999999. All value ranges are inclusive. Fractional seconds are optional. Seconds are optional unless fractional seconds are specified; in this case, seconds are required. When seconds or fractions are not specified, the default value of zero will be used instead. The offset part must have the format {+|-}HH:MM, where HH and MM have the same meaning as in the time part. The range of the offset, however, must be between -14:00 and + 14:00 There can be any number of spaces between the DATETIMEOFFSET symbol and the literal payload, but no new lines. DATETIMEOFFSET‘2006-10-1 23:11 +02:00’ DATETIMEOFFSET‘2006-12-25 01:01:00.0000000 -08:30’ Note A valid Entity SQL literal value can fall outside the supported ranges for CLR or the data source. This might result in an exception BinaryA binary string literal is a sequence of hexadecimal digits delimited by single quotes following the keyword binary or the shortcut symbol X or x. The shortcut symbol X is case insensitive. A zero or more spaces are allowed between the keyword binary and the binary string value. Hexadecimal characters are also case insensitive. If the literal is composed of an odd number of hexadecimal digits, the literal will be aligned to the next even hexadecimal digit by prefixing the literal with a hexadecimal zero digit. There is no formal limit on the size of the binary string. Binary'00ffaabb' X'ABCabc' BINARY '0f0f0f0F0F0F0F0F0F0F' X'' –- empty binary string GuidA GUID literal represents a globally unique identifier. It is a sequence formed by the keyword GUID followed by hexadecimal digits in the form known as registry format: 8-4-4-4-12 enclosed in single quotes. Hexadecimal digits are case insensitive. There can be any number of spaces between the GUID symbol and the literal payload, but no new lines. Guid'1afc7f5c-ffa0-4741-81cf-f12eAAb822bf' GUID '1AFC7F5C-FFA0-4741-81CF-F12EAAB822BF' See alsoNull Literals and Type Inference (Entity SQL)Null literals are compatible with any type in the Entity SQL type system. However, for the type of a null literal to be inferred correctly, Entity SQL imposes certain constraints on where a null literal can be used. Typed NullsTyped nulls can be used anywhere. Type inference is not required for typed nulls because the type is known. For example, you can construct a null of type Int16 with the following Entity SQL construct: (cast(null as Int16)) Free-Floating Null LiteralsFree-floating null literals can be used in the following contexts:
Free-floating null literals cannot be used in other scenarios. For example, they cannot be used as arguments to a row constructor. See alsoInput Character Set (Entity SQL)Entity SQL accepts UNICODE characters encoded in UTF-16. String literals can contain any UTF-16 character enclosed in single quotes. For example, N'文字列リテラル'. When string literals are compared, the original UTF-16 values are used. For example, N'ABC' is different in Japanese and Latin codepages. Comments can contain any UTF-16 character. Escaped identifiers can contain any UTF-16 character enclosed in square brackets. For example, [エスケープされた識別子]. The comparison of UTF-16 escaped identifiers is case insensitive. Entity SQL treats versions of letters that appear the same but are from different code pages as different characters. For example, [ABC] is equivalent to [abc] if the corresponding characters are from the same code page. However, if the same two identifiers are from different code pages, they are not equivalent. White space is any UTF-16 white space character. A newline is any normalized UTF-16 newline character. For example, '\n' and '\r\n' are considered newline characters, but '\r' is not a newline character. Keywords, expressions, and punctuation can be any UTF-16 character that normalizes to Latin. For example, SELECT in a Japanese codepage is a valid keyword. Keywords, expressions, and punctuation can only be Latin characters. SELECT in a Japanese codepage is not a keyword. +, -, *, /, =, (, ), ‘, [, ] and any other language construct not quoted here can only be Latin characters. Simple identifiers can only be Latin characters. This avoids ambiguity during comparison, because original values are compared. For example, ABC would be different in Japanese and Latin codepages. See alsoQuery Expressions (Entity SQL)A query expression combines many different query operators into a single syntax. Entity SQL provides various kinds of expressions, including the following: literals, parameters, variables, operators, functions, set operators, and so on. For more information, see Entity SQL Reference. ClausesA query expression is composed of a series of clauses that apply successive operations to a collection of objects. They are based on the same clauses found in standard a SQL select statement: SELECT, FROM, WHERE, GROUP BY, HAVING, and ORDER BY. ScopeNames defined in the FROM clause are introduced into the FROM scope in order of appearance, left to right. In the JOIN list, expressions can refer to names defined earlier in the list. Public properties of elements identified in the FROM clause are not added to the FROM scope: They must be always referenced through the alias-qualified name. Normally, all parts of the select expression are considered within the FROM scope. See alsoFunctions (Entity SQL)Entity SQL supports user-defined functions, canonical functions, and provider-specific functions. User-defined functions are specified in the conceptual model or inline in the query. For more information, see User-Defined Functions. Canonical functions are predefined in the Entity Framework and should be supported by data providers. Entity SQL commands will fail if a user calls a function that is not supported by a provider. Therefore, canonical functions are generally recommended over store-specific functions, which are in a provider-specific namespace. For more information, see Canonical Functions. The Microsoft SQL Client Managed Provider provides a set of provider-specific functions. For more information, see SqlClient for Entity Framework Functions. In This SectionSee alsoUser-Defined Functions (Entity SQL)Entity SQL supports calling user-defined functions in a query. You can define these functions inline with the query (see How to: Call a User-Defined Function) or as part of the conceptual model (see How to: Define Custom Functions in the Conceptual Model). Conceptual model functions are defined as an Entity SQL command in the DefiningExpression element of a Function element in the conceptual model. Entity SQL enables you to define functions in the query command itself. The FUNCTION operator defines inline functions. You can define multiple functions in a single command, and these functions can have the same function name, as long as the function signatures are unique. For more information, see Function Overload Resolution. See alsoFunction Overload Resolution (Entity SQL)This topic describes how Entity SQL functions are resolved. More than one function can be defined with the same name, as long as the functions have unique signatures. When this is the case, the following criteria must be applied to determine which function is referenced by a given expression. These criteria are applied in sequence. The first criterion that applies only to a single function is the resolved function.
If none of these criteria result in a single function being selected, the function invocation expression is ambiguous. Even if a single function can be extracted using these rules, the arguments still might not match the parameters. An error is raised in this case. For user-defined functions, the definition for an inline query function takes precedence even when a model-defined function exists with a signature that is a better match for the user-defined function. See alsoAggregate Functions (Entity SQL)An aggregate is a language construct that condenses a collection into a scalar as a part of a group operation. Entity SQL aggregates come in two forms:
Entity SQL first tries to interpret an expression as a collection function and if the expression is in the context of a SELECT expression it interprets it as a group aggregate. Entity SQL defines a special aggregate operator called GROUPPARTITION. This operator enables you to get a reference to the grouped input set. This allows more advanced grouping queries, where the results of the GROUP BY clause can be used in places other than group aggregate or collection functions. Collection FunctionsCollection functions operate on collections and return a scalar value. For example, if orders is a collection of all orders, you can calculate the earliest ship date with the following expression: min(select value o.ShipDate from LOB.Orders as o) Group AggregatesGroup aggregates are calculated over a group result as defined by the GROUP BY clause. The GROUP BY clause partitions data into groups. For each group in the result, the aggregate function is applied and a separate aggregate is calculated by using the elements in each group as inputs to the aggregate calculation. When a GROUP BY clause is used in a SELECT expression, only grouping expression names, aggregates, or constant expressions may be present in the projection, HAVING, or ORDER BY clause. The following example calculates the average quantity ordered for each product. select p, avg(ol.Quantity) from LOB.OrderLines as ol group by ol.Product as p It is possible to have a group aggregate without an explicit GROUP BY clause in the SELECT expression. All elements will be treated as a single group, equivalent to the case of specifying a grouping based on a constant. select avg(ol.Quantity) from LOB.OrderLines as ol select avg(ol.Quantity) from LOB.OrderLines as ol group by 1 Expressions used in the GROUP BY clause are evaluated by using the same name-resolution scope that would be visible to the WHERE clause expression. See alsoOperator Precedence (Entity SQL)When an Entity SQL query has multiple operators, operator precedence determines the sequence in which the operations are performed. The order of execution can significantly affect the query result. Operators have the precedence levels shown in the following table. An operator with a higher level is evaluated before an operator with a lower level.
When two operators in an expression have the same operator precedence level, they are evaluated left to right, based on their position in the query. For example, x+y-z is evaluated as (x+y)-z. You can use parentheses to override the defined precedence of the operators in a query. Everything within parentheses is evaluated first to yield a single result before that result can be used by any operator outside the parentheses. For example, x+y*z multiplies y by z and then adds x, but (x+y)*z adds x to y and then multiplies the result by z. See alsoPaging (Entity SQL)Physical paging can be performed by using the SKIP and LIMIT sub-clauses in the ORDER BY clause. To perform physical paging deterministically, you should use SKIP and LIMIT. If you only want to restrict the number of rows in the result in a non-deterministic way, you should use TOP. TOP and SKIP/LIMIT are mutually exclusive. TOP OverviewThe SELECT clause can have an optional TOP sub-clause following the optional ALL/DISTINCT modifier. The TOP sub-clause specifies that only the first set of rows will be returned from the query result. For more information, see TOP. SKIP And LIMIT OverviewSKIP and LIMIT are part of the ORDER BY clause. If a SKIP expression sub-clause is present in a ORDER BY clause, the results will be sorted according to the sort specification and the result set will include row(s) starting from the next row immediately after the SKIP expression. For example, SKIP 5 will skip the first five rows and return from the sixth row forward. If a LIMIT expression sub-clause is present in an ORDER BY clause, the query will be sorted according to the sort specification and the resulting number of rows will be restricted by the LIMIT expression. For instance, LIMIT 5 will restrict the result set to five instances or rows. SKIP and LIMIT do not have to be used together; you can use just SKIP or just LIMIT with ORDER BY clause. For more information, see the following topics: See alsoComparison Semantics (Entity SQL)Performing any of the following Entity SQL operators involves comparison of type instances: Explicit comparisonEquality operations:
Ordering operations:
Nullability operations:
Explicit distinctionEquality distinction:
Ordering distinction:
Implicit distinctionSet operations and predicates (equality):
Item predicates (equality):
Supported CombinationsThe following table shows all the supported combinations of comparison operators for each kind of type:
1The references of the given entity type instances are implicitly compared, as shown in the following example: SELECT p1, p2 FROM AdventureWorksEntities.Product AS p1 JOIN AdventureWorksEntities.Product AS p2 WHERE p1 != p2 OR p1 IS NULL An entity instance cannot be compared to an explicit reference. If this is attempted, an exception is thrown. For example, the following query will throw an exception: SELECT p1, p2 FROM AdventureWorksEntities.Product AS p1 JOIN AdventureWorksEntities.Product AS p2 WHERE p1 != REF(p2) 2Properties of complex types are flattened out before being sent to the store, so they become comparable (as long as all their properties are comparable). Also see 4. 3The Entity Framework runtime detects the unsupported case and throws a meaningful exception without engaging the provider/store. 4An attempt is made to compare all properties. If there is a property that is of a non-comparable type, such as text, ntext, or image, a server exception might be thrown. 5All individual elements of the references are compared (this includes the entity set name and all the key properties of the entity type). See alsoComposing Nested Entity SQL QueriesEntity SQL is a rich functional language. The building block of Entity SQL is an expression. Unlike conventional SQL, Entity SQL is not limited to a tabular result set: Entity SQL supports composing complex expressions that can have literals, parameters, or nested expressions. A value in the expression can be parameterized or composed of some other expression. Nested ExpressionsA nested expression can be placed anywhere a value of the type it returns is accepted. For example: -- Returns a hierarchical collection of three elements at top-level. -- x must be passed in the parameter collection. ROW(@x, {@x}, {@x, 4, 5}, {@x, 7, 8, 9}) -- Returns a hierarchical collection of one element at top-level. -- x must be passed in the parameter collection. {{{@x}}}; A nested query can be placed in a projection clause. For example: -- Returns a collection of rows where each row contains an Address entity. -- and a collection of references to its corresponding SalesOrderHeader entities. SELECT address, (SELECT DEREF(soh) FROM NAVIGATE(address, AdventureWorksModel.FK_SalesOrderHeader_Address_BillToAddressID) AS soh) AS salesOrderHeader FROM AdventureWorksEntities.Address AS address In Entity SQL, nested queries must always be enclosed in parentheses: -- Pseudo-Entity SQL ( SELECT … FROM … ) UNION ALL ( SELECT … FROM … ); The following example demonstrates how to properly nest expressions in Entity SQL: How to: Order the Union of Two Queries. Nested Queries in ProjectionNested queries in the project clause might get translated into Cartesian product queries on the server. In some backend servers, including SLQ Server, this can cause the TempDB table to get very large, which can adversely affect server performance. The following is an example of such a query: SELECT c, (SELECT c, (SELECT c FROM AdventureWorksModel.Vendor AS c ) As Inner2 FROM AdventureWorksModel.JobCandidate AS c ) As Inner1 FROM AdventureWorksModel.EmployeeDepartmentHistory AS c Ordering Nested QueriesIn the Entity Framework, a nested expression can be placed anywhere in the query. Because Entity SQL allows great flexibility in writing queries, it is possible to write a query that contains an ordering of nested queries. However, the order of a nested query is not preserved. -- The following query will order the results by last name. SELECT C1.FirstName, C1.LastName FROM AdventureWorksModel.Contact as C1 ORDER BY C1.LastName -- In the following query, ordering of the nested query is ignored. SELECT C2.FirstName, C2.LastName FROM (SELECT C1.FirstName, C1.LastName FROM AdventureWorksModel.Contact as C1 ORDER BY C1.LastName) as C2 See alsoNullable Structured Types (Entity SQL)A null instance of a structured type is an instance that does not exist. This is different from an existing instance in which all properties have null values. This topic describes the nullable structured types, including which types are nullable and which code patterns produce null instances of structured nullable types. Kinds of Nullable Structured TypesThere are three kinds of nullable structure types:
Code Patterns that Produce Null Instances of Structured TypesThe following scenarios produce null instances:
See alsoEntity SQL referenceThis section contains Entity SQL reference articles. This article summarizes and groups the Entity SQL operators by category. Arithmetic operatorsArithmetic operators perform mathematical operations on two expressions of one or more numeric data types. The following table lists the Entity SQL arithmetic operators:
Canonical functionsCanonical functions are supported by all data providers and can be used by all querying technologies. The following table lists the canonical functions:
Comparison operatorsComparison operators are defined for the following types: Byte, Int16, Int32, Int64, Double, Single, Decimal, String, DateTime, Date, Time, DateTimeOffset. Implicit type promotion occurs for the operands before the comparison operator is applied. Comparison operators always yield Boolean values. When at least one of the operands is null, the result is null. Equality and inequality are defined for any object type that has identity, such as the Boolean type. Non-primitive objects with identity are considered equal if they share the same identity. The following table lists the Entity SQL comparison operators:
Logical and case expression operatorsLogical operators test for the truth of a condition. The CASE expression evaluates a set of Boolean expressions to determine the result. The following table lists the logical and CASE expression operators:
Query operatorsQuery operators are used to define query expressions that return entity data. The following table lists query operators:
Reference operatorsA reference is a logical pointer (foreign key) to a specific entity in a specific entity set. Entity SQL supports the following operators to construct, deconstruct, and navigate through references:
Set operatorsEntity SQL provides various powerful set operations. This includes set operators similar to Transact-SQL operators such as UNION, INTERSECT, EXCEPT, and EXISTS. Entity SQL also supports operators for duplicate elimination (SET), membership testing (IN), and joins (JOIN). The following table lists the Entity SQL set operators:
Type operatorsEntity SQL provides operations that allow the type of an expression (value) to be constructed, queried, and manipulated. The following table lists operators that are used to work with types:
Other operatorsThe following table lists other Entity SQL operators:
See also+ (Add)Adds two numbers. Syntaxexpression + expression Argumentsexpression Result TypesThe data type that results from the implicit type promotion of the two arguments. For more information about implicit type promotion, see Type System. RemarksFor EDM.String types, addition is concatenation. ExampleThe following Entity SQL query uses the + arithmetic operator to add two numbers. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice = @price1 + @price2 See also+ (String Concatenation) (Entity SQL)Concatenates two strings. Syntaxexpression + expression Argumentsexpression Result TypesThe data type that results from the implicit type promotion of the two arguments. For more information about implicit type promotion, see Type System. ExampleThe following Entity SQL query uses the + operator to concatenates two strings. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE 'Name=[' + e.Name + ']' FROM AdventureWorksEntities.Products AS e See also- (Negative) (Entity SQL)Returns the negative of the value of a numeric expression. Syntax- expression Argumentsexpression Result TypesThe data type of expression. RemarksIf expression is an unsigned type, the result type will be the signed type that most closely relates to the type of expression. For example, if expression is of type Byte, a value of type Int16 will be returned. ExampleThe following Entity SQL query uses the - arithmetic operator to return the negative of the value of a numeric expression. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice = -(-@price) See also- (Subtract) (Entity SQL)Subtracts two numbers. Syntaxexpression - expression Argumentsexpression Result TypesThe data type that results from the implicit type promotion of the two arguments. For more information about implicit type promotion, see Type System. ExampleThe following Entity SQL query uses the - arithmetic operator to subtract two numbers. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice = @price1 - @price2 See also* (Multiply) (Entity SQL)Multiplies two expressions. Syntaxexpression * expression Argumentsexpression Result TypesThe data type that results from the implicit type promotion of the two arguments. For more information about implicit type promotion, see Type System. ExampleThe following Entity SQL query uses the * arithmetic operator to multiply two numbers. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice = @price1 * @price2 See also/ (Divide) (Entity SQL)Divides one number by another. Syntaxdividend / divisor Argumentsdividend divisor Result TypesThe data type that results from the implicit type promotion of the two arguments. For more information about implicit type promotion, see Type System. ExampleThe following Entity SQL query uses the / arithmetic operator to divide one number by another. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice = @price1 / @price2 See also(Modulo) (Entity SQL)Returns the remainder of one expression divided by another. Syntaxdividend % divisor Argumentsdividend divisor Result TypesEdm.Int32 ExampleThe following Entity SQL query uses the % arithmetic operator to return the remainder of one expression divided by another. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice = @price1 % @price2 See also&& (AND) (Entity SQL)Returns true if both expressions are true; otherwise, false or NULL. Syntaxboolean_expression AND boolean_expression or boolean_expression && boolean_expression Argumentsboolean_expression RemarksDouble ampersands (&&) have the same functionality as the AND operator. The following table shows possible input values and return types.
ExampleThe following Entity SQL query demonstrates how to use the AND operator. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
-- AND SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice > @price1 AND product.ListPrice < @price2 -- && SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice > @price1 && product.ListPrice < @price2 See also|| (OR) (Entity SQL)Combines two Boolean expressions. Syntaxboolean_expression OR boolean_expression or boolean_expression || boolean_expression Argumentsboolean_expression Return Valuetrue when either of the conditions is true; otherwise, false. RemarksOR is an Entity SQL logical operator. It is used to combine two conditions. When more than one logical operator is used in a statement, OR operators are evaluated after AND operators. However, you can change the order of evaluation by using parentheses. Double vertical bars (||) have the same functionality as the OR operator. The following table shows possible input values and return types.
ExampleThe following Entity SQL query uses the OR operator to combine two Boolean expressions. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
-- OR SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice = @price1 OR product.ListPrice = @price2 -- || SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice = @price1 || product.ListPrice = @price2 See also! (NOT) (Entity SQL)Negates a Boolean expression. SyntaxNOT boolean_expression or ! boolean_expression Argumentsboolean_expression RemarksThe exclamation point (!) has the same functionality as the NOT operator. ExampleThe following Entity SQL query uses the NOT operator to negates a Boolean expression. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
-- NOT SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice > @price1 AND NOT (product.ListPrice = @price2) -- ! SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice > @price1 AND ! (product.ListPrice = @price2) See also= (Equals) (Entity SQL)Compares the equality of two expressions. Syntaxexpression = expression or expression == expression Argumentsexpression Result Typestrue if the left expression is equal to the right expression; otherwise, false. RemarksThe == operator is equivalent to =. ExampleThe following Entity SQL query uses = comparison operator to compare the equality of two expressions. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice = @price See also> (Greater Than) (Entity SQL)Compares two expressions to determine whether the left expression has a value greater than the right expression. Syntaxexpression > expression Argumentsexpression Result Typestrue if the left expression has a value greater than the right expression; otherwise, false. ExampleThe following Entity SQL query uses > comparison operator to compare two expressions to determine whether the left expression has a value greater than the right expression. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice > @price See also>= (Greater Than or Equal To) (Entity SQL)Compares two expressions to determine whether the left expression has a value greater than or equal to the right expression. Syntaxexpression >= expression Argumentsexpression Result Typestrue if the left expression has a value greater than or equal to the right expression; otherwise, false. ExampleThe following Entity SQL query uses >= comparison operator to compare two expressions to determine whether the left expression has a value greater than or equal to the right expression. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice >= @price See also< (Less Than) (Entity SQL)Compares two expressions to determine whether the left expression has a value less than the right expression. Syntaxexpression < expression Argumentsexpression Result Typestrue if the left expression has a value less than the right expression; otherwise, false. ExampleThe following Entity SQL query uses < comparison operator to compare two expressions to determine whether the left expression has a value less than the right expression. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice < @price See also<= (Less Than or Equal To) (Entity SQL)Compares two expressions to determine whether the left expression has a value less than or equal to the right expression. Syntaxexpression <= expression Argumentsexpression Result Typestrue if the left expression has a value less than or equal to the right expression; otherwise, false. ExampleThe following Entity SQL query uses <= comparison operator to compare two expressions to determine whether the left expression has a value less than or equal to the right expression. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice <= @price See also!= (Not Equal To) (Entity SQL)Compares two expressions to determine whether the left expression is not equal to the right expression. The != (Not Equal To) operator is functionally equivalent to the <> operator. Syntaxexpression != expression or expression <> expression Argumentsexpression Result Typestrue if the left expression is not equal to the right expression; otherwise, false. ExampleThe following Entity SQL query uses the != operator to compare two expressions to determine whether the left expression is not equal to the right expression. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
-- != SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice != @price -- <> SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice <> @price See also. (Member Access) (Entity SQL)The dot operator (.) is the Entity SQL member access operator. You use the member access operator to yield the value of a property or field of an instance of structural conceptual model type. Syntaxexpression.identifier Argumentsexpression identifier RemarksThe dot (.) operator may be used to extract fields from a record, similar to extracting properties of a complex or entity type. For example, if n of type Name is a member of type Person, and p is an instance of type Person, then p.n is a legal member access expression that yields a value of type Name. select p.Name.FirstName from LOB.Person as p See also-- (Comment) (Entity SQL)Entity SQL queries can contain comments. Two dashes (--) start a comment line. Syntax-- text_of_comment Argumentstext_of_comment ExampleThe following Entity SQL query demonstrates how to use comments. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE product FROM AdventureWorksEntities.Products AS product -- add a comment here See alsoANYELEMENT (Entity SQL)Extracts an element from a multivalued collection. SyntaxANYELEMENT ( expression ) Argumentsexpression Return ValueA single element in the collection or an arbitrary element if the collection has more than one; if the collection is empty, returns null. If collection is a collection of type Collection<T>, then ANYELEMENT(collection) is a valid expression that yields an instance of type T. RemarksANYELEMENT extracts an arbitrary element from a multivalued collection. For example, the following example attempts to extract a singleton element from the set Customers. ANYELEMENT(Customers) ExampleThe following Entity SQL query uses the ANYELEMENT operator to extract an element from a multivalued collection. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
ANYELEMENT((SELECT VALUE product from AdventureWorksEntities.Products as product where product.ListPrice = @price)) See alsoBETWEEN (Entity SQL)Determines whether an expression results in a value in a specified range. The Entity SQL BETWEEN expression has the same functionality as the Transact-SQL BETWEEN expression. Syntaxexpression [ NOT ] BETWEEN begin_expression AND end_expression Argumentsexpression begin_expression end_expression NOT AND Return Valuetrue if expression is between the range indicated by begin_expression and end_expression; otherwise, false. null will be returned if expression is null or if begin_expression or end_expression is null. RemarksTo specify an exclusive range, use the greater than (>) and less than (<) operators instead of BETWEEN. ExampleThe following Entity SQL query uses BETWEEN operator to determine whether an expression results in a value in a specified range. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice BETWEEN @price1 AND @price2 See alsoCASE (Entity SQL)Evaluates a set of Boolean expressions to determine the result. SyntaxCASE WHEN Boolean_expression THEN result_expression [ ...n ] [ ELSE else_result_expression ] END Argumentsn THEN result_expression ELSE else_result_expression WHEN Boolean_expression Return ValueReturns the highest precedence type from the set of types in the result_expression and the optional else_result_expression. RemarksThe Entity SQL case expression resembles the Transact-SQL case expression. You use the case expression to make a series of conditional tests to determine which expression will yield the appropriate result. This form of the case expression applies to a series of one or more Boolean expressions to determine the correct resulting expression. The CASE function evaluates Boolean_expression for each WHEN clause in the order specified, and returns result_expression of the first Boolean_expression that evaluates to true. The remaining expressions are not evaluated. If no Boolean_expression evaluates to true, the Database Engine returns the else_result_expression if an ELSE clause is specified, or a null value if no ELSE clause is specified. A CASE statement cannot return a multiset. ExampleThe following Entity SQL query uses the CASE expression to evaluate a set of Boolean expressions in order to determine the result. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
CASE WHEN AVG({@score1,@score2,@score3}) < @total THEN TRUE ELSE FALSE END See alsoCAST (Entity SQL)Converts an expression of one data type to another. SyntaxCAST ( expression AS data_type ) Argumentsexpression data_type Return ValueReturns the same value as data_type. RemarksThe cast expression has similar semantics to the Transact-SQL CONVERT expression. The cast expression is used to convert a value of one type into a value of another type. CAST( e as T ) If e is of some type S, and S is convertible to T, then the above expression is a valid cast expression. T must be a primitive (scalar) type. Values for the precision and scale facets may optionally be provided when casting to Edm.Decimal. If not explicitly provided, the default values for precision and scale are 18 and 0, respectively. Specifically, the following overloads are supported for Decimal:
The use of a cast expression is considered an explicit conversion. Explicit conversions might truncate data or lose precision. Note CAST is only supported over primitive types and enumeration member types. ExampleThe following Entity SQL query uses the CAST operator to cast an expression of one data type to another. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE cast(p.ListPrice as Edm.Int32) FROM AdventureWorksEntities.Products as p order by p.ListPrice See alsoCOLLECTION (Entity SQL)The COLLECTION keyword is only used in the definition of an inline function. Collection functions are functions that operate on a collection of values and produce a scalar output. SyntaxCOLLECTION(type_definition) Argumentstype_definition RemarksFor more information about the COLLECTION keyword, see Type Definitions. ExampleThe following sample shows how to use the COLLECTION keyword to declare a collection of decimals as an argument for an inline query function. USING Microsoft.Samples.Entity Function MyAvg(dues Collection(Decimal)) AS ( Avg(select value due from dues as due where due > @price) ) SELECT TOP(10) contactID, MyAvg(GroupPartition(order.TotalDue)) FROM AdventureWorksEntities.SalesOrderHeaders AS order GROUP BY order.Contact.ContactID as contactID; See alsoCREATEREF (Entity SQL)Fabricates references to an entity in an entityset. SyntaxCreateRef(entityset_identifier, row_typed_expression) Argumentsentityset_identifier row_typed_expression Remarksrow_typed_expression must be structurally equivalent to the key type for the entity. That is, it must have the same number and types of fields in the same order as the entity keys. In the example below, Orders and BadOrders are both entitysets of type Order, and Id is assumed to be the single key property of Order. The example illustrates how we may produce a reference to an entity in BadOrders. Note that the reference may be dangling. That is, the reference may not actually identify a specific entity. In those cases, a DEREF operation on that reference returns a null. select CreateRef(LOB.BadOrders, row(o.Id)) from LOB.Orders as o ExampleThe following Entity SQL query uses the CREATEREF operator to fabricate references to an entity in an entity set. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE Key(CreateRef(AdventureWorksEntities.Products, row(p.ProductID))) FROM AdventureWorksEntities.Products as p See alsoDEREF (Entity SQL)Dereferences a reference value and produces the result of that dereference. SyntaxSELECT DEREF ( o.expression ) from Table as o; Argumentsexpression Return ValueThe value of the entity that is referenced. RemarksThe DEREF operator dereferences a reference value and produces the result of that dereference. For example, if r is a reference of type ref<T>, Deref(r) is an expression of type T that yields the entity referenced by r. If the reference value is null, or is dangling (that is, the target of the reference does not exist), the result of the DEREF operator is null. ExampleThe following Entity SQL query uses the DEREF operator to dereference a reference value and produce the result of that dereference. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE DEREF(REF(p)).Name FROM AdventureWorksEntities.Products as p See alsoEXCEPT (Entity SQL)Returns a collection of any distinct values from the query expression to the left of the EXCEPT operand that are not also returned from the query expression to the right of the EXCEPT operand. All expressions must be of the same type or of a common base or derived type as expression. Syntaxexpression EXCEPT expression Argumentsexpression Return ValueA collection of the same type or of a common base or derived type as expression. RemarksEXCEPT is one of the Entity SQL set operators. All Entity SQL set operators are evaluated from left to right. The following table shows the precedence of the Entity SQL set operators.
ExampleThe following Entity SQL query uses the EXCEPT operator to return a collection of any distinct values from two query expressions. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
(SELECT product from AdventureWorksEntities.Products as product WHERE product.ListPrice > @price1 ) except (select product from AdventureWorksEntities.Products as product WHERE product.ListPrice > @price2) See alsoEXISTS (Entity SQL)Determines if a collection is empty. Syntax[NOT] EXISTS ( expression ) Argumentsexpression NOT Return Valuetrue if the collection is not empty; otherwise, false. RemarksEXISTS is one of the Entity SQL set operators. All Entity SQL set operators are evaluated from left to right. For precedence information for the Entity SQL set operators, see EXCEPT. ExampleThe following Entity SQL query uses the EXISTS operator to determine whether the collection is empty. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE name from AdventureWorksEntities.Products AS name where exists(SELECT A from AdventureWorksEntities.Products as A WHERE A.ListPrice < @price1) See alsoFLATTEN (Entity SQL)Converts a collection of collections into a flattened collection. The new collection contains all the same elements as the old collection, but without a nested structure. SyntaxFLATTEN ( collection ) Argumentscollection RemarksFLATTEN is one of the Entity SQL set operators. All Entity SQL set operators are evaluated from left to right. See EXCEPT for precedence information for the Entity SQL set operators. ExampleThe following Entity SQL query uses the FLATTEN operator to convert a collection of collections into a flattened collection. To compile and run this query, follow these steps:
FLATTEN(SELECT VALUE c.SalesOrderHeaders From AdventureWorksEntities.Contacts as c) See alsoFROM (Entity SQL)Specifies the collection used in SELECT statements. SyntaxFROM expression [ ,...n ] as C Argumentsexpression RemarksA FROM clause is a comma-separated list of one or more FROM clause items. The FROM clause can be used to specify one or more sources for a SELECT statement. The simplest form of a FROM clause is a single query expression that identifies a collection and an alias used as the source in a SELECT statement, as illustrated in the following example: FROM C as c FROM Clause ItemsEach FROM clause item refers to a source collection in the Entity SQL query. Entity SQL supports the following classes of FROM clause items: simple FROM clause items, JOIN FROM clause items, and APPLY FROM clause items. Each of these FROM clause items is described in more detail in the following sections. Simple FROM Clause ItemThe simplest FROM clause item is a single expression that identifies a collection and an alias. The expression can simply be an entity set, or a subquery, or any other expression that is a collection type. The following is an example: LOB.Customers as c The alias specification is optional. An alternate specification of the above from clause item could be the following: LOB.Customers If no alias is specified, Entity SQL attempts to generate an alias based on the collection expression. JOIN FROM Clause ItemA JOIN FROM clause item represents a join between two FROM clause items. Entity SQL supports cross joins, inner joins, left and right outer joins, and full outer joins. All these joins are supported similar to the way that they are supported in Transact-SQL. As in Transact-SQL, the two FROM clause items involved in the JOIN must be independent. That is, they cannot be correlated. A CROSS APPLY or OUTER APPLY can be used for these cases. Cross JoinsA CROSS JOIN query expression produces the Cartesian product of the two collections, as illustrated in the following example: FROM C AS c CROSS JOIN D as d Inner JoinsAn INNER JOIN produces a constrained Cartesian product of the two collections, as illustrated in the following example: FROM C AS c [INNER] JOIN D AS d ON e The previous query expression processes a combination of every element of the collection on the left paired against every element of the collection on the right, where the ON condition is true. If no ON condition is specified, an INNER JOIN degenerates to a CROSS JOIN. Left Outer Joins and Right Outer JoinsAn OUTER JOIN query expression produces a constrained Cartesian product of the two collections, as illustrated in the following example: FROM C AS c LEFT OUTER JOIN D AS d ON e The previous query expression processes a combination of every element of the collection on the left paired against every element of the collection on the right, where the ON condition is true. If the ON condition is false, the expression still processes a single instance of the element on the left paired against the element on the right, with the value null. A RIGHT OUTER JOIN may be expressed in a similar manner. Full Outer JoinsAn explicit FULL OUTER JOIN produces a constrained Cartesian product of the two collections as illustrated in the following example: FROM C AS c FULL OUTER JOIN D AS d ON e The previous query expression processes a combination of every element of the collection on the left paired against every element of the collection on the right, where the ON condition is true. If the ON condition is false, the expression still processes one instance of the element on the left paired against the element on the right, with the value null. It also processes one instance of the element on the right paired against the element on the left, with the value null. Note To preserve compatibility with SQL-92, in Transact-SQL the OUTER keyword is optional. Therefore, LEFT JOIN, RIGHT JOIN, and FULL JOIN are synonyms for LEFT OUTER JOIN, RIGHT OUTER JOIN, and FULL OUTER JOIN. APPLY Clause ItemEntity SQL supports two kinds of APPLY: CROSS APPLY and OUTER APPLY. A CROSS APPLY produces a unique pairing of each element of the collection on the left with an element of the collection produced by evaluating the expression on the right. With a CROSS APPLY, the expression on the right is functionally dependent on the element on the left, as illustrated in the following associated collection example: SELECT c, f FROM C AS c CROSS APPLY c.Assoc AS f The behavior of CROSS APPLY is similar to the join list. If the expression on the right evaluates to an empty collection, the CROSS APPLY produces no pairings for that instance of the element on the left. An OUTER APPLY resembles a CROSS APPLY, except a pairing is still produced even when the expression on the right evaluates to an empty collection. The following is an example of an OUTER APPLY: SELECT c, f FROM C AS c OUTER APPLY c.Assoc AS f Note Unlike in Transact-SQL, there is no need for an explicit unnest step in Entity SQL. Note CROSS and OUTER APPLY operators were introduced in SQL Server 2005. In some cases, the query pipeline might produce Transact-SQL that contains CROSS APPLY and/or OUTER APPLY operators. Because some backend providers, including versions of SQL Server earlier than SQL Server 2005, do not support these operators, such queries cannot be executed on these backend providers. Some typical scenarios that might lead to the presence of CROSS APPLY and/or OUTER APPLY operators in the output query are the following: a correlated subquery with paging; AnyElement over a correlated subquery or over a collection produced by navigation; LINQ queries that use grouping methods that accept an element selector; a query in which a CROSS APPLY or an OUTER APPLY are explicitly specified; a query that has a DEREF construct over a REF construct. Multiple Collections in the FROM ClauseThe FROM clause can contain more than one collection separated by commas. In these cases, the collections are assumed to be joined together. Think of these as an n-way CROSS JOIN. In the following example, C and D are independent collections, but c.Names is dependent on C. FROM C AS c, D AS d, c.Names AS e The previous example is logically equivalent to the following example: FROM (C AS c JOIN D AS d) CROSS APPLY c.Names AS e Left CorrelationItems in the FROM clause can refer to items specified in earlier clauses. In the following example, C and D are independent collections, but c.Names is dependent on C: from C as c, D as d, c.Names as e This is logically equivalent to: from (C as c join D as d) cross apply c.Names as e SemanticsLogically, the collections in the FROM clause are assumed to be part of an n-way cross join (except in the case of a 1-way cross join). Aliases in the FROM clause are processed left to right, and are added to the current scope for later reference. The FROM clause is assumed to produce a multiset of rows. There will be one field for each item in the FROM clause that represents a single element from that collection item. The FROM clause logically produces a multiset of rows of type Row(c, d, e) where fields c, d, and e are assumed to be of the element type of C, D, and c.Names. Entity SQL introduces an alias for each simple FROM clause item in scope. For example, in the following FROM clause snippet, The names introduced into scope are c, d, and e. from (C as c join D as d) cross apply c.Names as e In Entity SQL (unlike Transact-SQL), the FROM clause only introduces the aliases into scope. Any references to columns (properties) of these collections must be qualified with the alias. Pulling Up Keys from Nested QueriesCertain types of queries that require pulling up keys from a nested query are not supported. For example, the following query is valid: select c.Orders from Customers as c However, the following query is not valid, because the nested query does not have any keys: select {1} from {2, 3} See alsoFUNCTION (Entity SQL)Defines a function in the scope of an Entity SQL query command. SyntaxFUNCTION function-name ( [ { parameter_name <type_definition> [ ,...n ] ] ) AS ( function_expression ) <type_definition>::= { data_type | COLLECTION ( <type_definition> ) | REF ( data_type ) | ROW ( row_expression ) } Argumentsfunction-name parameter-name function_expression data_type COLLECTION ( <type_definition> ) REF (data_type) ROW (row_expression) RemarksMultiple functions with the same name can be declared inline, as long as the function signatures are different. For more information, see Function Overload Resolution. An inline function can be called in an Entity SQL command only after it has been defined in that command. However, an inline function can be called inside another inline function either before or after the called function has been defined. In the following example, function A calls function B before function B is defined: Function A() as ('A calls B. ' + B()) Function B() as ('B was called.') A() For more information, see How to: Call a User-Defined Function. Functions can also be declared in the model itself. Functions declared in the model are executed in the same way as functions declared inline in the command. For more information, see User-Defined Functions. ExampleThe following Entity SQL command defines a function Products that takes an integer value to filter the returned products. USING Microsoft.Samples.Entity; FUNCTION Products(listPrice Int32) AS ( SELECT VALUE p FROM AdventureWorksEntities.Products AS p WHERE p.ListPrice >= listPrice ) select p from Products(@price) as p ExampleThe following Entity SQL command defines a function StringReturnsCollection that takes a collection of strings to filter the returned contacts. USING Microsoft.Samples.Entity; FUNCTION GetSpecificContacts(Ids Collection(Int32)) AS ( SELECT VALUE id FROM Ids AS id WHERE id < @price ) GetSpecificContacts(SELECT VALUE c.ContactID FROM AdventureWorksEntities.Contacts as c) See alsoGROUP BY (Entity SQL)Specifies groups into which objects returned by a query (SELECT) expression are to be placed. Syntax[ GROUP BY aliasedExpression [ ,...n ] ] ArgumentsaliasedExpression RemarksIf aggregate functions are included in the SELECT clause <select list>, GROUP BY calculates a summary value for each group. When GROUP BY is specified, either each property name in any nonaggregate expression in the select list should be included in the GROUP BY list, or the GROUP BY expression must exactly match the select list expression. Note If the ORDER BY clause is not specified, groups returned by the GROUP BY clause are not in any particular order. To specify a particular ordering of the data, we recommend that you always use the ORDER BY clause. When a GROUP BY clause is specified, either explicitly or implicitly (for example, by a HAVING clause in the query), the current scope is hidden, and a new scope is introduced. The SELECT clause, the HAVING clause, and the ORDER BY clause will no longer be able to refer to element names specified in the FROM clause. You can only refer to the grouping expressions themselves. To do this, you can assign new names (aliases) to each grouping expression. If no alias is specified for a grouping expression, Entity SQL tries to generate one by using the alias generation rules, as illustrated in the following example. SELECT g1, g2, ...gn FROM c as c1 GROUP BY e1 as g1, e2 as g2, ...en as gn Expressions in the GROUP BY clause cannot refer to names defined earlier in the same GROUP BY clause. In addition to grouping names, you can also specify aggregates in the SELECT clause, HAVING clause, and the ORDER BY clause. An aggregate contains an expression that is evaluated for each element of the group. The aggregate operator reduces the values of all these expressions (usually, but not always, into a single value). The aggregate expression can make references to the original element names visible in the parent scope, or to any of the new names introduced by the GROUP BY clause itself. Although the aggregates appear in the SELECT clause, HAVING clause, and ORDER BY clause, they are actually evaluated under the same scope as the grouping expressions, as illustrated in the following example. SELECT name, sum(o.Price * o.Quantity) as total FROM orderLines as o GROUP BY o.Product as name This query uses the GROUP BY clause to produce a report of the cost of all products ordered, broken down by product. It gives the name name to the product as part of the grouping expression, and then references that name in the SELECT list. It also specifies the aggregate sum in the SELECT list that internally references the price and quantity of the order line. Each GROUP By key expression must have at least one reference to the input scope: SELECT FROM Persons as P GROUP BY Q + P -- GOOD GROUP BY Q -- BAD GROUP BY 1 -- BAD, a constant is not allowed For an example of using GROUP BY, see HAVING. ExampleThe following Entity SQL query uses the GROUP BY operator to specify groups into which objects are returned by a query. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE name FROM AdventureWorksEntities.Products as P GROUP BY P.Name HAVING MAX(P.ListPrice) > @price See alsoGROUPPARTITION (Entity SQL)Returns a collection of argument values that are projected off the current group partition to which the aggregate is related. The GroupPartition aggregate is a group-based aggregate and has no collection-based form. SyntaxGROUPPARTITION( [ALL|DISTINCT] expression ) Argumentsexpression RemarksThe following query produces a list of products and a collection of order line quantities per each product: select p, GroupPartition(ol.Quantity) from LOB.OrderLines as ol group by ol.Product as p The following two queries are semantically equal: select p, Sum(GroupPartition(ol.Quantity)) from LOB.OrderLines as ol group by ol.Product as p select p, Sum(ol.Quantity) from LOB.OrderLines as ol group by ol.Product as p The GROUPPARTITION operator can be used in conjunction with user-defined aggregate functions. GROUPPARTITION is a special aggregate operator that holds a reference to the grouped input set. This reference can be used anywhere in the query where GROUP BY is in scope. For example, select p, GroupPartition(ol.Quantity) from LOB.OrderLines as ol group by ol.Product as p With a regular GROUP BY, the results of the grouping are hidden. You can only use the results in an aggregate function. In order to see the results of the grouping, you have to correlate the results of the grouping and the input set by using a subquery. The following two queries are equivalent: select p, (select q from GroupPartition(ol.Quantity) as q) from LOB.OrderLines as ol group by ol.Product as p select p, (select ol.Quantity as q from LOB.OrderLines as ol2 where ol2.Product = p) from LOB.OrderLines as ol group by ol.Product as p As seen from the example, the GROUPPARTITION aggregate operator makes it easier to get a reference to the input set after the grouping. The GROUPPARTITION operator can specify any Entity SQL expression in the operator input when you use the expression parameter. For instance all of the following input expressions to the group partition are valid: select groupkey, GroupPartition(b) from {1,2,3} as a inner join {4,5,6} as b on true group by a as groupkey select groupkey, GroupPartition(1) from {1,2,3} as a inner join {4,5,6} as b on true group by a as groupkey select groupkey, GroupPartition(a + b) from {1,2,3} as a inner join {4,5,6} as b on true group by a as groupkey select groupkey, GroupPartition({a + b}) from {1,2,3} as a inner join {4,5,6} as b on true group by a as groupkey select groupkey, GroupPartition({42}) from {1,2,3} as a inner join {4,5,6} as b on true group by a as groupkey select groupkey, GroupPartition(b > a) from {1,2,3} as a inner join {4,5,6} as b on true group by a as groupkey ExampleThe following example shows how to use the GROUPPARTITION clause with the GROUP BY clause. The GROUP BY clause groups SalesOrderHeader entities by their Contact. The GROUPPARTITION clause then projects the TotalDue property for each group, resulting in a collection of decimals. USING Microsoft.Samples.Entity Function MyAvg(dues Collection(Decimal)) AS ( Avg(select value due from dues as due where due > @price) ) SELECT TOP(10) contactID, MyAvg(GroupPartition(order.TotalDue)) FROM AdventureWorksEntities.SalesOrderHeaders AS order GROUP BY order.Contact.ContactID as contactID; HAVING (Entity SQL)Specifies a search condition for a group or an aggregate. Syntax[ HAVING search_condition ] Argumentssearch_condition RemarksThe HAVING clause is used to specify an additional filtering condition on the result of a grouping. If no GROUP BY clause is specified in the query expression, an implicit single-set group is assumed. Note HAVING can be used only with the SELECT statement. When GROUP BY is not used, HAVING behaves like a WHERE clause. The HAVING clause works like the WHERE clause except that it is applied after the GROUP BY operation. This means that the HAVING clause can only make references to grouping aliases and aggregates, as illustrated in the following example. SELECT Name, SUM(o.Price * o.Quantity) AS Total FROM orderLines AS o GROUP BY o.Product AS Name HAVING SUM(o.Quantity) > 1 The previous restricts the groups to only those that include more than one product. ExampleThe following Entity SQL query uses the HAVING and GROUP BY operators to specify a search condition for a group or an aggregate. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE name FROM AdventureWorksEntities.Products as P GROUP BY P.Name HAVING MAX(P.ListPrice) > @price See alsoKEY (Entity SQL)Extracts the key of a reference or of an entity expression. SyntaxKEY(createref_expression) RemarksAn entity key contains the key values in the correct order of the specified entity or entity reference. Because multiple entity sets can be based on the same type, the same key might appear in each entity set. To get a unique reference, use REF. The return type of the KEY operator is a row type that includes one field for each key of the entity, in the same order. In the following example, the key operator is passed a reference to the BadOrder entity, and returns the key portion of that reference. In this case, a record type with exactly one field corresponding to the Id property. select Key( CreateRef(LOB.BadOrders, row(o.Id)) ) from LOB.Orders as o ExampleThe following Entity SQL query uses the KEY operator to extract the key portion of an expression with type reference. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE Key(CreateRef(AdventureWorksEntities.Products, row(p.ProductID))) FROM AdventureWorksEntities.Products as p See alsoIN (Entity SQL)Determines whether a value matches any value in a collection. Syntaxvalue [ NOT ] IN expression Argumentsvalue [ NOT ] expression Return Valuetrue if the value is found in the collection; null if the value is null or the collection is null; otherwise, false. Using NOT IN negates the results of IN. ExampleThe following Entity SQL query uses the IN operator to determine whether a value matches any value in a collection. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE product FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice IN {125, 300} See alsoINTERSECT (Entity SQL)Returns a collection of any distinct values that are returned by both the query expressions on the left and right sides of the INTERSECT operand. All expressions must be of the same type or of a common base or derived type as expression. Syntaxexpression INTERSECT expression Argumentsexpression Return ValueA collection of the same type or of a common base or derived type as expression. RemarksINTERSECT is one of the Entity SQL set operators. All Entity SQL set operators are evaluated from left to right. For precedence information for the Entity SQL set operators, see EXCEPT. ExampleThe following Entity SQL query uses the INTERSECT operator to return a collection of any distinct values that are returned by both the query expressions on the left and right sides of the INTERSECT operand. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
(SELECT product from AdventureWorksEntities.Products as product where product.ListPrice > @price1 ) intersect (select product from AdventureWorksEntities.Products as product where product.ListPrice > @price2) See alsoISNULL (Entity SQL)Determines if a query expression is null. Syntaxexpression IS [ NOT ] NULL Argumentsexpression NOT Return Valuetrue if expression returns null; otherwise, false. RemarksUse IS NULL to determine if the element of an outer join is null: select c from LOB.Customers as c left outer join LOB.Orders as o on c.ID = o.CustomerID where o is not null and o.OrderQuantity = @x Use IS NULL to determine if a member has an actual value: select c from LOB.Customer as c where c.DOB is not null The following table shows the behavior of IS NULL over some patterns. All exceptions are thrown from the client side before the provider gets invoked:
ExampleThe following Entity SQL query uses the IS NOT NULL operator to determine if a query expression is not null. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE product FROM AdventureWorksEntities.Products AS product WHERE product.Color IS NOT NULL See alsoISOF (Entity SQL)Determines whether the type of an expression is of the specified type or one of its subtypes. Syntaxexpression IS [ NOT ] OF ( [ ONLY ] type ) Argumentsexpression NOT ONLY type Return Valuetrue if expression is of type T and T is either a base type, or a derived type of type; null if expression is null at runtime; otherwise, false. RemarksThe expressions expression IS NOT OF (type) and expression IS NOT OF (ONLY type) are syntactically equivalent to NOT (expression IS OF (type)) and NOT (expression IS OF (ONLY type)), respectively. The following table shows the behavior of IS OF operator over some typical- and corner patterns. All exceptions are thrown from the client side before the provider gets invoked:
ExampleThe following Entity SQL query uses the IS OF operator to determine the type of a query expression, and then uses the TREAT operator to convert an object of the type Course to a collection of objects of the type OnsiteCourse. The query is based on the School Model. SELECT VALUE TREAT (course as SchoolModel.OnsiteCourse) FROM SchoolEntities.Courses as course WHERE course IS OF( SchoolModel.OnsiteCourse) See alsoLIKE (Entity SQL)Determines whether a specific character String matches a specified pattern. Syntaxmatch [NOT] LIKE pattern [ESCAPE escape] Argumentsmatch pattern escape NOT Return Valuetrue if the string matches the pattern; otherwise, false. RemarksEntity SQL expressions that use the LIKE operator are evaluated in much the same way as expressions that use equality as the filter criteria. However, Entity SQL expressions that use the LIKE operator can include both literals and wildcard characters. The following table describes the syntax of the pattern string.
Note The Entity SQL LIKE operator and ESCAPE clause cannot be applied to System.DateTime or System.Guid values. LIKE supports ASCII pattern matching and Unicode pattern matching. When all parameters are ASCII characters, ASCII pattern matching is performed. If one or more of the arguments are Unicode, all arguments are converted to Unicode and Unicode pattern matching is performed. When you use Unicode with LIKE, trailing blanks are significant; however, for non-Unicode, trailing blanks are not significant. The pattern string syntax of Entity SQL is the same as that of Transact-SQL. A pattern can include regular characters and wildcard characters. During pattern matching, regular characters must exactly match the characters specified in the character string. However, wildcard characters can be matched with arbitrary fragments of the character string. When it is used with wildcard characters, the LIKE operator is more flexible than the = and != string comparison operators. Note You may use provider-specific extensions if you target a specific provider. However, such constructs may be treated differently by other providers, for example. SqlServer supports [first-last] and [^first-last] patterns where the former matches exactly one character between first and last, and the latter matches exactly one character that is not between first and last. EscapeBy using the ESCAPE clause, you can search for character strings that include one or more of the special wildcard characters described in the table in the previous section. For example, assume several documents include the literal "100%" in the title and you want to search for all of those documents. Because the percent (%) character is a wildcard character, you must escape it using the Entity SQL ESCAPE clause to successfully execute the search. The following is an example of this filter. "title like '%100!%%' escape '!'" In this search expression, the percent wildcard character (%) immediately following the exclamation point character (!) is treated as a literal, instead of as a wildcard character. You can use any character as an escape character except for the Entity SQL wildcard characters and the square bracket ([ ]) characters. In the previous example, the exclamation point (!) character is the escape character. ExampleThe following two Entity SQL queries use the LIKE and ESCAPE operators to determine whether a specific character string matches a specified pattern. The first query searches for the Name that starts with the characters Down_. This query uses the ESCAPE option because the underscore (_) is a wildcard character. Without specifying the ESCAPE option, the query would search for any Name values that start with the word Down followed by any single character other than the underscore character. The queries are based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
-- LIKE and ESCAPE -- If an AdventureWorksEntities.Products contained a Name -- with the value 'Down_Tube', the following query would find that -- value. Select value P.Name FROM AdventureWorksEntities.Products as P where P.Name LIKE 'DownA_%' ESCAPE 'A' -- LIKE Select value P.Name FROM AdventureWorksEntities.Products as P where P.Name like 'BB%' See alsoLIMIT (Entity SQL)Physical paging can be performed by using LIMIT sub-clause in ORDER BY clause. LIMIT can not be used separately from ORDER BY clause. Syntax[ LIMIT n ] Argumentsn If a LIMIT expression sub-clause is present in an ORDER BY clause, the query will be sorted according to the sort specification and the resulting number of rows will be restricted by the LIMIT expression. For instance, LIMIT 5 will restrict the result set to 5 instances or rows. LIMIT is functionally equivalent to TOP with the exception that LIMIT requires ORDER BY clause to be present. SKIP and LIMIT can be used independently along with ORDER BY clause. Note An Entity Sql query will be considered invalid if TOP modifier and SKIP sub-clause is present in the same query expression. The query should be rewritten by changing TOP expression to LIMIT expression. ExampleThe following Entity SQL query uses the ORDER BY operator with LIMIT to specify the sort order used on objects returned in a SELECT statement. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE p FROM AdventureWorksEntities.Products AS p order by p.ListPrice LIMIT(@limit) See alsoMULTISET (Entity SQL)Creates an instance of a multiset from a list of values. All the values in the MULTISET constructor must be of a compatible type T. Empty multiset constructors are not allowed. SyntaxMULTISET ( expression [{, expression }] ) or { expression [{, expression }] } Argumentsexpression Return ValueA collection of type MULTISET<T>. RemarksEntity SQL provides three kinds of constructors: row constructors, object constructors, and multiset (or collection) constructors. For more information, see Constructing Types. The multiset constructor creates an instance of a multiset from a list of values. All the values in the constructor must be of a compatible type. For example, the following expression creates a multiset of integers. MULTISET(1, 2, 3) {1, 2, 3} Note Nested multiset literals are only supported when a wrapping multiset has a single multiset element; for example, {{1, 2, 3}}. When the wrapping multiset has multiple multiset elements (for example, {{1, 2}, {3, 4}}), nested multiset literals are not supported. ExampleThe following Entity SQL query uses the MULTISET operator to create an instance of a multiset from a list of values. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE product FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice IN MultiSet (@price1, @price2) See alsoNamed Type Constructor (Entity SQL)Used to create instances of conceptual model nominal types such as Entity or Complex types. Syntax[{identifier. }] identifier( [expression [{, expression }]] ) Argumentsidentifier expression Return ValueInstances of named complex types and entity types. RemarksThe following examples show how to construct nominal and complex types: The expression below creates an instance of a Person type: Person("abc", 12) The expression below creates an instance of a complex type: MyModel.ZipCode(‘98118’, ‘4567’) The expression below creates an instance of a nested complex type: MyModel.AddressInfo('My street address', 'Seattle', 'WA', MyModel.ZipCode('98118', '4567')) The expression below creates an instance of an entity with a nested complex type: MyModel.Person("Bill", MyModel.AddressInfo('My street address', 'Seattle', 'WA', MyModel.ZipCode('98118', '4567'))) The following example shows how to initialize a property of a complex type to null:MyModel.ZipCode(‘98118’, null) ExampleThe following Entity SQL query uses the named type constructor to create an instance of a conceptual model type. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE AdventureWorksModel.SalesOrderDetail (o.SalesOrderID, o.SalesOrderDetailID, o.CarrierTrackingNumber, o.OrderQty, o.ProductID, o.SpecialOfferID, o.UnitPrice, o.UnitPriceDiscount, o.LineTotal, o.rowguid, o.ModifiedDate) FROM AdventureWorksEntities.SalesOrderDetails AS o See alsoNAVIGATE (Entity SQL)Navigates over the relationship established between entities. Syntaxnavigate(instance-expression, [relationship-type], [to-end [, from-end] ]) Argumentsinstance-expression An instance of an entity. relationship-type The type name of the relationship, from the conceptual schema definition language (CSDL) file. The relationship-type is qualified as <namespace>.<relationship type name>. to The end of the relationship. from The beginning of the relationship. Return ValueIf the cardinality of the to end is 1, the return value will be Ref<T>. If the cardinality of the to end is n, the return value will be Collection<Ref<T>>. RemarksRelationships are first-class constructs in the Entity Data Model (EDM). Relationships can be established between two or more entity types, and users can navigate over the relationship from one end (entity) to another. from and to are conditionally optional when there is no ambiguity in name resolution within the relationship. NAVIGATE is valid in O and C space. The general form of a navigation construct is the following: navigate(instance-expression, relationship-type, [ to-end [, from-end ] ] ) For example: Select o.Id, navigate(o, OrderCustomer, Customer, Order) From LOB.Orders as o Where OrderCustomer is the relationship, and Customer and Order are the to-end (customer) and from-end (order) of the relationship. If OrderCustomer was a n:1 relationship, then the result type of the navigate expression is Ref<Customer>. The simpler form of this expression is the following: Select o.Id, navigate(o, OrderCustomer) From LOB.Orders as o Similarly, in a query of the following form, The navigate expression would produce a Collection<Ref<Order>>. Select c.Id, navigate(c, OrderCustomer, Order, Customer) From LOB.Customers as c The instance-expression must be an entity/ref type. ExampleThe following Entity SQL query uses the NAVIGATE operator to navigate over the relationship established between Address and SalesOrderHeader entity types. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT address.AddressID, (SELECT VALUE DEREF(soh) FROM NAVIGATE(address, AdventureWorksModel.FK_SalesOrderHeader_Address_BillToAddressID) AS soh) FROM AdventureWorksEntities.Addresses AS address See alsoOFTYPE (Entity SQL)Returns a collection of objects from a query expression that is of a specific type. SyntaxOFTYPE ( expression, [ONLY] test_type ) Argumentsexpression test_type Return ValueA collection of objects that are of type test_type, or a base type or derived type of test_type. If ONLY is specified, only instances of the test_type or an empty collection will be returned. RemarksAn OFTYPE expression specifies a type expression that is issued to perform a type test against each element of a collection. The OFTYPE expression produces a new collection of the specified type containing only those elements that were either equivalent to that type or a sub-type of it. An OFTYPE expression is an abbreviation of the following query expression: select value treat(t as T) from ts as t where t is of (T) Given that a Manager is a subtype of Employee, the following expression produces a collection of only managers from a collection of employees: OfType(employees, NamespaceName.Manager) It is also possible to up cast a collection using the type filter: OfType(executives, NamespaceName.Manager) Since all executives are managers, the resulting collection still contains all the original executives, though the collection is now typed as a collection of managers. The following table shows the behavior of the OFTYPE operator over some patterns. All exceptions are thrown from the client side before the provider is invoked:
ExampleThe following Entity SQL query uses the OFTYPE operator to return a collection of OnsiteCourse objects from a collection of Course objects. The query is based on the School Model. SELECT onsiteCourse.Location FROM OFTYPE(SchoolEntities.Courses, SchoolModel.OnsiteCourse) AS onsiteCourse See alsoORDER BY (Entity SQL)Specifies the sort order used on objects returned in a SELECT statement. Syntax[ ORDER BY { order_by_expression [SKIP n] [LIMIT n] [ COLLATE collation_name ] [ ASC | DESC ] } [ ,…n ] ] Argumentsorder_by_expression COLLATE {collation_name} ASC DESC LIMIT n SKIP n RemarksThe ORDER BY clause is logically applied to the result of the SELECT clause. The ORDER BY clause can reference items in the select list by using their aliases. The ORDER BY clause can also reference other variables that are currently in-scope. However, if the SELECT clause has been specified with a DISTINCT modifier, the ORDER BY clause can only reference aliases from the SELECT clause. SELECT c AS c1 FROM cs AS c ORDER BY c1.e1, c.e2 Each expression in the ORDER BY clause must evaluate to some type that can be compared for ordered inequality (less than or greater than, and so on). These types are generally scalar primitives such as numbers, strings, and dates. RowTypes of comparable types are also order comparable. If your code iterates over an ordered set, other than for a top-level projection, the output is not guaranteed to have its order preserved. -- In the following sample, order is guaranteed to be preserved: SELECT C1.FirstName, C1.LastName FROM AdventureWorks.Contact as C1 ORDER BY C1.LastName -- In the following query ordering of the nested query is ignored. SELECT C2.FirstName, C2.LastName FROM (SELECT C1.FirstName, C1.LastName FROM AdventureWorks.Contact as C1 ORDER BY C1.LastName) as C2 To have an ordered UNION, UNION ALL, EXCEPT, or INTERSECT operation, use the following pattern: SELECT ... FROM ( UNION/EXCEPT/INTERSECT operation ) ORDER BY ... Restricted keywordsThe following keywords must be enclosed in quotation marks when used in an ORDER BY clause:
Ordering Nested QueriesIn the Entity Framework, a nested expression can be placed anywhere in the query; the order of a nested query is not preserved. -- The following query will order the results by the last name. SELECT C1.FirstName, C1.LastName FROM AdventureWorks.Contact as C1 ORDER BY C1.LastName -- In the following query, ordering of the nested query is ignored. SELECT C2.FirstName, C2.LastName FROM (SELECT C1.FirstName, C1.LastName FROM AdventureWorks.Contact as C1 ORDER BY C1.LastName) as C2 ExampleThe following Entity SQL query uses the ORDER BY operator to specify the sort order used on objects returned in a SELECT statement. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE p FROM AdventureWorksEntities.Products AS p order by p.ListPrice See alsoOVERLAPS (Entity SQL)Determines whether two collections have common elements. Syntaxexpression OVERLAPS expression Argumentsexpression Return Valuetrue if the two collections have common elements; otherwise, false. RemarksOVERLAPS provides functionally equivalent to the following: EXISTS ( expression INTERSECT expression ) OVERLAPS is one of the Entity SQL set operators. All Entity SQL set operators are evaluated from left to right. For precedence information for the Entity SQL set operators, see EXCEPT. ExampleThe following Entity SQL query uses the OVERLAPS operator to determines whether two collections have a common value. The query is based on the AdventureWorks Sales Model. To compile and run this, follow these steps:
SELECT value P from AdventureWorksEntities.Products as P WHERE ((select P from AdventureWorksEntities.Products as P WHERE P.ListPrice > @price1) overlaps (select P from AdventureWorksEntities.Products as P WHERE P.ListPrice < @price2)) See alsoREF (Entity SQL)Returns a reference to an entity instance. SyntaxREF( expression ) Argumentsexpression Return ValueA reference to the specified entity instance. RemarksAn entity reference consists of the entity key and an entity set name. Because different entity sets can be based on the same entity type, a particular entity key can appear in multiple entity sets. However, an entity reference is always unique. If the input expression represents a persisted entity, a reference to this entity will be returned. If the input expression is not a persisted entity, a null reference will be returned. If the property extraction operator (.) is used to access a property of an entity, the reference is automatically dereferenced. ExampleThe following Entity SQL query uses the REF operator to return the reference for an input entity argument. The same query dereferences the reference because we are using a property extraction operation (.) to access a property of the Product entity. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE REF(p).Name FROM AdventureWorksEntities.Products as p See alsoROW (Entity SQL)Constructs anonymous, structurally typed records from one or more values. SyntaxROW ( expression [ AS alias ] [,...] ) Argumentsexpression alias Return ValueA row type. RemarksYou use row constructors in the Entity SQL to construct anonymous, structurally typed records from one or more values. The result type of a row constructor is a row type whose field types correspond to the types of the values that were used to construct the row. For example, the following expression constructs a value of type Record(a int, b string, c int). ROW(1 AS a, "abc" AS b, a+34 AS c) If you do not provide an alias for an expression in a row constructor, the Entity Framework will try to generate one. For more information, see the "Aliasing Rules" section of the Identifiers topic. The following rules apply to expression aliasing in a row constructor:
For more information about query constructors, see Constructing Types. ExampleThe following Entity SQL query uses the ROW operator to construct anonymous, structurally typed records. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE ROW (product.ProductID as ProductID, product.Name as ProductName) FROM AdventureWorksEntities.Products AS product See alsoSELECT (Entity SQL)Specifies the elements returned by a query. SyntaxSELECT [ ALL | DISTINCT ] [ topSubclause ] aliasedExpr [{ , aliasedExpr }] FROM fromClause [ WHERE whereClause ] [ GROUP BY groupByClause [ HAVING havingClause ] ] [ ORDER BY orderByClause ] or SELECT VALUE [ ALL | DISTINCT ] [ topSubclause ] expr FROM fromClause [ WHERE whereClause ] [ GROUP BY groupByClause [ HAVING havingClause ] ] [ ORDER BY orderByClause ArgumentsALL DISTINCT VALUE topSubclause The LIMIT parameter of the ORDER BY operator also lets you select the first n items in the result set. aliasedExpr expr as identifier | expr expr RemarksThe SELECT clause is evaluated after the FROM, GROUP BY, and HAVING clauses have been evaluated. The SELECT clause can only refer to items currently in-scope (from the FROM clause, or from outer scopes). If a GROUP BY clause has been specified, the SELECT clause is only allowed to reference the aliases for the GROUP BY keys. Referring to the FROM clause items is only permitted in aggregate functions. The list of one or more query expressions following the SELECT keyword is known as the select list, or more formally as the projection. The most general form of projection is a single query expression. If you select a member member1 from a collection collection1, you will produce a new collection of all the member1 values for each object in collection1, as illustrated in the following example. SELECT collection1.member1 FROM collection1 For example, if customers is a collection of type Customer that has a property Name that is of type string, selecting Name from customers will yield a collection of strings, as illustrated in the following example. SELECT customers.Name FROM customers AS c It is also possible to use JOIN syntax (FULL, INNER, LEFT, OUTER, ON, and RIGHT). ON is required for inner joins and is nto allowed for cross joins. Row and Value Select ClausesEntity SQL supports two variants of the SELECT clause. The first variant, row select, is identified by the SELECT keyword, and can be used to specify one or more values that should be projected out. Because a row wrapper is implicitly added around the values returned, the result of the query expression is always a multiset of rows. Each query expression in a row select must specify an alias. If no alias is specified,Entity SQL attempts to generate an alias by using the alias generation rules. The other variant of the SELECT clause, value select, is identified by the SELECT VALUE keyword. It allows only one value to be specified, and does not add a row wrapper. A row select is always expressible in terms of VALUE SELECT, as illustrated in the following example. SELECT 1 AS a, "abc" AS b FROM C SELECT VALUE ROW(1 AS a, "abc" AS b) FROM C All and Distinct ModifiersBoth variants of SELECT in Entity SQL allow the specification of an ALL or DISTINCT modifier. If the DISTINCT modifier is specified, duplicates are eliminated from the collection produced by the query expression (up to and including the SELECT clause). If the ALL modifier is specified, no duplicate elimination is performed; ALL is the default. Differences from Transact-SQLUnlike Transact-SQL, Entity SQL does not support use of the * argument in the SELECT clause. Instead, Entity SQL allows queries to project out entire records by referencing the collection aliases from the FROM clause, as illustrated in the following example. SELECT * FROM T1, T2 The previous Transact-SQL query expression is expressed in Entity SQL in the following way. SELECT a1, a2 FROM T1 AS a1, T2 AS a2 ExampleThe following Entity SQL query uses the SELECT operator to specify the elements to be returned by a query. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SELECT VALUE product FROM AdventureWorksEntities.Products AS product where product.ListPrice < @price See alsoSET (Entity SQL)The SET expression is used to convert a collection of objects into a set by yielding a new collection with all duplicate elements removed. SyntaxSET ( expression ) Argumentsexpression RemarksThe set expression SET(c) is logically equivalent to the following select statement: SELECT VALUE DISTINCT c FROM c SET is one of the Entity SQL set operators. All Entity SQL set operators are evaluated from left to right. See EXCEPT for precedence information for the Entity SQL set operators. ExampleThe following Entity SQL query uses the SET expression to convert a collection of objects into a set. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
SET(SELECT VALUE P.Name FROM AdventureWorksEntities.Products AS P) See alsoSKIP (Entity SQL)You can perform physical paging by using the SKIP sub-clause in the ORDER BY clause. SKIP cannot be used separately from the ORDER BY clause. Syntax[ SKIP n ] Argumentsn RemarksIf a SKIP expression sub-clause is present in an ORDER BY clause, the results will be sorted according the sort specification and the result set will include rows starting from the next row immediately after the SKIP expression. For example, SKIP 5 will skip the first five rows and return from the sixth row forward. Note An Entity SQL query is invalid if both the TOP modifier and the SKIP sub-clause are present in the same query expression. The query should be rewritten by changing the TOP expression to the LIMIT expression. Note In SQL Server 2000, using SKIP with ORDER BY on non-key columns might return incorrect results. More than the specified number of rows might be skipped if the non-key column has duplicate data in it. This is due to how SKIP is translated for SQL Server 2000. For example, in the following code more than five rows might be skipped if E.NonKeyColumn has duplicate values: SELECT [E] FROM Container.EntitySet AS [E] ORDER BY [E].[NonKeyColumn] DESC SKIP 5L The Entity SQL query in How to: Page Through Query Results uses the ORDER BY operator with SKIP to specify the sort order used on objects returned in a SELECT statement. See alsoTHEN (Entity SQL)The result of a WHEN clause when it evaluates to true. SyntaxWHEN when_expression THEN then_expression Argumentswhen_expression then_expression RemarksIf when_expression evaluates to the value true, the result is the corresponding then-expression. If none of the WHEN conditions are satisfied, the else-expression is evaluated. However, if there is no else-expression, the result is null. For an example, see CASE. ExampleThe following Entity SQL query uses the CASE expression to evaluate a set of Boolean expressions. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
CASE WHEN AVG({@score1,@score2,@score3}) < @total THEN TRUE ELSE FALSE END See alsoTOP (Entity SQL)The SELECT clause can have an optional TOP sub-clause following the optional ALL/DISTINCT modifier. The TOP sub-clause specifies that only the first set of rows will be returned from the query result. Syntax[ TOP (n) ] Argumentsn The numeric expression that specifies the number of rows to be returned. n could be a single numeric literal or a single parameter. RemarksThe TOP expression must be either a single numeric literal or a single parameter. If a constant literal is used, the literal type must be implicitly promotable to Edm.Int64 (byte, int16, int32 or int64 or any provider type that maps to a type that is promotable to Edm.Int64) and its value must be greater than or equal to zero. Otherwise an exception will be raised. If a parameter is used as an expression, the parameter type must also be implicitly promotable to Edm.Int64, but there will be no validation of the actual parameter value during compilation because the parameter values are late bounded. The following is an example of constant TOP expression: select distinct top(10) c.a1, c.a2 from T as a The following is an example of parameterized TOP expression: select distinct top(@topParam) c.a1, c.a2 from T as a TOP is non-deterministic unless the query is sorted. If you require a deterministic result, use the SKIP and LIMIT sub-clauses in the ORDER BY clause. The TOP and SKIP/LIMIT are mutually exclusive. ExampleThe following Entity SQL query uses the TOP to specify the top one row to be returned from the query result. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
See alsoTREAT (Entity SQL)Treats an object of a particular base type as an object of the specified derived type. SyntaxTREAT ( expression as type) Argumentsexpression Note The type of the specified expression must be a subtype of the specified data type, or the data type must be a subtype of the type of expression. type Note The specified expression must be a subtype of the specified data type, or the data type must be a subtype of the expression. Return ValueA value of the specified data type. RemarksTREAT is used to perform upcasting between related classes. For example, if Employee derives from Person and p is of type Person, TREAT(p AS NamespaceName.Employee) upcasts a generic Person instance to Employee; that is, it allows you to treat p as Employee. TREAT is used in inheritance scenarios where you can do a query like the following: SELECT TREAT(p AS NamespaceName.Employee) FROM ContainerName.Person AS p WHERE p IS OF (NamespaceName.Employee) This query upcasts Person entities to the Employee type. If the value of p is not actually of type Employee, the expression yields the value null. Note The specified expression Employee must be a subtype of the specified data type Person, or the data type must be a subtype of the expression. Otherwise, the expression will result in a compile-time error. The following table shows the behavior of treat over some typical patterns and some less common patterns. All exceptions are thrown from the client side before the provider gets invoked:
ExampleThe following Entity SQL query uses the TREAT operator to convert an object of the type Course to a collection of objects of the type OnsiteCourse. The query is based on the School Model. SELECT VALUE TREAT (course as SchoolModel.OnsiteCourse) FROM SchoolEntities.Courses as course WHERE course IS OF( SchoolModel.OnsiteCourse) See alsoUNION (Entity SQL)Combines the results of two or more queries into a single collection. Syntaxexpression UNION [ ALL ] expression Argumentsexpression UNION ALL Return ValueA collection of the same type or of a common base or derived type as expression. RemarksUNION is one of the Entity SQL set operators. All Entity SQL set operators are evaluated from left to right. For precedence information for the Entity SQL set operators, see EXCEPT. ExampleThe following Entity SQL query uses the UNION ALL operator to combine the results of two queries into a single collection. The query is based on the AdventureWorks Sales Model. To compile and run this query, follow these steps:
(SELECT VALUE P from AdventureWorksEntities.Products as P WHERE P.Name LIKE 'C%') Union All ( SELECT VALUE A from AdventureWorksEntities.Products as A WHERE A.ListPrice > @price) See alsoUSING (Entity SQL)Specifies namespaces used in a query expression. SyntaxUSING [ alias = ] namespace Argumentsalias namespace ExampleThe following Entity SQL query uses the USING operator to specify namespaces used in a query expression. To compile and run this query, follow these steps:
using SqlServer; RAND() See alsoWHERE (Entity SQL)The WHERE clause is applied directly after the FROM clause. Syntax[ WHERE expression ] Argumentsexpression RemarksThe WHERE clause has the same semantics as described for Transact-SQL. It restricts the objects produced by the query expression by limiting the elements of the source collections to those that pass the condition. select c from cs as c where e The expression e must have the type Boolean. The WHERE clause is applied directly after the FROM clause and before any grouping, ordering, or projection takes place. All element names defined in the FROM clause are visible to the expression of the WHERE clause. See alsoCanonical FunctionsThis section discusses canonical functions that are supported by all data providers, and can be used by all querying technologies. Canonical functions cannot be extended by a provider. These canonical functions will be translated to the corresponding data source functionality for the provider. This allows for function invocations expressed in a common form across data sources. Because these canonical functions are independent of data sources, argument and return types of canonical functions are defined in terms of types in the conceptual model. However, some data sources might not support all types in the conceptual model. When canonical functions are used in an Entity SQL query, the appropriate function will be called at the data source. All canonical functions have both null-input behavior and error conditions explicitly specified. Store providers should comply with that behavior, but Entity Framework does not enforce this behavior. For LINQ scenarios, queries against the Entity Framework involve mapping CLR methods to methods in the underlying data source. The CLR methods map to canonical functions, so that a specific set of methods will correctly map, regardless of the data source. Canonical Functions NamespaceThe namespace for canonical function is System.Data.Metadata.Edm. The System.Data.Metadata.Edm namespace is automatically included in all queries. However, if another namespace is imported that contains a function with the same name as a canonical function (in the System.Data.Metadata.Edm namespace), you must specify the namespace. In This SectionAggregate Canonical Functions Math Canonical Functions String Canonical Functions Date and Time Canonical Functions Bitwise Canonical Functions Spatial Functions Other Canonical Functions See also
Aggregate Canonical FunctionsAggregates are expressions that reduce a series of input values into, for example, a single value. Aggregates are normally used in conjunction with the GROUP BY clause of the SELECT expression, and there are constraints on where they can be used. Aggregate Entity SQL canonical functionsThe following are the aggregate Entity SQL canonical functions. Avg(expression)Returns the average of the non-null values. Arguments An Int32, Int64, Double, and Decimal. Return Value The type of expression, or null if all input values are null values. Example queryString = @"SELECT VALUE AVG(p.ListPrice) FROM AdventureWorksEntities.Products as p"; SELECT VALUE AVG(p.ListPrice) FROM AdventureWorksEntities.Products AS p BigCount(expression)Returns the size of the aggregate including null and duplicate values. Arguments Any type. Return Value An Int64. Example queryString = @"SELECT VALUE BigCount(p.ProductID) FROM AdventureWorksEntities.Products as p"; SELECT VALUE BigCount(p.ProductID) FROM AdventureWorksEntities.Products AS p Count(expression)Returns the size of the aggregate including null and duplicate values. Arguments Any type. Return Value An Int32. Example queryString = @"SELECT VALUE Count(p.ProductID) FROM AdventureWorksEntities.Products as p"; SELECT VALUE Count(p.ProductID) FROM AdventureWorksEntities.Products AS p Max(expression)Returns the maximum of the non-null values. Arguments A Byte, Int16, Int32, Int64, Byte, Single, Double, Decimal, DateTime, DateTimeOffset, Time, String, Binary. Return Value The type of expression, or null if all input values are null values. Example queryString = @"SELECT VALUE MAX(p.ListPrice) FROM AdventureWorksEntities.Products as p"; SELECT VALUE MAX(p.ListPrice) FROM AdventureWorksEntities.Products AS p Min(expression)Returns the minimum of the non-null values. Arguments A Byte, Int16, Int32, Int64, Byte, Single, Double, Decimal, DateTime, DateTimeOffset, Time, String, Binary. Return Value The type of expression, or null if all input values are null values. Example queryString = @"SELECT VALUE MIN(p.ListPrice) FROM AdventureWorksEntities.Products as p"; SELECT VALUE MIN(p.ListPrice) FROM AdventureWorksEntities.Products AS p StDev(expression)Returns the standard deviation of the non-null values. Arguments An Int32, Int64, Double, Decimal. Return Value A Double. Null, if all input values are null values. Example queryString = @"SELECT VALUE StDev(product.ListPrice) FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice > @price"; SELECT VALUE StDev(product.ListPrice) FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice > @price StDevP(expression)Returns the standard deviation for the population of all values. Arguments An Int32, Int64, Double, Decimal. Return Value A Double, or null if all input values are null values. Example queryString = @"SELECT VALUE StDevP(product.ListPrice) FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice > @price"; SELECT VALUE StDevP(product.ListPrice) FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice > @price Sum(expression)Returns the sum of the non-null values. Arguments An Int32, Int64, Double, Decimal. Return Value A Double, or null if all input values are null values. Example queryString = @"SELECT VALUE Sum(p.ListPrice) FROM AdventureWorksEntities.Products as p"; SELECT VALUE Sum(p.ListPrice) FROM AdventureWorksEntities.Products AS p Var(expression)Returns the variance of all non-null values. Arguments An Int32, Int64, Double, Decimal. Return Value A Double, or null if all input values are null values. Example queryString = @"SELECT VALUE Var(product.ListPrice) FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice > @price"; SELECT VALUE Var(product.ListPrice) FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice > @price VarP(expression)Returns the variance for the population of all non-null values. Arguments An Int32, Int64, Double, Decimal. Return Value A Double, or null if all input values are null values. Example queryString = @"SELECT VALUE VarP(product.ListPrice) FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice > @price"; SELECT VALUE VarP(product.ListPrice) FROM AdventureWorksEntities.Products AS product WHERE product.ListPrice > @price Equivalent functionality is available in the Microsoft SQL Client Managed Provider. For more information, see SqlClient for Entity Framework Functions. Collection-based aggregatesCollection-based aggregates (collection functions) operate on collections and return a value. For example if ORDERS is a collection of all orders, you can calculate the earliest ship date with the following expression: min(select value o.ShipDate from LOB.Orders as o) Expressions inside collection-based aggregates are evaluated within the current ambient name-resolution scope. Group-based aggregatesGroup-based aggregates are calculated over a group as defined by the GROUP BY clause. For each group in the result, a separate aggregate is calculated by using the elements in each group as input to the aggregate calculation. When a group-by clause is used in a select expression, only grouping expression names, aggregates, or constant expressions can be present in the projection or order-by clause. The following example calculates the average quantity ordered for each product: select p, avg(ol.Quantity) from LOB.OrderLines as ol group by ol.Product as p It's possible to have a group-based aggregate without an explicit group-by clause in the SELECT expression. In this case, all elements are treated as a single group. This is equivalent of specifying a grouping based on a constant. Take, for example, the following expression: select avg(ol.Quantity) from LOB.OrderLines as ol This is equivalent to the following: select avg(ol.Quantity) from LOB.OrderLines as ol group by 1 Expressions inside the group-based aggregate are evaluated within the name-resolution scope that would be visible to the WHERE clause expression. As in Transact-SQL, group-based aggregates can also specify an ALL or DISTINCT modifier. If the DISTINCT modifier is specified, duplicates are eliminated from the aggregate input collection, before the aggregate is computed. If the ALL modifier is specified (or if no modifier is specified), no duplicate elimination is performed. See alsoMath Canonical FunctionsEntity SQL includes the following math canonical functions: Abs(value)Returns the absolute value of value. Arguments An Int16, Int32, Int64, Byte, Single, Double, and Decimal. Return Value The type of value. Example Abs(-2) Ceiling(value)Returns the smallest integer that is not less than value. Arguments A Single, Double, and Decimal. Return Value The type of value. Example SELECT VALUE product FROM AdventureWorksEntities.Products AS product WHERE CEILING(product.ListPrice) == FLOOR(product.ListPrice) SELECT VALUE product FROM AdventureWorksEntities.Products AS product WHERE CEILING(product.ListPrice) == FLOOR(product.ListPrice) Floor(value)Returns the largest integer that is not greater than value. Arguments A Single, Double, and Decimal. Return Value The type of value. Example SELECT VALUE product FROM AdventureWorksEntities.Products AS product WHERE FLOOR(product.ListPrice) == CEILING(product.ListPrice) SELECT VALUE product FROM AdventureWorksEntities.Products AS product WHERE FLOOR(product.ListPrice) == CEILING(product.ListPrice) Power(value, exponent)Returns the result of the specified value to the specified exponent. Arguments
Return Value The type of value. Example Power(748.58,2) Round(value)Returns the integer portion of value, rounded to the nearest integer. Arguments A Single, Double, and Decimal. Return Value The type of value. Example Round(748.58) Round(value, digits)Returns the value, rounded to the nearest specified digits. Arguments
Return Value The type of value. Example Round(748.58,1) Truncate(value, digits)Returns the value, truncated to the nearest specified digits. Arguments
Return Value The type of value. Example Truncate(748.58,1) These functions will return null if given null input. Equivalent functionality is available in the Microsoft SQL Client Managed Provider. For more information, see SqlClient for Entity Framework Functions. See alsoString Canonical FunctionsEntity SQL includes string canonical functions. RemarksThe following table shows the string Entity SQL canonical functions.
These functions will return null if given null input. Equivalent functionality is available in the Microsoft SQL Client Managed Provider. For more information, see SqlClient for Entity Framework Functions. See alsoDate and Time Canonical FunctionsEntity SQL includes date and time canonical functions. RemarksThe following table shows the date and time Entity SQL canonical functions. datetime is a DateTime value.
These functions will return null if given null input. Equivalent functionality is available in the Microsoft SQL Client Managed Provider. For more information, see SqlClient for Entity Framework Functions. See alsoBitwise Canonical FunctionsEntity SQL includes bitwise canonical functions. RemarksThe following table shows the bitwise Entity SQL canonical functions. These functions will return Null if Null input is provided. The return type of the functions is the same as the argument type(s). Arguments must be of the same type, if the function takes more than one argument. To perform bitwise operations across different types, you need to cast to the same type explicitly.
See alsoSpatial FunctionsThere is no literal format for spatial types. However, you can use canonical Entity Framework functions that you call using strings in Well-Known Text format. For example, the following function call creates a geometry point: GeometryFromText('POINT (43 -73)') The SpatialEdmFunctions methods have all spatial canonical Entity Framework methods. Click on a method of interest to see what parameters should be passed to a function. Other Canonical FunctionsEntity SQL includes canonical functions not classified as bitwise, aggregate, math, date/time, or string. The following table shows the other Entity SQL canonical functions.
See also
Source/Reference
©sideway ID: 201000021 Last Updated: 10/21/2020 Revision: 0 Ref: ![]() References
![]() Latest Updated Links
![]() ![]() ![]() ![]() ![]() |
![]() Home 5 Business Management HBR 3 Information Recreation Hobbies 8 Culture Chinese 1097 English 339 Travel 18 Reference 79 Computer Hardware 254 Software Application 213 Digitization 37 Latex 52 Manim 205 KB 1 Numeric 19 Programming Web 289 Unicode 504 HTML 66 CSS 65 SVG 46 ASP.NET 270 OS 431 DeskTop 7 Python 72 Knowledge Mathematics Formulas 8 Set 1 Logic 1 Algebra 84 Number Theory 206 Trigonometry 31 Geometry 34 Calculus 67 Engineering Tables 8 Mechanical Rigid Bodies Statics 92 Dynamics 37 Fluid 5 Control Acoustics 19 Natural Sciences Matter 1 Electric 27 Biology 1 |
Copyright © 2000-2025 Sideway . All rights reserved Disclaimers last modified on 06 September 2019