diff --git a/docs/csharp/programming-guide/concepts/async/task-asynchronous-programming-model.md b/docs/csharp/programming-guide/concepts/async/task-asynchronous-programming-model.md index f692b6d242ad6..3fceca27135e4 100644 --- a/docs/csharp/programming-guide/concepts/async/task-asynchronous-programming-model.md +++ b/docs/csharp/programming-guide/concepts/async/task-asynchronous-programming-model.md @@ -4,326 +4,336 @@ ms.date: 05/22/2017 ms.assetid: 9bcf896a-5826-4189-8c1a-3e35fa08243a --- # Task asynchronous programming model -You can avoid performance bottlenecks and enhance the overall responsiveness of your application by using asynchronous programming. However, traditional techniques for writing asynchronous applications can be complicated, making them difficult to write, debug, and maintain. - -[C# 5](../../../whats-new/csharp-version-history.md#c-version-50) introduced a simplified approach, async programming, that leverages asynchronous support in the .NET Framework 4.5 and higher, .NET Core, and the Windows Runtime. The compiler does the difficult work that the developer used to do, and your application retains a logical structure that resembles synchronous code. As a result, you get all the advantages of asynchronous programming with a fraction of the effort. - -This topic provides an overview of when and how to use async programming and includes links to support topics that contain details and examples. - -## Async improves responsiveness - Asynchrony is essential for activities that are potentially blocking, such as web access. Access to a web resource sometimes is slow or delayed. If such an activity is blocked in a synchronous process, the entire application must wait. In an asynchronous process, the application can continue with other work that doesn't depend on the web resource until the potentially blocking task finishes. - - The following table shows typical areas where asynchronous programming improves responsiveness. The listed APIs from .NET and the Windows Runtime contain methods that support async programming. - + +You can avoid performance bottlenecks and enhance the overall responsiveness of your application by using asynchronous programming. However, traditional techniques for writing asynchronous applications can be complicated, making them difficult to write, debug, and maintain. + +[C# 5](../../../whats-new/csharp-version-history.md#c-version-50) introduced a simplified approach, async programming, that leverages asynchronous support in the .NET Framework 4.5 and higher, .NET Core, and the Windows Runtime. The compiler does the difficult work that the developer used to do, and your application retains a logical structure that resembles synchronous code. As a result, you get all the advantages of asynchronous programming with a fraction of the effort. + +This topic provides an overview of when and how to use async programming and includes links to support topics that contain details and examples. + +## Async improves responsiveness + +Asynchrony is essential for activities that are potentially blocking, such as web access. Access to a web resource sometimes is slow or delayed. If such an activity is blocked in a synchronous process, the entire application must wait. In an asynchronous process, the application can continue with other work that doesn't depend on the web resource until the potentially blocking task finishes. + +The following table shows typical areas where asynchronous programming improves responsiveness. The listed APIs from .NET and the Windows Runtime contain methods that support async programming. + | Application area | .NET types with async methods | Windows Runtime types with async methods | |---------------------|-----------------------------------|-------------------------------------------| |Web access||| -|Working with files|, , || -|Working with images||, , | -|WCF programming|[Synchronous and Asynchronous Operations](../../../../framework/wcf/synchronous-and-asynchronous-operations.md)|| - -Asynchrony proves especially valuable for applications that access the UI thread because all UI-related activity usually shares one thread. If any process is blocked in a synchronous application, all are blocked. Your application stops responding, and you might conclude that it has failed when instead it's just waiting. - - When you use asynchronous methods, the application continues to respond to the UI. You can resize or minimize a window, for example, or you can close the application if you don't want to wait for it to finish. - - The async-based approach adds the equivalent of an automatic transmission to the list of options that you can choose from when designing asynchronous operations. That is, you get all the benefits of traditional asynchronous programming but with much less effort from the developer. - -## Async methods are easier to write - The [async](../../../../csharp/language-reference/keywords/async.md) and [await](../../../../csharp/language-reference/keywords/await.md) keywords in C# are the heart of async programming. By using those two keywords, you can use resources in the .NET Framework, .NET Core, or the Windows Runtime to create an asynchronous method almost as easily as you create a synchronous method. Asynchronous methods that you define by using the `async` keyword are referred to as *async methods*. - - The following example shows an async method. Almost everything in the code should look completely familiar to you. - - You can find a complete Windows Presentation Foundation (WPF) example file at the end of this topic, and you can download the sample from [Async Sample: Example from "Asynchronous Programming with Async and Await"](https://code.msdn.microsoft.com/Async-Sample-Example-from-9b9f505c). - -```csharp -async Task AccessTheWebAsync() -{ - // You need to add a reference to System.Net.Http to declare client. - using (HttpClient client = new HttpClient()) - { - Task getStringTask = client.GetStringAsync("https://docs.microsoft.com"); - - DoIndependentWork(); - - string urlContents = await getStringTask; - - return urlContents.Length; - } -} -``` - - You can learn several practices from the preceding sample. start with the method signature. It includes the `async` modifier. The return type is `Task` (See "Return Types" section for more options). The method name ends in `Async`. In the body of the method, `GetStringAsync` returns a `Task`. That means that when you `await` the task you'll get a `string` (`urlContents`). Before awaiting the task, you can do work that doesn't rely on the `string` from `GetStringAsync`. - - Pay close attention to the `await` operator. It suspends `AccessTheWebAsync`; - -- `AccessTheWebAsync` can't continue until `getStringTask` is complete. -- Meanwhile, control returns to the caller of `AccessTheWebAsync`. -- Control resumes here when `getStringTask` is complete. -- The `await` operator then retrieves the `string` result from `getStringTask`. - - The return statement specifies an integer result. Any methods that are awaiting `AccessTheWebAsync` retrieve the length value. - - If `AccessTheWebAsync` doesn't have any work that it can do between calling `GetStringAsync` and awaiting its completion, you can simplify your code by calling and awaiting in the following single statement. - -```csharp -string urlContents = await client.GetStringAsync("https://docs.microsoft.com"); -``` - -The following characteristics summarize what makes the previous example an async method. - -- The method signature includes an `async` modifier. - -- The name of an async method, by convention, ends with an "Async" suffix. - -- The return type is one of the following types: - - - if your method has a return statement in which the operand has type `TResult`. - - - if your method has no return statement or has a return statement with no operand. - - - `void` if you're writing an async event handler. - - - Any other type that has a `GetAwaiter` method (starting with C# 7.0). - - For more information, see the [Return Types and Parameters](#BKMK_ReturnTypesandParameters) section. - -- The method usually includes at least one `await` expression, which marks a point where the method can't continue until the awaited asynchronous operation is complete. In the meantime, the method is suspended, and control returns to the method's caller. The next section of this topic illustrates what happens at the suspension point. - - In async methods, you use the provided keywords and types to indicate what you want to do, and the compiler does the rest, including keeping track of what must happen when control returns to an await point in a suspended method. Some routine processes, such as loops and exception handling, can be difficult to handle in traditional asynchronous code. In an async method, you write these elements much as you would in a synchronous solution, and the problem is solved. - - For more information about asynchrony in previous versions of the .NET Framework, see [TPL and Traditional .NET Framework Asynchronous Programming](../../../../standard/parallel-programming/tpl-and-traditional-async-programming.md). - -## What happens in an async method - The most important thing to understand in asynchronous programming is how the control flow moves from method to method. The following diagram leads you through the process. - - ![Trace an async program](./media/task-asynchronous-programming-model/navigation-trace-async-program.png "NavigationTrace") - - The numbers in the diagram correspond to the following steps, initiated when the user clicks the "start" button. - -1. An event handler calls and awaits the `AccessTheWebAsync` async method. - -2. `AccessTheWebAsync` creates an instance and calls the asynchronous method to download the contents of a website as a string. - -3. Something happens in `GetStringAsync` that suspends its progress. Perhaps it must wait for a website to download or some other blocking activity. To avoid blocking resources, `GetStringAsync` yields control to its caller, `AccessTheWebAsync`. - - `GetStringAsync` returns a , where `TResult` is a string, and `AccessTheWebAsync` assigns the task to the `getStringTask` variable. The task represents the ongoing process for the call to `GetStringAsync`, with a commitment to produce an actual string value when the work is complete. - -4. Because `getStringTask` hasn't been awaited yet, `AccessTheWebAsync` can continue with other work that doesn't depend on the final result from `GetStringAsync`. That work is represented by a call to the synchronous method `DoIndependentWork`. - -5. `DoIndependentWork` is a synchronous method that does its work and returns to its caller. - -6. `AccessTheWebAsync` has run out of work that it can do without a result from `getStringTask`. `AccessTheWebAsync` next wants to calculate and return the length of the downloaded string, but the method can't calculate that value until the method has the string. - - Therefore, `AccessTheWebAsync` uses an await operator to suspend its progress and to yield control to the method that called `AccessTheWebAsync`. `AccessTheWebAsync` returns a `Task` to the caller. The task represents a promise to produce an integer result that's the length of the downloaded string. - +|Working with files|, , || +|Working with images||, , | +|WCF programming|[Synchronous and Asynchronous Operations](../../../../framework/wcf/synchronous-and-asynchronous-operations.md)|| + +Asynchrony proves especially valuable for applications that access the UI thread because all UI-related activity usually shares one thread. If any process is blocked in a synchronous application, all are blocked. Your application stops responding, and you might conclude that it has failed when instead it's just waiting. + +When you use asynchronous methods, the application continues to respond to the UI. You can resize or minimize a window, for example, or you can close the application if you don't want to wait for it to finish. + +The async-based approach adds the equivalent of an automatic transmission to the list of options that you can choose from when designing asynchronous operations. That is, you get all the benefits of traditional asynchronous programming but with much less effort from the developer. + +## Async methods are easier to write + +The [async](../../../../csharp/language-reference/keywords/async.md) and [await](../../../../csharp/language-reference/keywords/await.md) keywords in C# are the heart of async programming. By using those two keywords, you can use resources in the .NET Framework, .NET Core, or the Windows Runtime to create an asynchronous method almost as easily as you create a synchronous method. Asynchronous methods that you define by using the `async` keyword are referred to as *async methods*. + +The following example shows an async method. Almost everything in the code should look completely familiar to you. + +You can find a complete Windows Presentation Foundation (WPF) example file at the end of this topic, and you can download the sample from [Async Sample: Example from "Asynchronous Programming with Async and Await"](https://code.msdn.microsoft.com/Async-Sample-Example-from-9b9f505c). + +```csharp +async Task AccessTheWebAsync() +{ + // You need to add a reference to System.Net.Http to declare client. + using (HttpClient client = new HttpClient()) + { + Task getStringTask = client.GetStringAsync("https://docs.microsoft.com"); + + DoIndependentWork(); + + string urlContents = await getStringTask; + + return urlContents.Length; + } +} +``` + +You can learn several practices from the preceding sample. start with the method signature. It includes the `async` modifier. The return type is `Task` (See "Return Types" section for more options). The method name ends in `Async`. In the body of the method, `GetStringAsync` returns a `Task`. That means that when you `await` the task you'll get a `string` (`urlContents`). Before awaiting the task, you can do work that doesn't rely on the `string` from `GetStringAsync`. + +Pay close attention to the `await` operator. It suspends `AccessTheWebAsync`; + +- `AccessTheWebAsync` can't continue until `getStringTask` is complete. +- Meanwhile, control returns to the caller of `AccessTheWebAsync`. +- Control resumes here when `getStringTask` is complete. +- The `await` operator then retrieves the `string` result from `getStringTask`. + +The return statement specifies an integer result. Any methods that are awaiting `AccessTheWebAsync` retrieve the length value. + +If `AccessTheWebAsync` doesn't have any work that it can do between calling `GetStringAsync` and awaiting its completion, you can simplify your code by calling and awaiting in the following single statement. + +```csharp +string urlContents = await client.GetStringAsync("https://docs.microsoft.com"); +``` + +The following characteristics summarize what makes the previous example an async method. + +- The method signature includes an `async` modifier. + +- The name of an async method, by convention, ends with an "Async" suffix. + +- The return type is one of the following types: + + - if your method has a return statement in which the operand has type `TResult`. + + - if your method has no return statement or has a return statement with no operand. + + - `void` if you're writing an async event handler. + + - Any other type that has a `GetAwaiter` method (starting with C# 7.0). + + For more information, see the [Return Types and Parameters](#BKMK_ReturnTypesandParameters) section. + +- The method usually includes at least one `await` expression, which marks a point where the method can't continue until the awaited asynchronous operation is complete. In the meantime, the method is suspended, and control returns to the method's caller. The next section of this topic illustrates what happens at the suspension point. + +In async methods, you use the provided keywords and types to indicate what you want to do, and the compiler does the rest, including keeping track of what must happen when control returns to an await point in a suspended method. Some routine processes, such as loops and exception handling, can be difficult to handle in traditional asynchronous code. In an async method, you write these elements much as you would in a synchronous solution, and the problem is solved. + +For more information about asynchrony in previous versions of the .NET Framework, see [TPL and Traditional .NET Framework Asynchronous Programming](../../../../standard/parallel-programming/tpl-and-traditional-async-programming.md). + +## What happens in an async method + +The most important thing to understand in asynchronous programming is how the control flow moves from method to method. The following diagram leads you through the process. + +![Trace an async program](./media/task-asynchronous-programming-model/navigation-trace-async-program.png "NavigationTrace") + +The numbers in the diagram correspond to the following steps, initiated when the user clicks the "start" button. + +1. An event handler calls and awaits the `AccessTheWebAsync` async method. + +2. `AccessTheWebAsync` creates an instance and calls the asynchronous method to download the contents of a website as a string. + +3. Something happens in `GetStringAsync` that suspends its progress. Perhaps it must wait for a website to download or some other blocking activity. To avoid blocking resources, `GetStringAsync` yields control to its caller, `AccessTheWebAsync`. + + `GetStringAsync` returns a , where `TResult` is a string, and `AccessTheWebAsync` assigns the task to the `getStringTask` variable. The task represents the ongoing process for the call to `GetStringAsync`, with a commitment to produce an actual string value when the work is complete. + +4. Because `getStringTask` hasn't been awaited yet, `AccessTheWebAsync` can continue with other work that doesn't depend on the final result from `GetStringAsync`. That work is represented by a call to the synchronous method `DoIndependentWork`. + +5. `DoIndependentWork` is a synchronous method that does its work and returns to its caller. + +6. `AccessTheWebAsync` has run out of work that it can do without a result from `getStringTask`. `AccessTheWebAsync` next wants to calculate and return the length of the downloaded string, but the method can't calculate that value until the method has the string. + + Therefore, `AccessTheWebAsync` uses an await operator to suspend its progress and to yield control to the method that called `AccessTheWebAsync`. `AccessTheWebAsync` returns a `Task` to the caller. The task represents a promise to produce an integer result that's the length of the downloaded string. + > [!NOTE] - > If `GetStringAsync` (and therefore `getStringTask`) completes before `AccessTheWebAsync` awaits it, control remains in `AccessTheWebAsync`. The expense of suspending and then returning to `AccessTheWebAsync` would be wasted if the called asynchronous process (`getStringTask`) has already completed and `AccessTheWebSync` doesn't have to wait for the final result. - - Inside the caller (the event handler in this example), the processing pattern continues. The caller might do other work that doesn't depend on the result from `AccessTheWebAsync` before awaiting that result, or the caller might await immediately. The event handler is waiting for `AccessTheWebAsync`, and `AccessTheWebAsync` is waiting for `GetStringAsync`. - -7. `GetStringAsync` completes and produces a string result. The string result isn't returned by the call to `GetStringAsync` in the way that you might expect. (Remember that the method already returned a task in step 3.) Instead, the string result is stored in the task that represents the completion of the method, `getStringTask`. The await operator retrieves the result from `getStringTask`. The assignment statement assigns the retrieved result to `urlContents`. - -8. When `AccessTheWebAsync` has the string result, the method can calculate the length of the string. Then the work of `AccessTheWebAsync` is also complete, and the waiting event handler can resume. In the full example at the end of the topic, you can confirm that the event handler retrieves and prints the value of the length result. -If you are new to asynchronous programming, take a minute to consider the difference between synchronous and asynchronous behavior. A synchronous method returns when its work is complete (step 5), but an async method returns a task value when its work is suspended (steps 3 and 6). When the async method eventually completes its work, the task is marked as completed and the result, if any, is stored in the task. - -For more information about control flow, see [Control Flow in Async Programs (C#)](../../../../csharp/programming-guide/concepts/async/control-flow-in-async-programs.md). - -## API async methods - You might be wondering where to find methods such as `GetStringAsync` that support async programming. The .NET Framework 4.5 or higher and .NET Core contain many members that work with `async` and `await`. You can recognize them by the "Async" suffix that’s appended to the member name, and by their return type of or . For example, the `System.IO.Stream` class contains methods such as , , and alongside the synchronous methods , , and . - - The Windows Runtime also contains many methods that you can use with `async` and `await` in Windows apps. For more information, see [Threading and async programming](/windows/uwp/threading-async/) for UWP development, and [Asynchronous programming (Windows Store apps)](https://docs.microsoft.com/previous-versions/windows/apps/hh464924(v=win.10)) and [Quickstart: Calling asynchronous APIs in C# or Visual Basic](https://docs.microsoft.com/previous-versions/windows/apps/hh452713(v=win.10)) if you use earlier versions of the Windows Runtime. - -## Threads -Async methods are intended to be non-blocking operations. An `await` expression in an async method doesn’t block the current thread while the awaited task is running. Instead, the expression signs up the rest of the method as a continuation and returns control to the caller of the async method. - -The `async` and `await` keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active. You can use to move CPU-bound work to a background thread, but a background thread doesn't help with a process that's just waiting for results to become available. - -The async-based approach to asynchronous programming is preferable to existing approaches in almost every case. In particular, this approach is better than the class for I/O-bound operations because the code is simpler and you don't have to guard against race conditions. In combination with the method, async programming is better than for CPU-bound operations because async programming separates the coordination details of running your code from the work that `Task.Run` transfers to the threadpool. - -## async and await - If you specify that a method is an async method by using the [async](../../../../csharp/language-reference/keywords/async.md) modifier, you enable the following two capabilities. - -- The marked async method can use [await](../../../../csharp/language-reference/keywords/await.md) to designate suspension points. The `await` operator tells the compiler that the async method can't continue past that point until the awaited asynchronous process is complete. In the meantime, control returns to the caller of the async method. - - The suspension of an async method at an `await` expression doesn't constitute an exit from the method, and `finally` blocks don’t run. - -- The marked async method can itself be awaited by methods that call it. - -An async method typically contains one or more occurrences of an `await` operator, but the absence of `await` expressions doesn’t cause a compiler error. If an async method doesn’t use an `await` operator to mark a suspension point, the method executes as a synchronous method does, despite the `async` modifier. The compiler issues a warning for such methods. - - `async` and `await` are contextual keywords. For more information and examples, see the following topics: - -- [async](../../../../csharp/language-reference/keywords/async.md) - -- [await](../../../../csharp/language-reference/keywords/await.md) - -## Return types and parameters -An async method typically returns a or a . Inside an async method, an `await` operator is applied to a task that's returned from a call to another async method. - -You specify as the return type if the method contains a [`return`](../../../../csharp/language-reference/keywords/return.md) statement that specifies an operand of type `TResult`. - -You use as the return type if the method has no return statement or has a return statement that doesn't return an operand. + > If `GetStringAsync` (and therefore `getStringTask`) completes before `AccessTheWebAsync` awaits it, control remains in `AccessTheWebAsync`. The expense of suspending and then returning to `AccessTheWebAsync` would be wasted if the called asynchronous process (`getStringTask`) has already completed and `AccessTheWebSync` doesn't have to wait for the final result. + + Inside the caller (the event handler in this example), the processing pattern continues. The caller might do other work that doesn't depend on the result from `AccessTheWebAsync` before awaiting that result, or the caller might await immediately. The event handler is waiting for `AccessTheWebAsync`, and `AccessTheWebAsync` is waiting for `GetStringAsync`. + +7. `GetStringAsync` completes and produces a string result. The string result isn't returned by the call to `GetStringAsync` in the way that you might expect. (Remember that the method already returned a task in step 3.) Instead, the string result is stored in the task that represents the completion of the method, `getStringTask`. The await operator retrieves the result from `getStringTask`. The assignment statement assigns the retrieved result to `urlContents`. + +8. When `AccessTheWebAsync` has the string result, the method can calculate the length of the string. Then the work of `AccessTheWebAsync` is also complete, and the waiting event handler can resume. In the full example at the end of the topic, you can confirm that the event handler retrieves and prints the value of the length result. +If you are new to asynchronous programming, take a minute to consider the difference between synchronous and asynchronous behavior. A synchronous method returns when its work is complete (step 5), but an async method returns a task value when its work is suspended (steps 3 and 6). When the async method eventually completes its work, the task is marked as completed and the result, if any, is stored in the task. + +For more information about control flow, see [Control Flow in Async Programs (C#)](../../../../csharp/programming-guide/concepts/async/control-flow-in-async-programs.md). + +## API async methods + +You might be wondering where to find methods such as `GetStringAsync` that support async programming. The .NET Framework 4.5 or higher and .NET Core contain many members that work with `async` and `await`. You can recognize them by the "Async" suffix that’s appended to the member name, and by their return type of or . For example, the `System.IO.Stream` class contains methods such as , , and alongside the synchronous methods , , and . + +The Windows Runtime also contains many methods that you can use with `async` and `await` in Windows apps. For more information, see [Threading and async programming](/windows/uwp/threading-async/) for UWP development, and [Asynchronous programming (Windows Store apps)](https://docs.microsoft.com/previous-versions/windows/apps/hh464924(v=win.10)) and [Quickstart: Calling asynchronous APIs in C# or Visual Basic](https://docs.microsoft.com/previous-versions/windows/apps/hh452713(v=win.10)) if you use earlier versions of the Windows Runtime. + +## Threads + +Async methods are intended to be non-blocking operations. An `await` expression in an async method doesn’t block the current thread while the awaited task is running. Instead, the expression signs up the rest of the method as a continuation and returns control to the caller of the async method. + +The `async` and `await` keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active. You can use to move CPU-bound work to a background thread, but a background thread doesn't help with a process that's just waiting for results to become available. + +The async-based approach to asynchronous programming is preferable to existing approaches in almost every case. In particular, this approach is better than the class for I/O-bound operations because the code is simpler and you don't have to guard against race conditions. In combination with the method, async programming is better than for CPU-bound operations because async programming separates the coordination details of running your code from the work that `Task.Run` transfers to the threadpool. + +## async and await + +If you specify that a method is an async method by using the [async](../../../../csharp/language-reference/keywords/async.md) modifier, you enable the following two capabilities. + +- The marked async method can use [await](../../../../csharp/language-reference/keywords/await.md) to designate suspension points. The `await` operator tells the compiler that the async method can't continue past that point until the awaited asynchronous process is complete. In the meantime, control returns to the caller of the async method. + + The suspension of an async method at an `await` expression doesn't constitute an exit from the method, and `finally` blocks don’t run. + +- The marked async method can itself be awaited by methods that call it. + +An async method typically contains one or more occurrences of an `await` operator, but the absence of `await` expressions doesn’t cause a compiler error. If an async method doesn’t use an `await` operator to mark a suspension point, the method executes as a synchronous method does, despite the `async` modifier. The compiler issues a warning for such methods. + +`async` and `await` are contextual keywords. For more information and examples, see the following topics: + +- [async](../../../../csharp/language-reference/keywords/async.md) + +- [await](../../../../csharp/language-reference/keywords/await.md) + +## Return types and parameters + +An async method typically returns a or a . Inside an async method, an `await` operator is applied to a task that's returned from a call to another async method. + +You specify as the return type if the method contains a [`return`](../../../../csharp/language-reference/keywords/return.md) statement that specifies an operand of type `TResult`. + +You use as the return type if the method has no return statement or has a return statement that doesn't return an operand. Starting with C# 7.0, you can also specify any other return type, provided that the type includes a `GetAwaiter` method. is an example of such a type. It is available in the [System.Threading.Tasks.Extension](https://www.nuget.org/packages/System.Threading.Tasks.Extensions/) NuGet package. - - The following example shows how you declare and call a method that returns a or a . - -```csharp -// Signature specifies Task -async Task GetTaskOfTResultAsync() -{ - int hours = 0; - await Task.Delay(0); - // Return statement specifies an integer result. - return hours; -} - -// Calls to GetTaskOfTResultAsync -Task returnedTaskTResult = GetTaskOfTResultAsync(); -int intResult = await returnedTaskTResult; -// or, in a single statement -int intResult = await GetTaskOfTResultAsync(); - -// Signature specifies Task -async Task GetTaskAsync() -{ - await Task.Delay(0); - // The method has no return statement. -} - -// Calls to GetTaskAsync -Task returnedTask = GetTaskAsync(); -await returnedTask; -// or, in a single statement -await GetTaskAsync(); -``` - -Each returned task represents ongoing work. A task encapsulates information about the state of the asynchronous process and, eventually, either the final result from the process or the exception that the process raises if it doesn't succeed. - -An async method can also have a `void` return type. This return type is used primarily to define event handlers, where a `void` return type is required. Async event handlers often serve as the starting point for async programs. - -An async method that has a `void` return type can’t be awaited, and the caller of a void-returning method can't catch any exceptions that the method throws. - -An async method can't declare [in](../../../../csharp/language-reference/keywords/in-parameter-modifier.md), [ref](../../../../csharp/language-reference/keywords/ref.md) or [out](../../../../csharp/language-reference/keywords/out-parameter-modifier.md) parameters, but the method can call methods that have such parameters. Similarly, an async method can't return a value by reference, although it can call methods with ref return values. - -For more information and examples, see [Async Return Types (C#)](../../../../csharp/programming-guide/concepts/async/async-return-types.md). For more information about how to catch exceptions in async methods, see [try-catch](../../../../csharp/language-reference/keywords/try-catch.md). - -Asynchronous APIs in Windows Runtime programming have one of the following return types, which are similar to tasks: - -- , which corresponds to - -- , which corresponds to - -- - -- - -## Naming convention + +The following example shows how you declare and call a method that returns a or a . + +```csharp +// Signature specifies Task +async Task GetTaskOfTResultAsync() +{ + int hours = 0; + await Task.Delay(0); + // Return statement specifies an integer result. + return hours; +} + +// Calls to GetTaskOfTResultAsync +Task returnedTaskTResult = GetTaskOfTResultAsync(); +int intResult = await returnedTaskTResult; +// or, in a single statement +int intResult = await GetTaskOfTResultAsync(); + +// Signature specifies Task +async Task GetTaskAsync() +{ + await Task.Delay(0); + // The method has no return statement. +} + +// Calls to GetTaskAsync +Task returnedTask = GetTaskAsync(); +await returnedTask; +// or, in a single statement +await GetTaskAsync(); +``` + +Each returned task represents ongoing work. A task encapsulates information about the state of the asynchronous process and, eventually, either the final result from the process or the exception that the process raises if it doesn't succeed. + +An async method can also have a `void` return type. This return type is used primarily to define event handlers, where a `void` return type is required. Async event handlers often serve as the starting point for async programs. + +An async method that has a `void` return type can’t be awaited, and the caller of a void-returning method can't catch any exceptions that the method throws. + +An async method can't declare [in](../../../../csharp/language-reference/keywords/in-parameter-modifier.md), [ref](../../../../csharp/language-reference/keywords/ref.md) or [out](../../../../csharp/language-reference/keywords/out-parameter-modifier.md) parameters, but the method can call methods that have such parameters. Similarly, an async method can't return a value by reference, although it can call methods with ref return values. + +For more information and examples, see [Async Return Types (C#)](../../../../csharp/programming-guide/concepts/async/async-return-types.md). For more information about how to catch exceptions in async methods, see [try-catch](../../../../csharp/language-reference/keywords/try-catch.md). + +Asynchronous APIs in Windows Runtime programming have one of the following return types, which are similar to tasks: + +- , which corresponds to + +- , which corresponds to + +- + +- + +## Naming convention + By convention, methods that return commonly awaitable types (e.g. `Task`, `Task`, `ValueTask`, `ValueTask`) should have names that end with "Async". Methods that start an asynchronous operation but do not return an awaitable type should not have names that end with "Async", but may start with "Begin", "Start", or some other verb to suggest this method does not return or throw the result of the operation. - - You can ignore the convention where an event, base class, or interface contract suggests a different name. For example, you shouldn’t rename common event handlers, such as `Button1_Click`. - -## Related topics and samples (Visual Studio) - -|Title|Description|Sample| -|-----------|-----------------|------------| -|[Walkthrough: Accessing the Web by Using async and await (C#)](../../../../csharp/programming-guide/concepts/async/walkthrough-accessing-the-web-by-using-async-and-await.md)|Shows how to convert a synchronous WPF solution to an asynchronous WPF solution. The application downloads a series of websites.|[Async Sample: Accessing the Web Walkthrough](https://code.msdn.microsoft.com/Async-Sample-Accessing-the-9c10497f)| -|[How to: Extend the async Walkthrough by Using Task.WhenAll (C#)](../../../../csharp/programming-guide/concepts/async/how-to-extend-the-async-walkthrough-by-using-task-whenall.md)|Adds to the previous walkthrough. The use of `WhenAll` starts all the downloads at the same time.|| -|[How to: Make Multiple Web Requests in Parallel by Using async and await (C#)](../../../../csharp/programming-guide/concepts/async/how-to-make-multiple-web-requests-in-parallel-by-using-async-and-await.md)|Demonstrates how to start several tasks at the same time.|[Async Sample: Make Multiple Web Requests in Parallel](https://code.msdn.microsoft.com/Async-Make-Multiple-Web-49adb82e)| -|[Async Return Types (C#)](../../../../csharp/programming-guide/concepts/async/async-return-types.md)|Illustrates the types that async methods can return and explains when each type is appropriate.|| -|[Control Flow in Async Programs (C#)](../../../../csharp/programming-guide/concepts/async/control-flow-in-async-programs.md)|Traces in detail the flow of control through a succession of await expressions in an asynchronous program.|[Async Sample: Control Flow in Async Programs](https://code.msdn.microsoft.com/Async-Sample-Control-Flow-5c804fc0)| -|[Fine-Tuning Your Async Application (C#)](../../../../csharp/programming-guide/concepts/async/fine-tuning-your-async-application.md)|Shows how to add the following functionality to your async solution:

- [Cancel an Async Task or a List of Tasks (C#)](../../../../csharp/programming-guide/concepts/async/cancel-an-async-task-or-a-list-of-tasks.md)
- [Cancel Async Tasks after a Period of Time (C#)](../../../../csharp/programming-guide/concepts/async/cancel-async-tasks-after-a-period-of-time.md)
- [Cancel Remaining Async Tasks after One Is Complete (C#)](../../../../csharp/programming-guide/concepts/async/cancel-remaining-async-tasks-after-one-is-complete.md)
- [Start Multiple Async Tasks and Process Them As They Complete (C#)](../../../../csharp/programming-guide/concepts/async/start-multiple-async-tasks-and-process-them-as-they-complete.md)|[Async Sample: Fine Tuning Your Application](https://code.msdn.microsoft.com/Async-Fine-Tuning-Your-a676abea)| -|[Handling Reentrancy in Async Apps (C#)](../../../../csharp/programming-guide/concepts/async/handling-reentrancy-in-async-apps.md)|Shows how to handle cases in which an active asynchronous operation is restarted while it’s running.|| -|[WhenAny: Bridging between the .NET Framework and the Windows Runtime](https://docs.microsoft.com/previous-versions/visualstudio/visual-studio-2013/jj635140(v=vs.120))|Shows how to bridge between Task types in the .NET Framework and IAsyncOperations in the [!INCLUDE[wrt](~/includes/wrt-md.md)] so that you can use with a [!INCLUDE[wrt](~/includes/wrt-md.md)] method.|[Async Sample: Bridging between .NET and Windows Runtime (AsTask and WhenAny)](https://code.msdn.microsoft.com/Async-Sample-Bridging-d6a2f739)| -|Async Cancellation: Bridging between the .NET Framework and the Windows Runtime|Shows how to bridge between Task types in the .NET Framework and IAsyncOperations in the [!INCLUDE[wrt](~/includes/wrt-md.md)] so that you can use with a [!INCLUDE[wrt](~/includes/wrt-md.md)] method.|[Async Sample: Bridging between .NET and Windows Runtime (AsTask & Cancellation)](https://code.msdn.microsoft.com/Async-Sample-Bridging-9479eca3)| -|[Using Async for File Access (C#)](../../../../csharp/programming-guide/concepts/async/using-async-for-file-access.md)|Lists and demonstrates the benefits of using async and await to access files.|| -|[Task-based Asynchronous Pattern (TAP)](../../../../standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap.md)|Describes a new pattern for asynchrony in the .NET Framework. The pattern is based on the and types.|| -|[Async Videos on Channel 9](https://channel9.msdn.com/search?term=async%20&type=All#pubDate=year&ch9Search&lang-en=en)|Provides links to a variety of videos about async programming.|| - -## Complete example - The following code is the MainWindow.xaml.cs file from the Windows Presentation Foundation (WPF) application that this topic discusses. You can download the sample from [Async Sample: Example from "Asynchronous Programming with Async and Await"](https://code.msdn.microsoft.com/Async-Sample-Example-from-9b9f505c). - -```csharp -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; - -// Add a using directive and a reference for System.Net.Http; -using System.Net.Http; - -namespace AsyncFirstExample -{ - public partial class MainWindow : Window - { - // Mark the event handler with async so you can use await in it. - private async void StartButton_Click(object sender, RoutedEventArgs e) - { - // Call and await separately. - //Task getLengthTask = AccessTheWebAsync(); - //// You can do independent work here. - //int contentLength = await getLengthTask; - - int contentLength = await AccessTheWebAsync(); - + +You can ignore the convention where an event, base class, or interface contract suggests a different name. For example, you shouldn’t rename common event handlers, such as `Button1_Click`. + +## Related topics and samples (Visual Studio) + +|Title|Description|Sample| +|-----------|-----------------|------------| +|[Walkthrough: Accessing the Web by Using async and await (C#)](../../../../csharp/programming-guide/concepts/async/walkthrough-accessing-the-web-by-using-async-and-await.md)|Shows how to convert a synchronous WPF solution to an asynchronous WPF solution. The application downloads a series of websites.|[Async Sample: Accessing the Web Walkthrough](https://code.msdn.microsoft.com/Async-Sample-Accessing-the-9c10497f)| +|[How to: Extend the async Walkthrough by Using Task.WhenAll (C#)](../../../../csharp/programming-guide/concepts/async/how-to-extend-the-async-walkthrough-by-using-task-whenall.md)|Adds to the previous walkthrough. The use of `WhenAll` starts all the downloads at the same time.|| +|[How to: Make Multiple Web Requests in Parallel by Using async and await (C#)](../../../../csharp/programming-guide/concepts/async/how-to-make-multiple-web-requests-in-parallel-by-using-async-and-await.md)|Demonstrates how to start several tasks at the same time.|[Async Sample: Make Multiple Web Requests in Parallel](https://code.msdn.microsoft.com/Async-Make-Multiple-Web-49adb82e)| +|[Async Return Types (C#)](../../../../csharp/programming-guide/concepts/async/async-return-types.md)|Illustrates the types that async methods can return and explains when each type is appropriate.|| +|[Control Flow in Async Programs (C#)](../../../../csharp/programming-guide/concepts/async/control-flow-in-async-programs.md)|Traces in detail the flow of control through a succession of await expressions in an asynchronous program.|[Async Sample: Control Flow in Async Programs](https://code.msdn.microsoft.com/Async-Sample-Control-Flow-5c804fc0)| +|[Fine-Tuning Your Async Application (C#)](../../../../csharp/programming-guide/concepts/async/fine-tuning-your-async-application.md)|Shows how to add the following functionality to your async solution:

- [Cancel an Async Task or a List of Tasks (C#)](../../../../csharp/programming-guide/concepts/async/cancel-an-async-task-or-a-list-of-tasks.md)
- [Cancel Async Tasks after a Period of Time (C#)](../../../../csharp/programming-guide/concepts/async/cancel-async-tasks-after-a-period-of-time.md)
- [Cancel Remaining Async Tasks after One Is Complete (C#)](../../../../csharp/programming-guide/concepts/async/cancel-remaining-async-tasks-after-one-is-complete.md)
- [Start Multiple Async Tasks and Process Them As They Complete (C#)](../../../../csharp/programming-guide/concepts/async/start-multiple-async-tasks-and-process-them-as-they-complete.md)|[Async Sample: Fine Tuning Your Application](https://code.msdn.microsoft.com/Async-Fine-Tuning-Your-a676abea)| +|[Handling Reentrancy in Async Apps (C#)](../../../../csharp/programming-guide/concepts/async/handling-reentrancy-in-async-apps.md)|Shows how to handle cases in which an active asynchronous operation is restarted while it’s running.|| +|[WhenAny: Bridging between the .NET Framework and the Windows Runtime](https://docs.microsoft.com/previous-versions/visualstudio/visual-studio-2013/jj635140(v=vs.120))|Shows how to bridge between Task types in the .NET Framework and IAsyncOperations in the [!INCLUDE[wrt](~/includes/wrt-md.md)] so that you can use with a [!INCLUDE[wrt](~/includes/wrt-md.md)] method.|[Async Sample: Bridging between .NET and Windows Runtime (AsTask and WhenAny)](https://code.msdn.microsoft.com/Async-Sample-Bridging-d6a2f739)| +|Async Cancellation: Bridging between the .NET Framework and the Windows Runtime|Shows how to bridge between Task types in the .NET Framework and IAsyncOperations in the [!INCLUDE[wrt](~/includes/wrt-md.md)] so that you can use with a [!INCLUDE[wrt](~/includes/wrt-md.md)] method.|[Async Sample: Bridging between .NET and Windows Runtime (AsTask & Cancellation)](https://code.msdn.microsoft.com/Async-Sample-Bridging-9479eca3)| +|[Using Async for File Access (C#)](../../../../csharp/programming-guide/concepts/async/using-async-for-file-access.md)|Lists and demonstrates the benefits of using async and await to access files.|| +|[Task-based Asynchronous Pattern (TAP)](../../../../standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap.md)|Describes a new pattern for asynchrony in the .NET Framework. The pattern is based on the and types.|| +|[Async Videos on Channel 9](https://channel9.msdn.com/search?term=async%20&type=All#pubDate=year&ch9Search&lang-en=en)|Provides links to a variety of videos about async programming.|| + +## Complete example + +The following code is the MainWindow.xaml.cs file from the Windows Presentation Foundation (WPF) application that this topic discusses. You can download the sample from [Async Sample: Example from "Asynchronous Programming with Async and Await"](https://code.msdn.microsoft.com/Async-Sample-Example-from-9b9f505c). + +```csharp +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +// Add a using directive and a reference for System.Net.Http; +using System.Net.Http; + +namespace AsyncFirstExample +{ + public partial class MainWindow : Window + { + // Mark the event handler with async so you can use await in it. + private async void StartButton_Click(object sender, RoutedEventArgs e) + { + // Call and await separately. + //Task getLengthTask = AccessTheWebAsync(); + //// You can do independent work here. + //int contentLength = await getLengthTask; + + int contentLength = await AccessTheWebAsync(); + resultsTextBox.Text += $"\r\nLength of the downloaded string: {contentLength}.\r\n"; - } - - // Three things to note in the signature: - // - The method has an async modifier. - // - The return type is Task or Task. (See "Return Types" section.) - // Here, it is Task because the return statement returns an integer. - // - The method name ends in "Async." - async Task AccessTheWebAsync() - { - // You need to add a reference to System.Net.Http to declare client. - using (HttpClient client = new HttpClient()) - { - // GetStringAsync returns a Task. That means that when you await the - // task you'll get a string (urlContents). - Task getStringTask = client.GetStringAsync("https://docs.microsoft.com"); - - // You can do work here that doesn't rely on the string from GetStringAsync. - DoIndependentWork(); - - // The await operator suspends AccessTheWebAsync. - // - AccessTheWebAsync can't continue until getStringTask is complete. - // - Meanwhile, control returns to the caller of AccessTheWebAsync. - // - Control resumes here when getStringTask is complete. - // - The await operator then retrieves the string result from getStringTask. - string urlContents = await getStringTask; - - // The return statement specifies an integer result. - // Any methods that are awaiting AccessTheWebAsync retrieve the length value. - return urlContents.Length; - } - } - - void DoIndependentWork() - { - resultsTextBox.Text += "Working . . . . . . .\r\n"; - } - } -} - -// Sample Output: - -// Working . . . . . . . - -// Length of the downloaded string: 25035. -``` - + } + + // Three things to note in the signature: + // - The method has an async modifier. + // - The return type is Task or Task. (See "Return Types" section.) + // Here, it is Task because the return statement returns an integer. + // - The method name ends in "Async." + async Task AccessTheWebAsync() + { + // You need to add a reference to System.Net.Http to declare client. + using (HttpClient client = new HttpClient()) + { + // GetStringAsync returns a Task. That means that when you await the + // task you'll get a string (urlContents). + Task getStringTask = client.GetStringAsync("https://docs.microsoft.com"); + + // You can do work here that doesn't rely on the string from GetStringAsync. + DoIndependentWork(); + + // The await operator suspends AccessTheWebAsync. + // - AccessTheWebAsync can't continue until getStringTask is complete. + // - Meanwhile, control returns to the caller of AccessTheWebAsync. + // - Control resumes here when getStringTask is complete. + // - The await operator then retrieves the string result from getStringTask. + string urlContents = await getStringTask; + + // The return statement specifies an integer result. + // Any methods that are awaiting AccessTheWebAsync retrieve the length value. + return urlContents.Length; + } + } + + void DoIndependentWork() + { + resultsTextBox.Text += "Working . . . . . . .\r\n"; + } + } +} + +// Sample Output: + +// Working . . . . . . . + +// Length of the downloaded string: 25035. +``` + ## See also - [async](../../../../csharp/language-reference/keywords/async.md) diff --git a/docs/csharp/programming-guide/statements-expressions-operators/index.md b/docs/csharp/programming-guide/statements-expressions-operators/index.md index 8320cb2d093aa..b3e0438758396 100644 --- a/docs/csharp/programming-guide/statements-expressions-operators/index.md +++ b/docs/csharp/programming-guide/statements-expressions-operators/index.md @@ -2,7 +2,7 @@ title: "Statements, Expressions, and Operators - C# Programming Guide" ms.custom: seodec18 ms.date: 07/20/2015 -helpviewer_keywords: +helpviewer_keywords: - "expressions [C#]" - "operators [C#]" - "C# language, statements" @@ -12,33 +12,35 @@ helpviewer_keywords: ms.assetid: 20f8469d-5a6a-4084-ad90-0856b7e97e45 --- # Statements, Expressions, and Operators (C# Programming Guide) -The C# code that comprises an application consists of statements made up of keywords, expressions and operators. This section contains information regarding these fundamental elements of a C# program. - - For more information, see: - -- [Statements](statements.md) - -- [Expressions](expressions.md) - - - [Expression-bodied members](expression-bodied-members.md) - -- [Operators](operators.md) - -- [Anonymous Functions](anonymous-functions.md) - -- [Overloadable Operators](overloadable-operators.md) - -- [Conversion Operators](conversion-operators.md) - - - [Using Conversion Operators](using-conversion-operators.md) - - - [How to: Implement User-Defined Conversions Between Structs](how-to-implement-user-defined-conversions-between-structs.md) - -- [Equality Comparisons](equality-comparisons.md) - -## C# Language Specification - [!INCLUDE[CSharplangspec](~/includes/csharplangspec-md.md)] - + +The C# code that comprises an application consists of statements made up of keywords, expressions and operators. This section contains information regarding these fundamental elements of a C# program. + + For more information, see: + +- [Statements](statements.md) + +- [Expressions](expressions.md) + + - [Expression-bodied members](expression-bodied-members.md) + +- [Operators](operators.md) + +- [Anonymous Functions](anonymous-functions.md) + +- [Overloadable Operators](overloadable-operators.md) + +- [Conversion Operators](conversion-operators.md) + + - [Using Conversion Operators](using-conversion-operators.md) + + - [How to: Implement User-Defined Conversions Between Structs](how-to-implement-user-defined-conversions-between-structs.md) + +- [Equality Comparisons](equality-comparisons.md) + +## C# Language Specification + +[!INCLUDE[CSharplangspec](~/includes/csharplangspec-md.md)] + ## See also - [C# Programming Guide](../../../csharp/programming-guide/index.md) diff --git a/docs/csharp/programming-guide/xmldoc/processing-the-xml-file.md b/docs/csharp/programming-guide/xmldoc/processing-the-xml-file.md index b70451cef8ae2..4415385fe4515 100644 --- a/docs/csharp/programming-guide/xmldoc/processing-the-xml-file.md +++ b/docs/csharp/programming-guide/xmldoc/processing-the-xml-file.md @@ -2,79 +2,81 @@ title: "Processing the XML File - C# Programming Guide" ms.custom: seodec18 ms.date: 07/20/2015 -helpviewer_keywords: +helpviewer_keywords: - "XML processing [C#]" - "XML [C#], processing" ms.assetid: 60c71193-9dac-4cd3-98c5-100bd0edcc42 --- # Processing the XML File (C# Programming Guide) -The compiler generates an ID string for each construct in your code that is tagged to generate documentation. (For information about how to tag your code, see [Recommended Tags for Documentation Comments](../../../csharp/programming-guide/xmldoc/recommended-tags-for-documentation-comments.md).) The ID string uniquely identifies the construct. Programs that process the XML file can use the ID string to identify the corresponding .NET Framework metadata/reflection item that the documentation applies to. - - The XML file is not a hierarchical representation of your code; it is a flat list that has a generated ID for each element. - - The compiler observes the following rules when it generates the ID strings: - -- No white space is in the string. - -- The first part of the ID string identifies the kind of member being identified, by way of a single character followed by a colon. The following member types are used: - - |Character|Description| - |---------------|-----------------| - |N|namespace

You cannot add documentation comments to a namespace, but you can make cref references to them, where supported.| - |T|type: class, interface, struct, enum, delegate| - |F|field| - |P|property (including indexers or other indexed properties)| - |M|method (including such special methods as constructors, operators, and so forth)| - |E|event| - |!|error string

The rest of the string provides information about the error. The C# compiler generates error information for links that cannot be resolved.| - -- The second part of the string is the fully qualified name of the item, starting at the root of the namespace. The name of the item, its enclosing type(s), and namespace are separated by periods. If the name of the item itself has periods, they are replaced by the hash-sign ('#'). It is assumed that no item has a hash-sign directly in its name. For example, the fully qualified name of the String constructor would be "System.String.#ctor". - -- For properties and methods, if there are arguments to the method, the argument list enclosed in parentheses follows. If there are no arguments, no parentheses are present. The arguments are separated by commas. The encoding of each argument follows directly how it is encoded in a .NET Framework signature: - - - Base types. Regular types (ELEMENT_TYPE_CLASS or ELEMENT_TYPE_VALUETYPE) are represented as the fully qualified name of the type. - - - Intrinsic types (for example, ELEMENT_TYPE_I4, ELEMENT_TYPE_OBJECT, ELEMENT_TYPE_STRING, ELEMENT_TYPE_TYPEDBYREF. and ELEMENT_TYPE_VOID) are represented as the fully qualified name of the corresponding full type. For example, System.Int32 or System.TypedReference. - - - ELEMENT_TYPE_PTR is represented as a '\*' following the modified type. - - - ELEMENT_TYPE_BYREF is represented as a '\@' following the modified type. - - - ELEMENT_TYPE_PINNED is represented as a '^' following the modified type. The C# compiler never generates this. - - - ELEMENT_TYPE_CMOD_REQ is represented as a '|' and the fully qualified name of the modifier class, following the modified type. The C# compiler never generates this. - - - ELEMENT_TYPE_CMOD_OPT is represented as a '!' and the fully qualified name of the modifier class, following the modified type. - - - ELEMENT_TYPE_SZARRAY is represented as "[]" following the element type of the array. - - - ELEMENT_TYPE_GENERICARRAY is represented as "[?]" following the element type of the array. The C# compiler never generates this. - - - ELEMENT_TYPE_ARRAY is represented as [*lowerbound*:`size`,*lowerbound*:`size`] where the number of commas is the rank - 1, and the lower bounds and size of each dimension, if known, are represented in decimal. If a lower bound or size is not specified, it is simply omitted. If the lower bound and size for a particular dimension are omitted, the ':' is omitted as well. For example, a 2-dimensional array with 1 as the lower bounds and unspecified sizes is [1:,1:]. - - - ELEMENT_TYPE_FNPTR is represented as "=FUNC:`type`(*signature*)", where `type` is the return type, and *signature* is the arguments of the method. If there are no arguments, the parentheses are omitted. The C# compiler never generates this. - - The following signature components are not represented because they are never used for differentiating overloaded methods: - - - calling convention - - - return type - - - ELEMENT_TYPE_SENTINEL - -- For conversion operators only (op_Implicit and op_Explicit), the return value of the method is encoded as a '~' followed by the return type, as encoded above. - -- For generic types, the name of the type is followed by a backtick and then a number that indicates the number of generic type parameters. For example: - - ```` is the tag for a type that is defined as `public class SampleClass`. - - For methods taking generic types as parameters, the generic type parameters are specified as numbers prefaced with backticks (for example \`0,\`1). Each number representing a zero-based array notation for the type's generic parameters. - -## Examples - The following examples show how the ID strings for a class and its members would be generated: - - [!code-csharp[csProgGuidePointers#21](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csProgGuidePointers/CS/Pointers.cs#21)] - + +The compiler generates an ID string for each construct in your code that is tagged to generate documentation. (For information about how to tag your code, see [Recommended Tags for Documentation Comments](../../../csharp/programming-guide/xmldoc/recommended-tags-for-documentation-comments.md).) The ID string uniquely identifies the construct. Programs that process the XML file can use the ID string to identify the corresponding .NET Framework metadata/reflection item that the documentation applies to. + + The XML file is not a hierarchical representation of your code; it is a flat list that has a generated ID for each element. + + The compiler observes the following rules when it generates the ID strings: + +- No white space is in the string. + +- The first part of the ID string identifies the kind of member being identified, by way of a single character followed by a colon. The following member types are used: + + |Character|Description| + |---------------|-----------------| + |N|namespace

You cannot add documentation comments to a namespace, but you can make cref references to them, where supported.| + |T|type: class, interface, struct, enum, delegate| + |F|field| + |P|property (including indexers or other indexed properties)| + |M|method (including such special methods as constructors, operators, and so forth)| + |E|event| + |!|error string

The rest of the string provides information about the error. The C# compiler generates error information for links that cannot be resolved.| + +- The second part of the string is the fully qualified name of the item, starting at the root of the namespace. The name of the item, its enclosing type(s), and namespace are separated by periods. If the name of the item itself has periods, they are replaced by the hash-sign ('#'). It is assumed that no item has a hash-sign directly in its name. For example, the fully qualified name of the String constructor would be "System.String.#ctor". + +- For properties and methods, if there are arguments to the method, the argument list enclosed in parentheses follows. If there are no arguments, no parentheses are present. The arguments are separated by commas. The encoding of each argument follows directly how it is encoded in a .NET Framework signature: + + - Base types. Regular types (ELEMENT_TYPE_CLASS or ELEMENT_TYPE_VALUETYPE) are represented as the fully qualified name of the type. + + - Intrinsic types (for example, ELEMENT_TYPE_I4, ELEMENT_TYPE_OBJECT, ELEMENT_TYPE_STRING, ELEMENT_TYPE_TYPEDBYREF. and ELEMENT_TYPE_VOID) are represented as the fully qualified name of the corresponding full type. For example, System.Int32 or System.TypedReference. + + - ELEMENT_TYPE_PTR is represented as a '\*' following the modified type. + + - ELEMENT_TYPE_BYREF is represented as a '\@' following the modified type. + + - ELEMENT_TYPE_PINNED is represented as a '^' following the modified type. The C# compiler never generates this. + + - ELEMENT_TYPE_CMOD_REQ is represented as a '|' and the fully qualified name of the modifier class, following the modified type. The C# compiler never generates this. + + - ELEMENT_TYPE_CMOD_OPT is represented as a '!' and the fully qualified name of the modifier class, following the modified type. + + - ELEMENT_TYPE_SZARRAY is represented as "[]" following the element type of the array. + + - ELEMENT_TYPE_GENERICARRAY is represented as "[?]" following the element type of the array. The C# compiler never generates this. + + - ELEMENT_TYPE_ARRAY is represented as [*lowerbound*:`size`,*lowerbound*:`size`] where the number of commas is the rank - 1, and the lower bounds and size of each dimension, if known, are represented in decimal. If a lower bound or size is not specified, it is simply omitted. If the lower bound and size for a particular dimension are omitted, the ':' is omitted as well. For example, a 2-dimensional array with 1 as the lower bounds and unspecified sizes is [1:,1:]. + + - ELEMENT_TYPE_FNPTR is represented as "=FUNC:`type`(*signature*)", where `type` is the return type, and *signature* is the arguments of the method. If there are no arguments, the parentheses are omitted. The C# compiler never generates this. + + The following signature components are not represented because they are never used for differentiating overloaded methods: + + - calling convention + + - return type + + - ELEMENT_TYPE_SENTINEL + +- For conversion operators only (op_Implicit and op_Explicit), the return value of the method is encoded as a '~' followed by the return type, as encoded above. + +- For generic types, the name of the type is followed by a backtick and then a number that indicates the number of generic type parameters. For example: + + ```` is the tag for a type that is defined as `public class SampleClass`. + + For methods taking generic types as parameters, the generic type parameters are specified as numbers prefaced with backticks (for example \`0,\`1). Each number representing a zero-based array notation for the type's generic parameters. + +## Examples + +The following examples show how the ID strings for a class and its members would be generated: + +[!code-csharp[csProgGuidePointers#21](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csProgGuidePointers/CS/Pointers.cs#21)] + ## See also - [C# Programming Guide](../../../csharp/programming-guide/index.md) diff --git a/docs/csharp/tour-of-csharp/classes-and-objects.md b/docs/csharp/tour-of-csharp/classes-and-objects.md index 0ba150e886145..52ffc27d2b775 100644 --- a/docs/csharp/tour-of-csharp/classes-and-objects.md +++ b/docs/csharp/tour-of-csharp/classes-and-objects.md @@ -28,42 +28,42 @@ The members of a class are either static members or instance members. Static mem The following provides an overview of the kinds of members a class can contain. * Constants - - Constant values associated with the class + - Constant values associated with the class * Fields - - Variables of the class + - Variables of the class * Methods - - Computations and actions that can be performed by the class + - Computations and actions that can be performed by the class * Properties - - Actions associated with reading and writing named properties of the class + - Actions associated with reading and writing named properties of the class * Indexers - - Actions associated with indexing instances of the class like an array + - Actions associated with indexing instances of the class like an array * Events - - Notifications that can be generated by the class + - Notifications that can be generated by the class * Operators - - Conversions and expression operators supported by the class + - Conversions and expression operators supported by the class * Constructors - - Actions required to initialize instances of the class or the class itself + - Actions required to initialize instances of the class or the class itself * Finalizers - - Actions to perform before instances of the class are permanently discarded + - Actions to perform before instances of the class are permanently discarded * Types - - Nested types declared by the class + - Nested types declared by the class ## Accessibility Each member of a class has an associated accessibility, which controls the regions of program text that are able to access the member. There are six possible forms of accessibility. These are summarized below. * `public` - - Access not limited + - Access not limited * `protected` - - Access limited to this class or classes derived from this class + - Access limited to this class or classes derived from this class * `internal` - - Access limited to the current assembly (.exe, .dll, etc.) + - Access limited to the current assembly (.exe, .dll, etc.) * `protected internal` - - Access limited to the containing class, classes derived from the containing class, or classes within the same assembly + - Access limited to the containing class, classes derived from the containing class, or classes within the same assembly * `private` - - Access limited to this class + - Access limited to this class * `private protected` - - Access limited to the containing class or classes derived from the containing type within the same assembly + - Access limited to the containing class or classes derived from the containing type within the same assembly ## Type parameters diff --git a/docs/csharp/tutorials/working-with-linq.md b/docs/csharp/tutorials/working-with-linq.md index f3e3c5e3e3a6c..387d1eba2dc20 100644 --- a/docs/csharp/tutorials/working-with-linq.md +++ b/docs/csharp/tutorials/working-with-linq.md @@ -335,9 +335,9 @@ Aside from LINQ, you learned a bit about a technique magicians use for card tric For more information on LINQ, see: - [Language Integrated Query (LINQ)](../programming-guide/concepts/linq/index.md) - - [Introduction to LINQ](../programming-guide/concepts/linq/introduction-to-linq.md) - - [Getting Started With LINQ in C#](../programming-guide/concepts/linq/getting-started-with-linq.md) - - [Basic LINQ Query Operations (C#)](../programming-guide/concepts/linq/basic-linq-query-operations.md) - - [Data Transformations With LINQ (C#)](../programming-guide/concepts/linq/data-transformations-with-linq.md) - - [Query Syntax and Method Syntax in LINQ (C#)](../programming-guide/concepts/linq/query-syntax-and-method-syntax-in-linq.md) - - [C# Features That Support LINQ](../programming-guide/concepts/linq/features-that-support-linq.md) + - [Introduction to LINQ](../programming-guide/concepts/linq/introduction-to-linq.md) + - [Getting Started With LINQ in C#](../programming-guide/concepts/linq/getting-started-with-linq.md) + - [Basic LINQ Query Operations (C#)](../programming-guide/concepts/linq/basic-linq-query-operations.md) + - [Data Transformations With LINQ (C#)](../programming-guide/concepts/linq/data-transformations-with-linq.md) + - [Query Syntax and Method Syntax in LINQ (C#)](../programming-guide/concepts/linq/query-syntax-and-method-syntax-in-linq.md) + - [C# Features That Support LINQ](../programming-guide/concepts/linq/features-that-support-linq.md) diff --git a/docs/framework/data/adonet/ef/the-shape-of-the-command-trees.md b/docs/framework/data/adonet/ef/the-shape-of-the-command-trees.md index a2f761e183d1e..52980e5d93326 100644 --- a/docs/framework/data/adonet/ef/the-shape-of-the-command-trees.md +++ b/docs/framework/data/adonet/ef/the-shape-of-the-command-trees.md @@ -80,9 +80,9 @@ DbNewInstanceExpression can only occur in the following two cases: - As the Projection property of DbProjectExpression. When used as such the following restrictions apply: - - The result type must be a row type. + - The result type must be a row type. - - Each of its arguments is an expression that produces a result with a primitive type. Typically, each argument is a scalar expression, like a PropertyExpression over a DbVariableReferenceExpression, a function invocation, or an arithmetic computation of the DbPropertyExpression over a DbVariableReferenceExpression or a function invocation. However, an expression representing a scalar subquery can also occur in the list of arguments for a DbNewInstanceExpression. An expression that represents a scalar subquery is an expression tree that represents a subquery that returns exactly one row and one column of a primitive type with a DbElementExpression object root + - Each of its arguments is an expression that produces a result with a primitive type. Typically, each argument is a scalar expression, like a PropertyExpression over a DbVariableReferenceExpression, a function invocation, or an arithmetic computation of the DbPropertyExpression over a DbVariableReferenceExpression or a function invocation. However, an expression representing a scalar subquery can also occur in the list of arguments for a DbNewInstanceExpression. An expression that represents a scalar subquery is an expression tree that represents a subquery that returns exactly one row and one column of a primitive type with a DbElementExpression object root - With a collection return type, in which case it defines a new collection of the expressions provided as arguments. diff --git a/docs/framework/data/adonet/sql/granting-row-level-permissions-in-sql-server.md b/docs/framework/data/adonet/sql/granting-row-level-permissions-in-sql-server.md index 27217839d30e5..12bd4e673fff5 100644 --- a/docs/framework/data/adonet/sql/granting-row-level-permissions-in-sql-server.md +++ b/docs/framework/data/adonet/sql/granting-row-level-permissions-in-sql-server.md @@ -18,35 +18,35 @@ The following example describes how to configure row-level filtering based on a - Enable row-level filtering: - - If you are using SQL Server 2016 or higher, or [Azure SQL Database](https://docs.microsoft.com/azure/sql-database/), create a security policy that adds a predicate on the table restricting the rows returned to those that match either the current database user (using the CURRENT_USER() built-in function) or the current login name (using the SUSER_SNAME() built-in function): - - ```sql - CREATE SCHEMA Security - GO - - CREATE FUNCTION Security.userAccessPredicate(@UserName sysname) - RETURNS TABLE - WITH SCHEMABINDING - AS - RETURN SELECT 1 AS accessResult - WHERE @UserName = SUSER_SNAME() - GO - - CREATE SECURITY POLICY Security.userAccessPolicy - ADD FILTER PREDICATE Security.userAccessPredicate(UserName) ON dbo.MyTable, - ADD BLOCK PREDICATE Security.userAccessPredicate(UserName) ON dbo.MyTable - GO - ``` - - - If you are using a version of SQL Server prior to 2016, you can achieve similar functionality using a view: - - ```sql - CREATE VIEW vw_MyTable - AS - RETURN SELECT * FROM MyTable - WHERE UserName = SUSER_SNAME() - GO - ``` + - If you are using SQL Server 2016 or higher, or [Azure SQL Database](https://docs.microsoft.com/azure/sql-database/), create a security policy that adds a predicate on the table restricting the rows returned to those that match either the current database user (using the CURRENT_USER() built-in function) or the current login name (using the SUSER_SNAME() built-in function): + + ```sql + CREATE SCHEMA Security + GO + + CREATE FUNCTION Security.userAccessPredicate(@UserName sysname) + RETURNS TABLE + WITH SCHEMABINDING + AS + RETURN SELECT 1 AS accessResult + WHERE @UserName = SUSER_SNAME() + GO + + CREATE SECURITY POLICY Security.userAccessPolicy + ADD FILTER PREDICATE Security.userAccessPredicate(UserName) ON dbo.MyTable, + ADD BLOCK PREDICATE Security.userAccessPredicate(UserName) ON dbo.MyTable + GO + ``` + + - If you are using a version of SQL Server prior to 2016, you can achieve similar functionality using a view: + + ```sql + CREATE VIEW vw_MyTable + AS + RETURN SELECT * FROM MyTable + WHERE UserName = SUSER_SNAME() + GO + ``` - Create stored procedures to select, insert, update, and delete data. If the filtering is enacted by a security policy, the stored procedures should perform these operations on the base table directly; otherwise, if the filtering is enacted by a view, the stored procedures should instead operate against the view. The security policy or view will automatically filter the rows returned or modified by user queries, and the stored procedure will provide a harder security boundary to prevent users with direct query access from successfully running queries that can infer the existence of filtered data. diff --git a/docs/framework/data/adonet/sql/linq/data-binding.md b/docs/framework/data/adonet/sql/linq/data-binding.md index 46b4b73080a07..e30ba3eef4134 100644 --- a/docs/framework/data/adonet/sql/linq/data-binding.md +++ b/docs/framework/data/adonet/sql/linq/data-binding.md @@ -37,9 +37,9 @@ Collection generations are implemented by generic . There are two scenarios: - - If [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] finds the underlying from the , the source allows for edition and the situation is the same as in the first bullet point. + - If [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] finds the underlying from the , the source allows for edition and the situation is the same as in the first bullet point. - - If [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] cannot find the underlying , the source does not allow for edition (for example, `groupby`). [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] browses the query to fill a generic `SortableBindingList`, which is a simple that implements the sorting feature for T entities for a given property. + - If [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] cannot find the underlying , the source does not allow for edition (for example, `groupby`). [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] browses the query to fill a generic `SortableBindingList`, which is a simple that implements the sorting feature for T entities for a given property. ## Specialized Collections diff --git a/docs/framework/data/adonet/sql/linq/numeric-and-comparison-operators.md b/docs/framework/data/adonet/sql/linq/numeric-and-comparison-operators.md index d5a4f1a436ef3..875385455a90a 100644 --- a/docs/framework/data/adonet/sql/linq/numeric-and-comparison-operators.md +++ b/docs/framework/data/adonet/sql/linq/numeric-and-comparison-operators.md @@ -4,53 +4,55 @@ ms.date: "03/30/2017" ms.assetid: 25b4a26a-06f2-4f80-87a9-76705ed46197 --- # Numeric and Comparison Operators -Arithmetic and comparison operators work as expected in the common language runtime (CLR) except as follows: - -- SQL does not support the modulus operator on floating-point numbers. - -- SQL does not support unchecked arithmetic. - -- Increment and decrement operators cause side-effects when you use them in expressions that cannot be replicated in SQL and are, therefore, not supported. - -## Supported Operators - [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] supports the following operators. - -- Basic arithmetic operators: - - - `+` - - - `-` (subtraction) - - - `*` - - - `/` - - - Visual Basic integer division (`\`) - - - `%` (Visual Basic `Mod`) - - - `<<` - - - `>>` - - - `-` (unary negation) - -- Basic comparison operators: - - - Visual Basic `=` and C# `==` - - - Visual Basic `<>` and C# `!=` - - - Visual Basic `Is/IsNot` - - - `<` - - - `<=` - - - `>` - - - `>=` - + +Arithmetic and comparison operators work as expected in the common language runtime (CLR) except as follows: + +- SQL does not support the modulus operator on floating-point numbers. + +- SQL does not support unchecked arithmetic. + +- Increment and decrement operators cause side-effects when you use them in expressions that cannot be replicated in SQL and are, therefore, not supported. + +## Supported Operators + +[!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] supports the following operators. + +- Basic arithmetic operators: + + - `+` + + - `-` (subtraction) + + - `*` + + - `/` + + - Visual Basic integer division (`\`) + + - `%` (Visual Basic `Mod`) + + - `<<` + + - `>>` + + - `-` (unary negation) + +- Basic comparison operators: + + - Visual Basic `=` and C# `==` + + - Visual Basic `<>` and C# `!=` + + - Visual Basic `Is/IsNot` + + - `<` + + - `<=` + + - `>` + + - `>=` + ## See also - [Data Types and Functions](../../../../../../docs/framework/data/adonet/sql/linq/data-types-and-functions.md) diff --git a/docs/framework/data/adonet/sql/linq/sql-clr-type-mismatches.md b/docs/framework/data/adonet/sql/linq/sql-clr-type-mismatches.md index 9a6b86204afd2..eb83c9abff082 100644 --- a/docs/framework/data/adonet/sql/linq/sql-clr-type-mismatches.md +++ b/docs/framework/data/adonet/sql/linq/sql-clr-type-mismatches.md @@ -1,292 +1,304 @@ --- title: "SQL-CLR Type Mismatches" ms.date: "03/30/2017" -dev_langs: +dev_langs: - "csharp" - "vb" ms.assetid: 0a90c33f-7ed7-4501-ad5f-6224c5da8e9b --- # SQL-CLR Type Mismatches -[!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] automates much of the translation between the object model and SQL Server. Nevertheless, some situations prevent exact translation. These key mismatches between the common language runtime (CLR) types and the SQL Server database types are summarized in the following sections. You can find more details about specific type mappings and function translation at [SQL-CLR Type Mapping](../../../../../../docs/framework/data/adonet/sql/linq/sql-clr-type-mapping.md) and [Data Types and Functions](../../../../../../docs/framework/data/adonet/sql/linq/data-types-and-functions.md). - -## Data Types - Translation between the CLR and SQL Server occurs when a query is being sent to the database, and when the results are sent back to your object model. For example, the following Transact-SQL query requires two value conversions: - -``` -Select DateOfBirth From Customer Where CustomerId = @id -``` - - Before the query can be executed on SQL Server, the value for the Transact-SQL parameter must be specified. In this example, the `id` parameter value must first be translated from a CLR type to a SQL Server `INT` type so that the database can understand what the value is. Then to retrieve the results, the SQL Server `DateOfBirth` column must be translated from a SQL Server `DATETIME` type to a CLR type for use in the object model. In this example, the types in the CLR object model and SQL Server database have natural mappings. But, this is not always the case. - -### Missing Counterparts - The following types do not have reasonable counterparts. - -- Mismatches in the CLR namespace: - - - **Unsigned integers**. These types are typically mapped to their signed counterparts of larger size to avoid overflow. Literals can be converted to a signed numeric of the same or smaller size, based on value. - - - **Boolean**. These types can be mapped to a bit or larger numeric or string. A literal can be mapped to an expression that evaluates to the same value (for example, `1=1` in SQL for `True` in CLS). - - - **TimeSpan**. This type represents the difference between two `DateTime` values and does not correspond to the `timestamp` of SQL Server. The CLR may also map to the SQL Server `TIME` type in some cases. The SQL Server `TIME` type was only intended to represent positive values less than 24 hours. The CLR has a much larger range. - - > [!NOTE] - > SQL Server-specific [!INCLUDE[dnprdnshort](../../../../../../includes/dnprdnshort-md.md)] types in are not included in this comparison. - -- Mismatches in SQL Server: - - - **Fixed length character types**. Transact-SQL distinguishes between Unicode and non-Unicode categories and has three distinct types in each category: fixed length `nchar`/`char`, variable length `nvarchar`/`varchar`, and larger-sized `ntext`/`text`. The fixed length character types could be mapped to the CLR type for retrieving characters, but they do not really correspond to the same type in conversions and behavior. - - - **Bit**. Although the `bit` domain has the same number of values as `Nullable`, the two are different types. `Bit` takes values `1` and `0` instead of `true`/`false`, and cannot be used as an equivalent to Boolean expressions. - - - **Timestamp**. Unlike the CLR type, the SQL Server `TIMESTAMP` type represents an 8-byte number generated by the database that is unique for each update and is not based on the difference between values. - - - **Money** and **SmallMoney**. These types can be mapped to but are basically different types and are treated as such by server-based functions and conversions. - -### Multiple Mappings - There are many SQL Server data types that you can map to one or more CLR data types. There are also many CLR types that you can map to one or more SQL Server types. Although a mapping may be supported by LINQ to SQL, it does not mean that the two types mapped between the CLR and SQL Server are a perfect match in precision, range, and semantics. Some mappings may include differences in any or all of these dimensions. You can find details about these potential differences for the various mapping possibilities at [SQL-CLR Type Mapping](../../../../../../docs/framework/data/adonet/sql/linq/sql-clr-type-mapping.md). - -### User-defined Types - User-defined CLR types are designed to help bridge the type system gap. Nevertheless they surface interesting issues about type versioning. A change in the version on the client might not be matched by a change in the type stored on the database server. Any such change causes another type mismatch where the type semantics might not match and the version gap is likely to become visible. Further complications occur as inheritance hierarchies are refactored in successive versions. - -## Expression Semantics - In addition to the pairwise mismatch between CLR and database types, expressions add complexity to the mismatch. Mismatches in operator semantics, function semantics, implicit type conversion, and precedence rules must be considered. - - The following subsections illustrate the mismatch between apparently similar expressions. It might be possible to generate SQL expressions that are semantically equivalent to a given CLR expression. However, it is not clear whether the semantic differences between apparently similar expressions are evident to a CLR user, and therefore whether the changes that are required for semantic equivalence are intended or not. This is an especially critical issue when an expression is evaluated for a set of values. The visibility of the difference might depend on data- and be hard to identify during coding and debugging. - -### Null Semantics - SQL expressions provide three-valued logic for Boolean expressions. The result can be true, false, or null. By contrast, CLR specifies two-valued Boolean result for comparisons involving null values. Consider the following code: - - [!code-csharp[DLinqMismatch#2](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqMismatch/cs/Program.cs#2)] - [!code-vb[DLinqMismatch#2](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqMismatch/vb/Module1.vb#2)] - -``` --- Assume col1 and col2 are integer columns with null values. --- Assume that ANSI null behavior has not been explicitly --- turned off. -Select … -From … -Where col1 = col2 --- Evaluates to null, not true and the corresponding row is not --- selected. --- To obtain matching behavior (i -> col1, j -> col2) change --- the query to the following: -Select … -From … -Where - col1 = col2 -or (col1 is null and col2 is null) --- (Visual Basic 'Nothing'.) -``` - - A similar problem occurs with the assumption about two-valued results. - - [!code-csharp[DLinqMismatch#3](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqMismatch/cs/Program.cs#3)] - [!code-vb[DLinqMismatch#3](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqMismatch/vb/Module1.vb#3)] - -``` --- Assume col1 and col2 are nullable columns. --- Assume that ANSI null behavior has not been explicitly --- turned off. -Select … -From … -Where - col1 = col2 -or col1 != col2 --- Visual Basic: col1 <> col2. - --- Excludes the case where the boolean expression evaluates --- to null. Therefore the where clause does not always --- evaluate to true. -``` - - In the previous case, you can get equivalent behavior in generating SQL, but the translation might not accurately reflect your intention. - - [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] does not impose C# `null` or Visual Basic `nothing` comparison semantics on SQL. Comparison operators are syntactically translated to their SQL equivalents. The semantics reflect SQL semantics as defined by server or connection settings. Two null values are considered unequal under default SQL Server settings (although you can change the settings to change the semantics). Regardless, [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] does not consider server settings in query translation. - - A comparison with the literal `null` (`nothing`) is translated to the appropriate SQL version (`is null` or `is not null`). - - The value of `null` (`nothing`) in collation is defined by SQL Server; [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] does not change the collation. - -### Type Conversion and Promotion - SQL supports a rich set of implicit conversions in expressions. Similar expressions in C# would require an explicit cast. For example: - -- `Nvarchar` and `DateTime` types can be compared in SQL without any explicit casts; C# requires explicit conversion. - -- `Decimal` is implicitly converted to `DateTime` in SQL. C# does not allow for an implicit conversion. - - Likewise, type precedence in Transact-SQL differs from type precedence in C# because the underlying set of types is different. In fact, there is no clear subset/superset relationship between the precedence lists. For example, comparing an `nvarchar` with a `varchar` causes the implicit conversion of the `varchar` expression to `nvarchar`. The CLR provides no equivalent promotion. - - In simple cases, these differences cause CLR expressions with casts to be redundant for a corresponding SQL expression. More importantly, the intermediate results of a SQL expression might be implicitly promoted to a type that has no accurate counterpart in C#, and vice versa. Overall, the testing, debugging, and validation of such expressions adds significant burden on the user. - -### Collation - Transact-SQL supports explicit collations as annotations to character string types. These collations determine the validity of certain comparisons. For example, comparing two columns with different explicit collations is an error. The use of much simplified CTS string type does not cause such errors. Consider the following example: - -``` -create table T2 ( - Col1 nvarchar(10), - Col2 nvarchar(10) collate Latin_general_ci_as -) -``` - - [!code-csharp[DLinqMismatch#4](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqMismatch/cs/Program.cs#4)] - [!code-vb[DLinqMismatch#4](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqMismatch/vb/Module1.vb#4)] - -``` -Select … -From … -Where Col1 = Col2 --- Error, collation conflict. -``` - - In effect, the collation subclause creates a *restricted type* that is not substitutable. - - Similarly, the sort order can be significantly different across the type systems. This difference affects the sorting of results. is sorted on all 16 bytes by lexicographic order (`IComparable()`), whereas T-SQL compares GUIDs in the following order: node(10-15), clock-seq(8-9), time-high(6-7), time-mid(4-5), time-low(0-3). This ordering was done in SQL 7.0 when NT-generated GUIDs had such an octet order. The approach ensured that GUIDs generated at the same node cluster came together in sequential order according to timestamp. The approach was also useful for building indexes (inserts become appends instead of random IOs). The order was scrambled later in Windows because of privacy concerns, but SQL must maintain compatibility. A workaround is to use instead of . - -### Operator and Function Differences - Operators and functions that are essentially comparable have subtly different semantics. For example: - -- C# specifies short circuit semantics based on lexical order of operands for logical operators `&&` and `||`. SQL on the other hand is targeted for set-based queries and therefore provides more freedom for the optimizer to decide the order of execution. Some of the implications include the following: - - - Semantically equivalent translation would require "`CASE` … `WHEN` … `THEN`" construct in SQL to avoid reordering of operand execution. - - - A loose translation to `AND`/`OR` operators could cause unexpected errors if the C# expression relies on evaluation the second operand being based on the result of the evaluation of the first operand. - -- `Round()` function has different semantics in [!INCLUDE[dnprdnshort](../../../../../../includes/dnprdnshort-md.md)] and in T-SQL. - -- Starting index for strings is 0 in the CLR but 1 in SQL. Therefore, any function that has index needs index translation. - -- The CLR supports modulus (‘%’) operator for floating point numbers but SQL does not. - -- The `Like` operator effectively acquires automatic overloads based on implicit conversions. Although the `Like` operator is defined to operate on character string types, implicit conversion from numeric types or `DateTime` types allows for those non-string types to be used with `Like` just as well. In CTS, comparable implicit conversions do not exist. Therefore, additional overloads are needed. - + +[!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] automates much of the translation between the object model and SQL Server. Nevertheless, some situations prevent exact translation. These key mismatches between the common language runtime (CLR) types and the SQL Server database types are summarized in the following sections. You can find more details about specific type mappings and function translation at [SQL-CLR Type Mapping](../../../../../../docs/framework/data/adonet/sql/linq/sql-clr-type-mapping.md) and [Data Types and Functions](../../../../../../docs/framework/data/adonet/sql/linq/data-types-and-functions.md). + +## Data Types + +Translation between the CLR and SQL Server occurs when a query is being sent to the database, and when the results are sent back to your object model. For example, the following Transact-SQL query requires two value conversions: + +```sql +Select DateOfBirth From Customer Where CustomerId = @id +``` + +Before the query can be executed on SQL Server, the value for the Transact-SQL parameter must be specified. In this example, the `id` parameter value must first be translated from a CLR type to a SQL Server `INT` type so that the database can understand what the value is. Then to retrieve the results, the SQL Server `DateOfBirth` column must be translated from a SQL Server `DATETIME` type to a CLR type for use in the object model. In this example, the types in the CLR object model and SQL Server database have natural mappings. But, this is not always the case. + +### Missing Counterparts + +The following types do not have reasonable counterparts. + +- Mismatches in the CLR namespace: + + - **Unsigned integers**. These types are typically mapped to their signed counterparts of larger size to avoid overflow. Literals can be converted to a signed numeric of the same or smaller size, based on value. + + - **Boolean**. These types can be mapped to a bit or larger numeric or string. A literal can be mapped to an expression that evaluates to the same value (for example, `1=1` in SQL for `True` in CLS). + + - **TimeSpan**. This type represents the difference between two `DateTime` values and does not correspond to the `timestamp` of SQL Server. The CLR may also map to the SQL Server `TIME` type in some cases. The SQL Server `TIME` type was only intended to represent positive values less than 24 hours. The CLR has a much larger range. + + > [!NOTE] + > SQL Server-specific [!INCLUDE[dnprdnshort](../../../../../../includes/dnprdnshort-md.md)] types in are not included in this comparison. + +- Mismatches in SQL Server: + + - **Fixed length character types**. Transact-SQL distinguishes between Unicode and non-Unicode categories and has three distinct types in each category: fixed length `nchar`/`char`, variable length `nvarchar`/`varchar`, and larger-sized `ntext`/`text`. The fixed length character types could be mapped to the CLR type for retrieving characters, but they do not really correspond to the same type in conversions and behavior. + + - **Bit**. Although the `bit` domain has the same number of values as `Nullable`, the two are different types. `Bit` takes values `1` and `0` instead of `true`/`false`, and cannot be used as an equivalent to Boolean expressions. + + - **Timestamp**. Unlike the CLR type, the SQL Server `TIMESTAMP` type represents an 8-byte number generated by the database that is unique for each update and is not based on the difference between values. + + - **Money** and **SmallMoney**. These types can be mapped to but are basically different types and are treated as such by server-based functions and conversions. + +### Multiple Mappings + +There are many SQL Server data types that you can map to one or more CLR data types. There are also many CLR types that you can map to one or more SQL Server types. Although a mapping may be supported by LINQ to SQL, it does not mean that the two types mapped between the CLR and SQL Server are a perfect match in precision, range, and semantics. Some mappings may include differences in any or all of these dimensions. You can find details about these potential differences for the various mapping possibilities at [SQL-CLR Type Mapping](../../../../../../docs/framework/data/adonet/sql/linq/sql-clr-type-mapping.md). + +### User-defined Types + +User-defined CLR types are designed to help bridge the type system gap. Nevertheless they surface interesting issues about type versioning. A change in the version on the client might not be matched by a change in the type stored on the database server. Any such change causes another type mismatch where the type semantics might not match and the version gap is likely to become visible. Further complications occur as inheritance hierarchies are refactored in successive versions. + +## Expression Semantics + +In addition to the pairwise mismatch between CLR and database types, expressions add complexity to the mismatch. Mismatches in operator semantics, function semantics, implicit type conversion, and precedence rules must be considered. + +The following subsections illustrate the mismatch between apparently similar expressions. It might be possible to generate SQL expressions that are semantically equivalent to a given CLR expression. However, it is not clear whether the semantic differences between apparently similar expressions are evident to a CLR user, and therefore whether the changes that are required for semantic equivalence are intended or not. This is an especially critical issue when an expression is evaluated for a set of values. The visibility of the difference might depend on data- and be hard to identify during coding and debugging. + +### Null Semantics + +SQL expressions provide three-valued logic for Boolean expressions. The result can be true, false, or null. By contrast, CLR specifies two-valued Boolean result for comparisons involving null values. Consider the following code: + +[!code-csharp[DLinqMismatch#2](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqMismatch/cs/Program.cs#2)] +[!code-vb[DLinqMismatch#2](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqMismatch/vb/Module1.vb#2)] + +```sql +-- Assume col1 and col2 are integer columns with null values. +-- Assume that ANSI null behavior has not been explicitly +-- turned off. +Select … +From … +Where col1 = col2 +-- Evaluates to null, not true and the corresponding row is not +-- selected. +-- To obtain matching behavior (i -> col1, j -> col2) change +-- the query to the following: +Select … +From … +Where + col1 = col2 +or (col1 is null and col2 is null) +-- (Visual Basic 'Nothing'.) +``` + +A similar problem occurs with the assumption about two-valued results. + +[!code-csharp[DLinqMismatch#3](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqMismatch/cs/Program.cs#3)] +[!code-vb[DLinqMismatch#3](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqMismatch/vb/Module1.vb#3)] + +```sql +-- Assume col1 and col2 are nullable columns. +-- Assume that ANSI null behavior has not been explicitly +-- turned off. +Select … +From … +Where + col1 = col2 +or col1 != col2 +-- Visual Basic: col1 <> col2. + +-- Excludes the case where the boolean expression evaluates +-- to null. Therefore the where clause does not always +-- evaluate to true. +``` + +In the previous case, you can get equivalent behavior in generating SQL, but the translation might not accurately reflect your intention. + +[!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] does not impose C# `null` or Visual Basic `nothing` comparison semantics on SQL. Comparison operators are syntactically translated to their SQL equivalents. The semantics reflect SQL semantics as defined by server or connection settings. Two null values are considered unequal under default SQL Server settings (although you can change the settings to change the semantics). Regardless, [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] does not consider server settings in query translation. + +A comparison with the literal `null` (`nothing`) is translated to the appropriate SQL version (`is null` or `is not null`). + +The value of `null` (`nothing`) in collation is defined by SQL Server; [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] does not change the collation. + +### Type Conversion and Promotion + +SQL supports a rich set of implicit conversions in expressions. Similar expressions in C# would require an explicit cast. For example: + +- `Nvarchar` and `DateTime` types can be compared in SQL without any explicit casts; C# requires explicit conversion. + +- `Decimal` is implicitly converted to `DateTime` in SQL. C# does not allow for an implicit conversion. + +Likewise, type precedence in Transact-SQL differs from type precedence in C# because the underlying set of types is different. In fact, there is no clear subset/superset relationship between the precedence lists. For example, comparing an `nvarchar` with a `varchar` causes the implicit conversion of the `varchar` expression to `nvarchar`. The CLR provides no equivalent promotion. + +In simple cases, these differences cause CLR expressions with casts to be redundant for a corresponding SQL expression. More importantly, the intermediate results of a SQL expression might be implicitly promoted to a type that has no accurate counterpart in C#, and vice versa. Overall, the testing, debugging, and validation of such expressions adds significant burden on the user. + +### Collation + +Transact-SQL supports explicit collations as annotations to character string types. These collations determine the validity of certain comparisons. For example, comparing two columns with different explicit collations is an error. The use of much simplified CTS string type does not cause such errors. Consider the following example: + +```sql +create table T2 ( + Col1 nvarchar(10), + Col2 nvarchar(10) collate Latin_general_ci_as +) +``` + +[!code-csharp[DLinqMismatch#4](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqMismatch/cs/Program.cs#4)] +[!code-vb[DLinqMismatch#4](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqMismatch/vb/Module1.vb#4)] + +```sql +Select … +From … +Where Col1 = Col2 +-- Error, collation conflict. +``` + +In effect, the collation subclause creates a *restricted type* that is not substitutable. + +Similarly, the sort order can be significantly different across the type systems. This difference affects the sorting of results. is sorted on all 16 bytes by lexicographic order (`IComparable()`), whereas T-SQL compares GUIDs in the following order: node(10-15), clock-seq(8-9), time-high(6-7), time-mid(4-5), time-low(0-3). This ordering was done in SQL 7.0 when NT-generated GUIDs had such an octet order. The approach ensured that GUIDs generated at the same node cluster came together in sequential order according to timestamp. The approach was also useful for building indexes (inserts become appends instead of random IOs). The order was scrambled later in Windows because of privacy concerns, but SQL must maintain compatibility. A workaround is to use instead of . + +### Operator and Function Differences + +Operators and functions that are essentially comparable have subtly different semantics. For example: + +- C# specifies short circuit semantics based on lexical order of operands for logical operators `&&` and `||`. SQL on the other hand is targeted for set-based queries and therefore provides more freedom for the optimizer to decide the order of execution. Some of the implications include the following: + + - Semantically equivalent translation would require "`CASE` … `WHEN` … `THEN`" construct in SQL to avoid reordering of operand execution. + + - A loose translation to `AND`/`OR` operators could cause unexpected errors if the C# expression relies on evaluation the second operand being based on the result of the evaluation of the first operand. + +- `Round()` function has different semantics in [!INCLUDE[dnprdnshort](../../../../../../includes/dnprdnshort-md.md)] and in T-SQL. + +- Starting index for strings is 0 in the CLR but 1 in SQL. Therefore, any function that has index needs index translation. + +- The CLR supports modulus (‘%’) operator for floating point numbers but SQL does not. + +- The `Like` operator effectively acquires automatic overloads based on implicit conversions. Although the `Like` operator is defined to operate on character string types, implicit conversion from numeric types or `DateTime` types allows for those non-string types to be used with `Like` just as well. In CTS, comparable implicit conversions do not exist. Therefore, additional overloads are needed. + > [!NOTE] - > This `Like` operator behavior applies to C# only; the Visual Basic `Like` keyword is unchanged. - -- Overflow is always checked in SQL but it has to be explicitly specified in C# (not in Visual Basic) to avoid wraparound. Given integer columns C1, C2 and C3, if C1+C2 is stored in C3 (Update T Set C3 = C1 + C2). - - ``` - create table T3 ( - Col1 integer, - Col2 integer - ) - insert into T3 (col1, col2) values (2147483647, 5) - -- Valid values: max integer value and 5. - select * from T3 where col1 + col2 < 0 - -- Produces arithmetic overflow error. - ``` - - [!code-csharp[DLinqMismatch#5](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqMismatch/cs/Program.cs#5)] - [!code-vb[DLinqMismatch#5](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqMismatch/vb/Module1.vb#5)] - -- SQL performs symmetric arithmetic rounding while [!INCLUDE[dnprdnshort](../../../../../../includes/dnprdnshort-md.md)] uses banker’s rounding. See Knowledgebase article 196652 for additional details. - -- By default, for common locales, character-string comparisons are case-insensitive in SQL. In Visual Basic and in C#, they are case-sensitive. For example, `s == "Food"` (`s = "Food"` in Visual Basic) and `s == "Food"` can yield different results if `s` is `food`. - - ``` - -- Assume default US-English locale (case insensitive). - create table T4 ( - Col1 nvarchar (256) - ) - insert into T4 values (‘Food’) - insert into T4 values (‘FOOD’) - select * from T4 where Col1 = ‘food’ - -- Both the rows are returned because of case-insensitive matching. - ``` - - [!code-csharp[DLinqMismatch#6](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqMismatch/cs/Program.cs#6)] - [!code-vb[DLinqMismatch#6](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqMismatch/vb/Module1.vb#6)] - -- Operators/ functions applied to fixed length character type arguments in SQL have significantly different semantics than the same operators/functions applied to the CLR . This could also be viewed as an extension of the missing counterpart problem discussed in the section about types. - - ``` - create table T4 ( - Col1 nchar(4) - ) - Insert into T5(Col1) values ('21'); - Insert into T5(Col1) values ('1021'); - Select * from T5 where Col1 like '%1' - -- Only the second row with Col1 = '1021' is returned. - -- Not the first row! - ``` - + > This `Like` operator behavior applies to C# only; the Visual Basic `Like` keyword is unchanged. + +- Overflow is always checked in SQL but it has to be explicitly specified in C# (not in Visual Basic) to avoid wraparound. Given integer columns C1, C2 and C3, if C1+C2 is stored in C3 (Update T Set C3 = C1 + C2). + + ```sql + create table T3 ( + Col1 integer, + Col2 integer + ) + insert into T3 (col1, col2) values (2147483647, 5) + -- Valid values: max integer value and 5. + select * from T3 where col1 + col2 < 0 + -- Produces arithmetic overflow error. + ``` + +[!code-csharp[DLinqMismatch#5](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqMismatch/cs/Program.cs#5)] +[!code-vb[DLinqMismatch#5](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqMismatch/vb/Module1.vb#5)] + +- SQL performs symmetric arithmetic rounding while [!INCLUDE[dnprdnshort](../../../../../../includes/dnprdnshort-md.md)] uses banker’s rounding. See Knowledgebase article 196652 for additional details. + +- By default, for common locales, character-string comparisons are case-insensitive in SQL. In Visual Basic and in C#, they are case-sensitive. For example, `s == "Food"` (`s = "Food"` in Visual Basic) and `s == "Food"` can yield different results if `s` is `food`. + + ```sql + -- Assume default US-English locale (case insensitive). + create table T4 ( + Col1 nvarchar (256) + ) + insert into T4 values (‘Food’) + insert into T4 values (‘FOOD’) + select * from T4 where Col1 = ‘food’ + -- Both the rows are returned because of case-insensitive matching. + ``` + +[!code-csharp[DLinqMismatch#6](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqMismatch/cs/Program.cs#6)] +[!code-vb[DLinqMismatch#6](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqMismatch/vb/Module1.vb#6)] + +- Operators/ functions applied to fixed length character type arguments in SQL have significantly different semantics than the same operators/functions applied to the CLR . This could also be viewed as an extension of the missing counterpart problem discussed in the section about types. + + ```sql + create table T4 ( + Col1 nchar(4) + ) + Insert into T5(Col1) values ('21'); + Insert into T5(Col1) values ('1021'); + Select * from T5 where Col1 like '%1' + -- Only the second row with Col1 = '1021' is returned. + -- Not the first row! + ``` + [!code-csharp[DLinqMismatch#7](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqMismatch/cs/Program.cs#7)] - [!code-vb[DLinqMismatch#7](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqMismatch/vb/Module1.vb#7)] - - A similar problem occurs with string concatenation. - - ``` - create table T6 ( - Col1 nchar(4) - Col2 nchar(4) - ) - Insert into T6 values ('a', 'b'); - Select Col1+Col2 from T6 - -- Returns concatenation of padded strings "a b " and not "ab". - ``` - - In summary, a convoluted translation might be required for CLR expressions and additional operators/functions may be necessary to expose SQL functionality. - -### Type Casting - In C# and in SQL, users can override the default semantics of expressions by using explicit type casts (`Cast` and `Convert`). However, exposing this capability across the type system boundary poses a dilemma. A SQL cast that provides the desired semantics cannot be easily translated to a corresponding C# cast. On the other hand, a C# cast cannot be directly translated into an equivalent SQL cast because of type mismatches, missing counterparts, and different type precedence hierarchies. There is a trade-off between exposing the type system mismatch and losing significant power of expression. - - In other cases, type casting might not be needed in either domain for validation of an expression but might be required to make sure that a non-default mapping is correctly applied to the expression. - -``` --- Example from "Non-default Mapping" section extended -create table T5 ( - Col1 nvarchar(10), - Col2 nvarchar(10) -) -Insert into T5(col1, col2) values (‘3’, ‘2’); -``` - - [!code-csharp[DLinqMismatch#8](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqMismatch/cs/Program.cs#8)] - [!code-vb[DLinqMismatch#8](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqMismatch/vb/Module1.vb#8)] - -``` -Select * -From T5 -Where Col1 + Col2 > 4 --- "Col1 + Col2" expr evaluates to '32' -``` - -## Performance Issues - Accounting for some SQL Server-CLR type differences may result in a decrease in performance when crossing between the CLR and SQL Server type systems. Examples of scenarios impacting performance include the following: - -- Forced order of evaluation for logical and/or operators - -- Generating SQL to enforce order of predicate evaluation restricts the SQL optimizer’s ability. - -- Type conversions, whether introduced by a CLR compiler or by an Object-Relational query implementation, may curtail index usage. - - For example, - - ``` - -- Table DDL - create table T5 ( - Col1 varchar(100) - ) - ``` - + [!code-vb[DLinqMismatch#7](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqMismatch/vb/Module1.vb#7)] + + A similar problem occurs with string concatenation. + + ```sql + create table T6 ( + Col1 nchar(4) + Col2 nchar(4) + ) + Insert into T6 values ('a', 'b'); + Select Col1+Col2 from T6 + -- Returns concatenation of padded strings "a b " and not "ab". + ``` + +In summary, a convoluted translation might be required for CLR expressions and additional operators/functions may be necessary to expose SQL functionality. + +### Type Casting + +In C# and in SQL, users can override the default semantics of expressions by using explicit type casts (`Cast` and `Convert`). However, exposing this capability across the type system boundary poses a dilemma. A SQL cast that provides the desired semantics cannot be easily translated to a corresponding C# cast. On the other hand, a C# cast cannot be directly translated into an equivalent SQL cast because of type mismatches, missing counterparts, and different type precedence hierarchies. There is a trade-off between exposing the type system mismatch and losing significant power of expression. + +In other cases, type casting might not be needed in either domain for validation of an expression but might be required to make sure that a non-default mapping is correctly applied to the expression. + +```sql +-- Example from "Non-default Mapping" section extended +create table T5 ( + Col1 nvarchar(10), + Col2 nvarchar(10) +) +Insert into T5(col1, col2) values (‘3’, ‘2’); +``` + +[!code-csharp[DLinqMismatch#8](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqMismatch/cs/Program.cs#8)] +[!code-vb[DLinqMismatch#8](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqMismatch/vb/Module1.vb#8)] + +```sql +Select * +From T5 +Where Col1 + Col2 > 4 +-- "Col1 + Col2" expr evaluates to '32' +``` + +## Performance Issues + +Accounting for some SQL Server-CLR type differences may result in a decrease in performance when crossing between the CLR and SQL Server type systems. Examples of scenarios impacting performance include the following: + +- Forced order of evaluation for logical and/or operators + +- Generating SQL to enforce order of predicate evaluation restricts the SQL optimizer’s ability. + +- Type conversions, whether introduced by a CLR compiler or by an Object-Relational query implementation, may curtail index usage. + + For example, + + ```sql + -- Table DDL + create table T5 ( + Col1 varchar(100) + ) + ``` + [!code-csharp[DLinqMismatch#9](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqMismatch/cs/Program.cs#9)] - [!code-vb[DLinqMismatch#9](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqMismatch/vb/Module1.vb#9)] - - Consider the translation of expression `(s = SOME_STRING_CONSTANT)`. - - ``` - -- Corresponding part of SQL where clause - Where … - Col1 = SOME_STRING_CONSTANT - -- This expression is of the form = . - -- Hence SQL introduces a conversion from varchar to nvarchar, - -- resulting in - Where … - Convert(nvarchar(100), Col1) = SOME_STRING_CONSTANT - -- Cannot use the index for column Col1 for some implementations. - ``` - - In addition to semantic differences, it is important to consider impacts to performance when crossing between the SQL Server and CLR type systems. For large data sets, such performance issues can determine whether an application is deployable. - + [!code-vb[DLinqMismatch#9](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqMismatch/vb/Module1.vb#9)] + + Consider the translation of expression `(s = SOME_STRING_CONSTANT)`. + + ```sql + -- Corresponding part of SQL where clause + Where … + Col1 = SOME_STRING_CONSTANT + -- This expression is of the form = . + -- Hence SQL introduces a conversion from varchar to nvarchar, + -- resulting in + Where … + Convert(nvarchar(100), Col1) = SOME_STRING_CONSTANT + -- Cannot use the index for column Col1 for some implementations. + ``` + +In addition to semantic differences, it is important to consider impacts to performance when crossing between the SQL Server and CLR type systems. For large data sets, such performance issues can determine whether an application is deployable. + ## See also - [Background Information](../../../../../../docs/framework/data/adonet/sql/linq/background-information.md) diff --git a/docs/framework/data/adonet/sql/linq/standard-query-operator-translation.md b/docs/framework/data/adonet/sql/linq/standard-query-operator-translation.md index 88a3b88576641..b08780d2064a6 100644 --- a/docs/framework/data/adonet/sql/linq/standard-query-operator-translation.md +++ b/docs/framework/data/adonet/sql/linq/standard-query-operator-translation.md @@ -1,224 +1,245 @@ --- title: "Standard Query Operator Translation" ms.date: "03/30/2017" -dev_langs: +dev_langs: - "csharp" - "vb" ms.assetid: a60c30fa-1e68-45fe-b984-f6abb9ede40e --- # Standard Query Operator Translation -[!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] translates Standard Query Operators to SQL commands. The query processor of the database determines the execution semantics of SQL translation. - - Standard Query Operators are defined against *sequences*. A sequence is *ordered* and relies on reference identity for each element of the sequence. For more information, see [Standard Query Operators Overview (C#)](../../../../../csharp/programming-guide/concepts/linq/standard-query-operators-overview.md) or [Standard Query Operators Overview (Visual Basic)](../../../../../visual-basic/programming-guide/concepts/linq/standard-query-operators-overview.md). - - SQL deals primarily with *unordered sets of values*. Ordering is typically an explicitly stated, post-processing operation that is applied to the final result of a query rather than to intermediate results. Identity is defined by values. For this reason, SQL queries are understood to deal with multisets (*bags*) instead of *sets*. - - The following paragraphs describe the differences between the Standard Query Operators and their SQL translation for the SQL Server provider for [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)]. - -## Operator Support - -### Concat - The method is defined for ordered multisets where the order of the receiver and the order of the argument are the same. works as `UNION ALL` over the multisets followed by the common order. - - The final step is ordering in SQL before results are produced. does not preserve the order of its arguments. To ensure appropriate ordering, you must explicitly order the results of . - -### Intersect, Except, Union - The and methods are well defined only on sets. The semantics for multisets is undefined. - - The method is defined for multisets as the unordered concatenation of the multisets (effectively the result of the UNION ALL clause in SQL). - -### Take, Skip - and methods are well defined only against *ordered sets*. The semantics for unordered sets or multisets are undefined. - + +[!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] translates Standard Query Operators to SQL commands. The query processor of the database determines the execution semantics of SQL translation. + +Standard Query Operators are defined against *sequences*. A sequence is *ordered* and relies on reference identity for each element of the sequence. For more information, see [Standard Query Operators Overview (C#)](../../../../../csharp/programming-guide/concepts/linq/standard-query-operators-overview.md) or [Standard Query Operators Overview (Visual Basic)](../../../../../visual-basic/programming-guide/concepts/linq/standard-query-operators-overview.md). + +SQL deals primarily with *unordered sets of values*. Ordering is typically an explicitly stated, post-processing operation that is applied to the final result of a query rather than to intermediate results. Identity is defined by values. For this reason, SQL queries are understood to deal with multisets (*bags*) instead of *sets*. + +The following paragraphs describe the differences between the Standard Query Operators and their SQL translation for the SQL Server provider for [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)]. + +## Operator Support + +### Concat + +The method is defined for ordered multisets where the order of the receiver and the order of the argument are the same. works as `UNION ALL` over the multisets followed by the common order. + +The final step is ordering in SQL before results are produced. does not preserve the order of its arguments. To ensure appropriate ordering, you must explicitly order the results of . + +### Intersect, Except, Union + +The and methods are well defined only on sets. The semantics for multisets is undefined. + +The method is defined for multisets as the unordered concatenation of the multisets (effectively the result of the UNION ALL clause in SQL). + +### Take, Skip + + and methods are well defined only against *ordered sets*. The semantics for unordered sets or multisets are undefined. + > [!NOTE] -> and have certain limitations when they are used in queries against SQL Server 2000. For more information, see the "Skip and Take Exceptions in SQL Server 2000" entry in [Troubleshooting](../../../../../../docs/framework/data/adonet/sql/linq/troubleshooting.md). - - Because of limitations on ordering in SQL, [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] tries to move the ordering of the argument of these methods to the result of the method. For example, consider the following [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] query: - - [!code-csharp[DLinqSQOTranslation#1](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqSQOTranslation/cs/Program.cs#1)] - [!code-vb[DLinqSQOTranslation#1](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqSQOTranslation/vb/Module1.vb#1)] - - The generated SQL for this code moves the ordering to the end, as follows: - -``` -SELECT TOP 1 [t0].[CustomerID], [t0].[CompanyName], -FROM [Customers] AS [t0] -WHERE (NOT (EXISTS( - SELECT NULL AS [EMPTY] - FROM ( - SELECT TOP 1 [t1].[CustomerID] - FROM [Customers] AS [t1] - WHERE [t1].[City] = @p0 - ORDER BY [t1].[CustomerID] - ) AS [t2] - WHERE [t0].[CustomerID] = [t2].[CustomerID] - ))) AND ([t0].[City] = @p1) -ORDER BY [t0].[CustomerID] -``` - - It becomes obvious that all the specified ordering must be consistent when and are chained together. Otherwise, the results are undefined. - - Both and are well-defined for non-negative, constant integral arguments based on the Standard Query Operator specification. - -### Operators with No Translation - The following methods are not translated by [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)]. The most common reason is the difference between unordered multisets and sequences. - -|Operators|Rationale| -|---------------|---------------| -|, |SQL queries operate on multisets, not on sequences. `ORDER BY` must be the last clause applied to the results. For this reason, there is no general-purpose translation for these two methods.| -||Translation of this method is possible for an ordered set but is not currently translated by [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)].| -|, |Translation of these methods is possible for an ordered set but is not currently translated by [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)].| -|, |SQL queries operate on multisets, not on indexable sequences.| -| (overload with default arg)|In general, a default value cannot be specified for an arbitrary tuple. Null values for tuples are possible in some cases through outer joins.| - -## Expression Translation - -### Null semantics - [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] does not impose null comparison semantics on SQL. Comparison operators are syntactically translated to their SQL equivalents. For this reason, the semantics reflect SQL semantics that are defined by server or connection settings. For example, two null values are considered unequal under default SQL Server settings, but you can change the settings to change the semantics. [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] does not consider server settings when it translates queries. - - A comparison with the literal null is translated to the appropriate SQL version (`is null` or `is not null`). - - The value of `null` in collation is defined by SQL Server. [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] does not change the collation. - -### Aggregates - The Standard Query Operator aggregate method evaluates to zero for an empty sequence or for a sequence that contains only nulls. In [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)], the semantics of SQL are left unchanged, and evaluates to `null` instead of zero for an empty sequence or for a sequence that contains only nulls. - - SQL limitations on intermediate results apply to aggregates in [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)]. The of 32-bit integer quantities is not computed by using 64-bit results. Overflow might occur for a [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] translation of , even if the Standard Query Operator implementation does not cause an overflow for the corresponding in-memory sequence. - - Likewise, the [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] translation of of integer values is computed as an `integer`, not as a `double`. - -### Entity Arguments - [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] enables entity types to be used in the and methods. In the translation of these operators, the use of an argument of a type is considered to be the equivalent to specifying all members of that type. For example, the following code is equivalent: - - [!code-csharp[DLinqSQOTranslation#2](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqSQOTranslation/cs/Program.cs#2)] - [!code-vb[DLinqSQOTranslation#2](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqSQOTranslation/vb/Module1.vb#2)] - -### Equatable / Comparable Arguments - Equality of arguments is required in the implementation of the following methods: - - - - - - - - - - - - [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] supports equality and comparison for *flat* arguments, but not for arguments that are or contain sequences. A flat argument is a type that can be mapped to a SQL row. A projection of one or more entity types that can be statically determined not to contain a sequence is considered a flat argument. - - Following are examples of flat arguments: - - [!code-csharp[DLinqSQOTranslation#3](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqSQOTranslation/cs/Program.cs#3)] - [!code-vb[DLinqSQOTranslation#3](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqSQOTranslation/vb/Module1.vb#3)] - - The following are examples of non-flat (hierarchical) arguments. - - [!code-csharp[DLinqSQOTranslation#4](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqSQOTranslation/cs/Program.cs#4)] - [!code-vb[DLinqSQOTranslation#4](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqSQOTranslation/vb/Module1.vb#4)] - -### Visual Basic Function Translation - The following helper functions that are used by the Visual Basic compiler are translated to corresponding SQL operators and functions: - - `CompareString` - - `DateTime.Compare` - - `Decimal.Compare` - - `IIf (in Microsoft.VisualBasic.Interaction)` - - Conversion methods: - -||||| -|-|-|-|-| -|ToBoolean|ToSByte|ToByte|ToChar| -|ToCharArrayRankOne|ToDate|ToDecimal|ToDouble| -|ToInteger|ToUInteger|ToLong|ToULong| -|ToShort|ToUShort|ToSingle|ToString| - -## Inheritance Support - -### Inheritance Mapping Restrictions - For more information, see [How to: Map Inheritance Hierarchies](../../../../../../docs/framework/data/adonet/sql/linq/how-to-map-inheritance-hierarchies.md). - -### Inheritance in Queries - C# casts are supported only in projection. Casts that are used elsewhere are not translated and are ignored. Aside from SQL function names, SQL really only performs the equivalent of the common language runtime (CLR) . That is, SQL can change the value of one type to another. There is no equivalent of CLR cast because there is no concept of reinterpreting the same bits as those of another type. That is why a C# cast works only locally. It is not remoted. - - The operators, `is` and `as`, and the `GetType` method are not restricted to the `Select` operator. They can be used in other query operators also. - -## SQL Server 2008 Support - Starting with the .NET Framework 3.5 SP1, LINQ to SQL supports mapping to new date and time types introduced with SQL Server 2008. But, there are some limitations to the LINQ to SQL query operators that you can use when operating against values mapped to these new types. - -### Unsupported Query Operators - The following query operators are not supported on values mapped to the new SQL Server date and time types: `DATETIME2`, `DATE`, `TIME`, and `DATETIMEOFFSET`. - -- `Aggregate` - -- `Average` - -- `LastOrDefault` - -- `OfType` - -- `Sum` - - For more information about mapping to these SQL Server date and time types, see [SQL-CLR Type Mapping](../../../../../../docs/framework/data/adonet/sql/linq/sql-clr-type-mapping.md). - -## SQL Server 2005 Support - [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] does not support the following SQL Server 2005 features: - -- Stored procedures written for SQL CLR. - -- User-defined type. - -- XML query features. - -## SQL Server 2000 Support - The following [!INCLUDE[ss2k](../../../../../../includes/ss2k-md.md)] limitations (compared to [!INCLUDE[sqprsqext](../../../../../../includes/sqprsqext-md.md)]) affect [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] support. - -### Cross Apply and Outer Apply Operators - These operators are not available in [!INCLUDE[ss2k](../../../../../../includes/ss2k-md.md)]. [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] tries a series of rewrites to replace them with appropriate joins. - - `Cross Apply` and `Outer Apply` are generated for relationship navigations. The set of queries for which such rewrites are possible is not well defined. For this reason, the minimal set of queries that is supported for [!INCLUDE[ss2k](../../../../../../includes/ss2k-md.md)] is the set that does not involve relationship navigation. - -### text / ntext - Data types `text` / `ntext` cannot be used in certain query operations against `varchar(max)` / `nvarchar(max)`, which are supported by [!INCLUDE[sqprsqext](../../../../../../includes/sqprsqext-md.md)]. - - No resolution is available for this limitation. Specifically, you cannot use `Distinct()` on any result that contains members that are mapped to `text` or `ntext` columns. - -### Behavior Triggered by Nested Queries - [!INCLUDE[ss2k](../../../../../../includes/ss2k-md.md)] (through SP4) binder has some idiosyncrasies that are triggered by nested queries. The set of SQL queries that triggers these idiosyncrasies is not well defined. For this reason, you cannot define the set of [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] queries that might cause SQL Server exceptions. - -### Skip and Take Operators - and have certain limitations when they are used in queries against [!INCLUDE[ss2k](../../../../../../includes/ss2k-md.md)]. For more information, see the "Skip and Take Exceptions in SQL Server 2000" entry in [Troubleshooting](../../../../../../docs/framework/data/adonet/sql/linq/troubleshooting.md). - -## Object Materialization - Materialization creates CLR objects from rows that are returned by one or more SQL queries. - -- The following calls are *executed locally* as a part of materialization: - - - Constructors - - - `ToString` methods in projections - - - Type casts in projections - -- Methods that follow the method are *executed locally*. This method does not cause immediate execution. - -- You can use a `struct` as the return type of a query result or as a member of the result type. Entities are required to be classes. Anonymous types are materialized as class instances, but named structs (non-entities) can be used in projection. - -- A member of the return type of a query result can be of type . It is materialized as a local collection. - -- The following methods cause the *immediate materialization* of the sequence that the methods are applied to: - - - - - - - - - - +> and have certain limitations when they are used in queries against SQL Server 2000. For more information, see the "Skip and Take Exceptions in SQL Server 2000" entry in [Troubleshooting](../../../../../../docs/framework/data/adonet/sql/linq/troubleshooting.md). + +Because of limitations on ordering in SQL, [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] tries to move the ordering of the argument of these methods to the result of the method. For example, consider the following [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] query: + +[!code-csharp[DLinqSQOTranslation#1](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqSQOTranslation/cs/Program.cs#1)] +[!code-vb[DLinqSQOTranslation#1](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqSQOTranslation/vb/Module1.vb#1)] + +The generated SQL for this code moves the ordering to the end, as follows: + +```sql +SELECT TOP 1 [t0].[CustomerID], [t0].[CompanyName], +FROM [Customers] AS [t0] +WHERE (NOT (EXISTS( + SELECT NULL AS [EMPTY] + FROM ( + SELECT TOP 1 [t1].[CustomerID] + FROM [Customers] AS [t1] + WHERE [t1].[City] = @p0 + ORDER BY [t1].[CustomerID] + ) AS [t2] + WHERE [t0].[CustomerID] = [t2].[CustomerID] + ))) AND ([t0].[City] = @p1) +ORDER BY [t0].[CustomerID] +``` + +It becomes obvious that all the specified ordering must be consistent when and are chained together. Otherwise, the results are undefined. + +Both and are well-defined for non-negative, constant integral arguments based on the Standard Query Operator specification. + +### Operators with No Translation + +The following methods are not translated by [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)]. The most common reason is the difference between unordered multisets and sequences. + +|Operators|Rationale| +|---------------|---------------| +|, |SQL queries operate on multisets, not on sequences. `ORDER BY` must be the last clause applied to the results. For this reason, there is no general-purpose translation for these two methods.| +||Translation of this method is possible for an ordered set but is not currently translated by [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)].| +|, |Translation of these methods is possible for an ordered set but is not currently translated by [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)].| +|, |SQL queries operate on multisets, not on indexable sequences.| +| (overload with default arg)|In general, a default value cannot be specified for an arbitrary tuple. Null values for tuples are possible in some cases through outer joins.| + +## Expression Translation + +### Null semantics + +[!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] does not impose null comparison semantics on SQL. Comparison operators are syntactically translated to their SQL equivalents. For this reason, the semantics reflect SQL semantics that are defined by server or connection settings. For example, two null values are considered unequal under default SQL Server settings, but you can change the settings to change the semantics. [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] does not consider server settings when it translates queries. + +A comparison with the literal null is translated to the appropriate SQL version (`is null` or `is not null`). + +The value of `null` in collation is defined by SQL Server. [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] does not change the collation. + +### Aggregates + +The Standard Query Operator aggregate method evaluates to zero for an empty sequence or for a sequence that contains only nulls. In [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)], the semantics of SQL are left unchanged, and evaluates to `null` instead of zero for an empty sequence or for a sequence that contains only nulls. + +SQL limitations on intermediate results apply to aggregates in [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)]. The of 32-bit integer quantities is not computed by using 64-bit results. Overflow might occur for a [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] translation of , even if the Standard Query Operator implementation does not cause an overflow for the corresponding in-memory sequence. + +Likewise, the [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] translation of of integer values is computed as an `integer`, not as a `double`. + +### Entity Arguments + +[!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] enables entity types to be used in the and methods. In the translation of these operators, the use of an argument of a type is considered to be the equivalent to specifying all members of that type. For example, the following code is equivalent: + +[!code-csharp[DLinqSQOTranslation#2](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqSQOTranslation/cs/Program.cs#2)] +[!code-vb[DLinqSQOTranslation#2](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqSQOTranslation/vb/Module1.vb#2)] + +### Equatable / Comparable Arguments + +Equality of arguments is required in the implementation of the following methods: + +- + +- + +- + +- + +- + +[!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] supports equality and comparison for *flat* arguments, but not for arguments that are or contain sequences. A flat argument is a type that can be mapped to a SQL row. A projection of one or more entity types that can be statically determined not to contain a sequence is considered a flat argument. + +Following are examples of flat arguments: + +[!code-csharp[DLinqSQOTranslation#3](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqSQOTranslation/cs/Program.cs#3)] +[!code-vb[DLinqSQOTranslation#3](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqSQOTranslation/vb/Module1.vb#3)] + +The following are examples of non-flat (hierarchical) arguments. + +[!code-csharp[DLinqSQOTranslation#4](../../../../../../samples/snippets/csharp/VS_Snippets_Data/DLinqSQOTranslation/cs/Program.cs#4)] +[!code-vb[DLinqSQOTranslation#4](../../../../../../samples/snippets/visualbasic/VS_Snippets_Data/DLinqSQOTranslation/vb/Module1.vb#4)] + +### Visual Basic Function Translation + +The following helper functions that are used by the Visual Basic compiler are translated to corresponding SQL operators and functions: + +- `CompareString` + +- `DateTime.Compare` + +- `Decimal.Compare` + +- `IIf (in Microsoft.VisualBasic.Interaction)` + +Conversion methods: + +||||| +|-|-|-|-| +|ToBoolean|ToSByte|ToByte|ToChar| +|ToCharArrayRankOne|ToDate|ToDecimal|ToDouble| +|ToInteger|ToUInteger|ToLong|ToULong| +|ToShort|ToUShort|ToSingle|ToString| + +## Inheritance Support + +### Inheritance Mapping Restrictions + +For more information, see [How to: Map Inheritance Hierarchies](../../../../../../docs/framework/data/adonet/sql/linq/how-to-map-inheritance-hierarchies.md). + +### Inheritance in Queries + +C# casts are supported only in projection. Casts that are used elsewhere are not translated and are ignored. Aside from SQL function names, SQL really only performs the equivalent of the common language runtime (CLR) . That is, SQL can change the value of one type to another. There is no equivalent of CLR cast because there is no concept of reinterpreting the same bits as those of another type. That is why a C# cast works only locally. It is not remoted. + +The operators, `is` and `as`, and the `GetType` method are not restricted to the `Select` operator. They can be used in other query operators also. + +## SQL Server 2008 Support + +Starting with the .NET Framework 3.5 SP1, LINQ to SQL supports mapping to new date and time types introduced with SQL Server 2008. But, there are some limitations to the LINQ to SQL query operators that you can use when operating against values mapped to these new types. + +### Unsupported Query Operators + +The following query operators are not supported on values mapped to the new SQL Server date and time types: `DATETIME2`, `DATE`, `TIME`, and `DATETIMEOFFSET`. + +- `Aggregate` + +- `Average` + +- `LastOrDefault` + +- `OfType` + +- `Sum` + +For more information about mapping to these SQL Server date and time types, see [SQL-CLR Type Mapping](../../../../../../docs/framework/data/adonet/sql/linq/sql-clr-type-mapping.md). + +## SQL Server 2005 Support + +[!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] does not support the following SQL Server 2005 features: + +- Stored procedures written for SQL CLR. + +- User-defined type. + +- XML query features. + +## SQL Server 2000 Support + +The following [!INCLUDE[ss2k](../../../../../../includes/ss2k-md.md)] limitations (compared to [!INCLUDE[sqprsqext](../../../../../../includes/sqprsqext-md.md)]) affect [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] support. + +### Cross Apply and Outer Apply Operators + +These operators are not available in [!INCLUDE[ss2k](../../../../../../includes/ss2k-md.md)]. [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] tries a series of rewrites to replace them with appropriate joins. + +`Cross Apply` and `Outer Apply` are generated for relationship navigations. The set of queries for which such rewrites are possible is not well defined. For this reason, the minimal set of queries that is supported for [!INCLUDE[ss2k](../../../../../../includes/ss2k-md.md)] is the set that does not involve relationship navigation. + +### text / ntext + +Data types `text` / `ntext` cannot be used in certain query operations against `varchar(max)` / `nvarchar(max)`, which are supported by [!INCLUDE[sqprsqext](../../../../../../includes/sqprsqext-md.md)]. + +No resolution is available for this limitation. Specifically, you cannot use `Distinct()` on any result that contains members that are mapped to `text` or `ntext` columns. + +### Behavior Triggered by Nested Queries + +[!INCLUDE[ss2k](../../../../../../includes/ss2k-md.md)] (through SP4) binder has some idiosyncrasies that are triggered by nested queries. The set of SQL queries that triggers these idiosyncrasies is not well defined. For this reason, you cannot define the set of [!INCLUDE[vbtecdlinq](../../../../../../includes/vbtecdlinq-md.md)] queries that might cause SQL Server exceptions. + +### Skip and Take Operators + + and have certain limitations when they are used in queries against [!INCLUDE[ss2k](../../../../../../includes/ss2k-md.md)]. For more information, see the "Skip and Take Exceptions in SQL Server 2000" entry in [Troubleshooting](../../../../../../docs/framework/data/adonet/sql/linq/troubleshooting.md). + +## Object Materialization + +Materialization creates CLR objects from rows that are returned by one or more SQL queries. + +- The following calls are *executed locally* as a part of materialization: + + - Constructors + + - `ToString` methods in projections + + - Type casts in projections + +- Methods that follow the method are *executed locally*. This method does not cause immediate execution. + +- You can use a `struct` as the return type of a query result or as a member of the result type. Entities are required to be classes. Anonymous types are materialized as class instances, but named structs (non-entities) can be used in projection. + +- A member of the return type of a query result can be of type . It is materialized as a local collection. + +- The following methods cause the *immediate materialization* of the sequence that the methods are applied to: + + - + + - + + - + ## See also - [Reference](../../../../../../docs/framework/data/adonet/sql/linq/reference.md) diff --git a/docs/framework/data/adonet/whats-new.md b/docs/framework/data/adonet/whats-new.md index 6458aa41cba0b..32b06b6894b35 100644 --- a/docs/framework/data/adonet/whats-new.md +++ b/docs/framework/data/adonet/whats-new.md @@ -4,46 +4,49 @@ ms.date: "03/30/2017" ms.assetid: 3bb65d38-cce2-46f5-b979-e5c505e95e10 --- # What's New in ADO.NET -The following features are new in [!INCLUDE[vstecado](../../../../includes/vstecado-md.md)] in the [!INCLUDE[net_v45](../../../../includes/net-v45-md.md)]. - -## SqlClient Data Provider - The following features are new in the [!INCLUDE[dnprdnshort](../../../../includes/dnprdnshort-md.md)] Data Provider for SQL Server in [!INCLUDE[net_v45](../../../../includes/net-v45-md.md)]: - -- The ConnectRetryCount and ConnectRetryInterval connection string keywords () let you control the idle connection resiliency feature. - -- Streaming support from SQL Server to an application supports scenarios where data on the server is unstructured. See [SqlClient Streaming Support](../../../../docs/framework/data/adonet/sqlclient-streaming-support.md) for more information. - -- Support has been added for asynchronous programming. See [Asynchronous Programming](../../../../docs/framework/data/adonet/asynchronous-programming.md) for more information. - -- Connection failures will now be logged in the extended events log. For more information, see [Data Tracing in ADO.NET](../../../../docs/framework/data/adonet/data-tracing.md). - -- SqlClient now has support for SQL Server's high availability, disaster recovery feature, AlwaysOn. For more information, see [SqlClient Support for High Availability, Disaster Recovery](../../../../docs/framework/data/adonet/sql/sqlclient-support-for-high-availability-disaster-recovery.md). - -- A password can be passed as a when using SQL Server Authentication. See for more information. - -- When `TrustServerCertificate` is false and `Encrypt` is true, the server name (or IP address) in a SQL Server SSL certificate must exactly match the server name (or IP address) specified in the connection string. Otherwise, the connection attempt will fail. For more information, see the description of the `Encrypt` connection option in . - - If this change causes an existing application to no longer connect, you can fix the application using one of the following: - - - Issue a certificate that specifies the short name in the Common Name (CN) or Subject Alternative Name (SAN) field. This solution will work for database mirroring. - - - Add an alias that maps the short name to the fully-qualified domain name. - - - Use the fully-qualified domain name in the connection string. - -- SqlClient supports Extended Protection. For more information about Extended Protection, see [Connecting to the Database Engine Using Extended Protection](https://go.microsoft.com/fwlink/?LinkId=219978). - -- SqlClient supports connections to LocalDB databases. For more information, see [SqlClient Support for LocalDB](../../../../docs/framework/data/adonet/sql/sqlclient-support-for-localdb.md). - -- `Type System Version=SQL Server 2012;` is new value to pass to the `Type System Version` connection property. The `Type System Version=Latest;` value is now obsolete and has been made equivalent to `Type System Version=SQL Server 2008;`. For more information, see . - -- SqlClient provides additional support for sparse columns, a feature that was added in SQL Server 2008. If your application already accesses data in a table that uses sparse columns, you should see an increase in performance. The IsColumnSet column of indicates if a column is a sparse column that is a member of a column set. indicates if a column is a sparse column (see [SQL Server Schema Collections](../../../../docs/framework/data/adonet/sql-server-schema-collections.md) for more information). For more information about sparse columns, see [Using Sparse Columns](https://go.microsoft.com/fwlink/?LinkId=224244). - -- The assembly Microsoft.SqlServer.Types.dll, which contains the spatial data types, has been upgraded from version 10.0 to version 11.0. Applications that reference this assembly may fail. For more information, see [Breaking Changes to Database Engine Features](https://go.microsoft.com/fwlink/?LinkId=224367). - -## ADO.NET Entity Framework - The [!INCLUDE[net_v45](../../../../includes/net-v45-md.md)] adds APIs that enable new scenarios when working with the Entity Framework 5.0. For more information about improvements and features that were added to the Entity Framework 5.0, see the following topics: [What’s New](https://go.microsoft.com/fwlink/?LinkID=251106) and [Entity Framework Releases and Versioning](https://go.microsoft.com/fwlink/?LinkId=234899). - + +The following features are new in [!INCLUDE[vstecado](../../../../includes/vstecado-md.md)] in the [!INCLUDE[net_v45](../../../../includes/net-v45-md.md)]. + +## SqlClient Data Provider + +The following features are new in the [!INCLUDE[dnprdnshort](../../../../includes/dnprdnshort-md.md)] Data Provider for SQL Server in [!INCLUDE[net_v45](../../../../includes/net-v45-md.md)]: + +- The ConnectRetryCount and ConnectRetryInterval connection string keywords () let you control the idle connection resiliency feature. + +- Streaming support from SQL Server to an application supports scenarios where data on the server is unstructured. See [SqlClient Streaming Support](../../../../docs/framework/data/adonet/sqlclient-streaming-support.md) for more information. + +- Support has been added for asynchronous programming. See [Asynchronous Programming](../../../../docs/framework/data/adonet/asynchronous-programming.md) for more information. + +- Connection failures will now be logged in the extended events log. For more information, see [Data Tracing in ADO.NET](../../../../docs/framework/data/adonet/data-tracing.md). + +- SqlClient now has support for SQL Server's high availability, disaster recovery feature, AlwaysOn. For more information, see [SqlClient Support for High Availability, Disaster Recovery](../../../../docs/framework/data/adonet/sql/sqlclient-support-for-high-availability-disaster-recovery.md). + +- A password can be passed as a when using SQL Server Authentication. See for more information. + +- When `TrustServerCertificate` is false and `Encrypt` is true, the server name (or IP address) in a SQL Server SSL certificate must exactly match the server name (or IP address) specified in the connection string. Otherwise, the connection attempt will fail. For more information, see the description of the `Encrypt` connection option in . + + If this change causes an existing application to no longer connect, you can fix the application using one of the following: + + - Issue a certificate that specifies the short name in the Common Name (CN) or Subject Alternative Name (SAN) field. This solution will work for database mirroring. + + - Add an alias that maps the short name to the fully-qualified domain name. + + - Use the fully-qualified domain name in the connection string. + +- SqlClient supports Extended Protection. For more information about Extended Protection, see [Connecting to the Database Engine Using Extended Protection](https://go.microsoft.com/fwlink/?LinkId=219978). + +- SqlClient supports connections to LocalDB databases. For more information, see [SqlClient Support for LocalDB](../../../../docs/framework/data/adonet/sql/sqlclient-support-for-localdb.md). + +- `Type System Version=SQL Server 2012;` is new value to pass to the `Type System Version` connection property. The `Type System Version=Latest;` value is now obsolete and has been made equivalent to `Type System Version=SQL Server 2008;`. For more information, see . + +- SqlClient provides additional support for sparse columns, a feature that was added in SQL Server 2008. If your application already accesses data in a table that uses sparse columns, you should see an increase in performance. The IsColumnSet column of indicates if a column is a sparse column that is a member of a column set. indicates if a column is a sparse column (see [SQL Server Schema Collections](../../../../docs/framework/data/adonet/sql-server-schema-collections.md) for more information). For more information about sparse columns, see [Using Sparse Columns](https://go.microsoft.com/fwlink/?LinkId=224244). + +- The assembly Microsoft.SqlServer.Types.dll, which contains the spatial data types, has been upgraded from version 10.0 to version 11.0. Applications that reference this assembly may fail. For more information, see [Breaking Changes to Database Engine Features](https://go.microsoft.com/fwlink/?LinkId=224367). + +## ADO.NET Entity Framework + +The [!INCLUDE[net_v45](../../../../includes/net-v45-md.md)] adds APIs that enable new scenarios when working with the Entity Framework 5.0. For more information about improvements and features that were added to the Entity Framework 5.0, see the following topics: [What’s New](https://go.microsoft.com/fwlink/?LinkID=251106) and [Entity Framework Releases and Versioning](https://go.microsoft.com/fwlink/?LinkId=234899). + ## See also - [ADO.NET](../../../../docs/framework/data/adonet/index.md) diff --git a/docs/framework/data/wcf/how-to-define-a-service-operation-wcf-data-services.md b/docs/framework/data/wcf/how-to-define-a-service-operation-wcf-data-services.md index b87b408d4ca38..542e0e677dbce 100644 --- a/docs/framework/data/wcf/how-to-define-a-service-operation-wcf-data-services.md +++ b/docs/framework/data/wcf/how-to-define-a-service-operation-wcf-data-services.md @@ -1,52 +1,54 @@ --- title: "How to: Define a Service Operation (WCF Data Services)" ms.date: "03/30/2017" -dev_langs: +dev_langs: - "csharp" - "vb" -helpviewer_keywords: +helpviewer_keywords: - "Service Operations [WCF Data Services]" - "WCF Data Services, service operations" ms.assetid: dfcd3cb1-2f07-4d0b-b16a-6b056c4f45fa --- # How to: Define a Service Operation (WCF Data Services) -[!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] expose methods that are defined on the server as service operations. Service operations allow a data service to provide access through a URI to a method that is defined on the server. To define a service operation, apply the [`WebGet]` or `[WebInvoke]` attribute to the method. To support query operators, the service operation must return an instance. Service operations may access the underlying data source through the property on the . For more information, see [Service Operations](../../../../docs/framework/data/wcf/service-operations-wcf-data-services.md). - - The example in this topic defines a service operation named `GetOrdersByCity` that returns a filtered instance of `Orders` and related `Order_Details` objects. The example accesses the instance that is the data source for the Northwind sample data service. This service is created when you complete the [WCF Data Services quickstart](../../../../docs/framework/data/wcf/quickstart-wcf-data-services.md). - -### To define a service operation in the Northwind data service - -1. In the Northwind data service project, open the Northwind.svc file. - -2. In the `Northwind` class, define a service operation method named `GetOrdersByCity` as follows: - + +[!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] expose methods that are defined on the server as service operations. Service operations allow a data service to provide access through a URI to a method that is defined on the server. To define a service operation, apply the [`WebGet]` or `[WebInvoke]` attribute to the method. To support query operators, the service operation must return an instance. Service operations may access the underlying data source through the property on the . For more information, see [Service Operations](../../../../docs/framework/data/wcf/service-operations-wcf-data-services.md). + +The example in this topic defines a service operation named `GetOrdersByCity` that returns a filtered instance of `Orders` and related `Order_Details` objects. The example accesses the instance that is the data source for the Northwind sample data service. This service is created when you complete the [WCF Data Services quickstart](../../../../docs/framework/data/wcf/quickstart-wcf-data-services.md). + +### To define a service operation in the Northwind data service + +1. In the Northwind data service project, open the Northwind.svc file. + +2. In the `Northwind` class, define a service operation method named `GetOrdersByCity` as follows: + [!code-csharp[Astoria Northwind Service#ServiceOperationDef](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_service/cs/northwind2.svc.cs#serviceoperationdef)] - [!code-vb[Astoria Northwind Service#ServiceOperationDef](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_service/vb/northwind2.svc.vb#serviceoperationdef)] - -3. In the `InitializeService` method of the `Northwind` class, add the following code to enable access to the service operation: - + [!code-vb[Astoria Northwind Service#ServiceOperationDef](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_service/vb/northwind2.svc.vb#serviceoperationdef)] + +3. In the `InitializeService` method of the `Northwind` class, add the following code to enable access to the service operation: + [!code-csharp[Astoria Northwind Service#ServiceOperationConfig](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_service/cs/northwind2.svc.cs#serviceoperationconfig)] - [!code-vb[Astoria Northwind Service#ServiceOperationConfig](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_service/vb/northwind2.svc.vb#serviceoperationconfig)] - -### To query the GetOrdersByCity service operation - -- In a Web browser, enter one of the following URIs to invoke the service operation that is defined in the following example: - - - `http://localhost:12345/Northwind.svc/GetOrdersByCity?city='London'` - - - `http://localhost:12345/Northwind.svc/GetOrdersByCity?city='London'&$top=2` - - - `http://localhost:12345/Northwind.svc/GetOrdersByCity?city='London'&$expand=Order_Details&$orderby=RequiredDate desc` - -## Example - The following example implements a service operation named `GetOrderByCity` on the Northwind data service. This operation uses the ADO.NET Entity Framework to return a set of `Orders` and related `Order_Details` objects as an instance based on the provided city name. - + [!code-vb[Astoria Northwind Service#ServiceOperationConfig](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_service/vb/northwind2.svc.vb#serviceoperationconfig)] + +### To query the GetOrdersByCity service operation + +- In a Web browser, enter one of the following URIs to invoke the service operation that is defined in the following example: + + - `http://localhost:12345/Northwind.svc/GetOrdersByCity?city='London'` + + - `http://localhost:12345/Northwind.svc/GetOrdersByCity?city='London'&$top=2` + + - `http://localhost:12345/Northwind.svc/GetOrdersByCity?city='London'&$expand=Order_Details&$orderby=RequiredDate desc` + +## Example + +The following example implements a service operation named `GetOrderByCity` on the Northwind data service. This operation uses the ADO.NET Entity Framework to return a set of `Orders` and related `Order_Details` objects as an instance based on the provided city name. + > [!NOTE] -> Query operators are supported on this service operation endpoint because the method returns an instance. - - [!code-csharp[Astoria Northwind Service#ServiceOperation](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_service/cs/northwind2.svc.cs#serviceoperation)] - [!code-vb[Astoria Northwind Service#ServiceOperation](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_service/vb/northwind2.svc.vb#serviceoperation)] - +> Query operators are supported on this service operation endpoint because the method returns an instance. + +[!code-csharp[Astoria Northwind Service#ServiceOperation](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_service/cs/northwind2.svc.cs#serviceoperation)] +[!code-vb[Astoria Northwind Service#ServiceOperation](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_service/vb/northwind2.svc.vb#serviceoperation)] + ## See also - [Defining WCF Data Services](../../../../docs/framework/data/wcf/defining-wcf-data-services.md) diff --git a/docs/framework/data/wcf/querying-the-data-service-wcf-data-services.md b/docs/framework/data/wcf/querying-the-data-service-wcf-data-services.md index 4217cc5560410..d048a2a3e2a97 100644 --- a/docs/framework/data/wcf/querying-the-data-service-wcf-data-services.md +++ b/docs/framework/data/wcf/querying-the-data-service-wcf-data-services.md @@ -1,141 +1,150 @@ --- title: "Querying the Data Service (WCF Data Services)" ms.date: "03/30/2017" -dev_langs: +dev_langs: - "csharp" - "vb" -helpviewer_keywords: +helpviewer_keywords: - "WCF Data Services, client library" - "WCF Data Services, querying" - "WCF Data Services, accessing data" ms.assetid: 823e9444-27aa-4f1f-be8e-0486d67f54c0 --- # Querying the Data Service (WCF Data Services) -The [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] client library enables you to execute queries against a data service by using familiar [!INCLUDE[dnprdnshort](../../../../includes/dnprdnshort-md.md)] programming patterns, including using language integrated query (LINQ). The client library translates a query, which is defined on the client as an instance of the class, into an HTTP GET request message. The library receives the response message and translates it into instances of client data service classes. These classes are tracked by the to which the belongs. - -## Data Service Queries - The generic class represents a query that returns a collection of zero or more entity type instances. A data service query always belongs to an existing data service context. This context maintains the service URI and metadata information that is required to compose and execute the query. - - When you use the **Add Service Reference** dialog to add a data service to a [!INCLUDE[dnprdnshort](../../../../includes/dnprdnshort-md.md)]-based client application, an entity container class is created that inherits from the class. This class includes properties that return typed instances. There is one property for each entity set that the data service exposes. These properties make it easier to create an instance of a typed . - - A query is executed in the following scenarios: - -- When results are enumerated implicitly, such as: - - - When a property on the that represents and entity set is enumerated, such as during a `foreach` (C#) or `For Each` (Visual Basic) loop. - - - When the query is assigned to a `List` collection. - -- When the or method is explicitly called. - -- When a LINQ query execution operator, such as or is called. - - The following query, when it is executed, returns all `Customers` entities in the Northwind data service: - - [!code-csharp[Astoria Northwind Client#GetAllCustomersSpecific](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_client/cs/source.cs#getallcustomersspecific)] - [!code-vb[Astoria Northwind Client#GetAllCustomersSpecific](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_client/vb/source.vb#getallcustomersspecific)] - - For more information, see [How to: Execute Data Service Queries](../../../../docs/framework/data/wcf/how-to-execute-data-service-queries-wcf-data-services.md). - - The [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] client supports queries for late-bound objects, such as when you use the *dynamic* type in C#. However, for performance reasons you should always compose strongly-typed queries against the data service. The type and dynamic objects are not supported by the client. - -## LINQ Queries - Because the class implements the interface defined by LINQ, the [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] client library is able to transform LINQ queries against entity set data into a URI that represents a query expression evaluated against a data service resource. The following example is a LINQ query that is equivalent to the previous that returns `Orders` that have a freight cost of more than $30 and orders the results by the freight cost: - - [!code-csharp[Astoria Northwind Client#AddQueryOptionsLinqSpecific](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_client/cs/source.cs#addqueryoptionslinqspecific)] - [!code-vb[Astoria Northwind Client#AddQueryOptionsLinqSpecific](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_client/vb/source.vb#addqueryoptionslinqspecific)] - - This LINQ query is translated into the following query URI that is executed against the Northwind-based [quickstart](../../../../docs/framework/data/wcf/quickstart-wcf-data-services.md) data service: - -``` -http://localhost:12345/Northwind.svc/Orders?Orderby=ShippedDate&?filter=Freight gt 30 -``` - + +The [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] client library enables you to execute queries against a data service by using familiar [!INCLUDE[dnprdnshort](../../../../includes/dnprdnshort-md.md)] programming patterns, including using language integrated query (LINQ). The client library translates a query, which is defined on the client as an instance of the class, into an HTTP GET request message. The library receives the response message and translates it into instances of client data service classes. These classes are tracked by the to which the belongs. + +## Data Service Queries + +The generic class represents a query that returns a collection of zero or more entity type instances. A data service query always belongs to an existing data service context. This context maintains the service URI and metadata information that is required to compose and execute the query. + +When you use the **Add Service Reference** dialog to add a data service to a [!INCLUDE[dnprdnshort](../../../../includes/dnprdnshort-md.md)]-based client application, an entity container class is created that inherits from the class. This class includes properties that return typed instances. There is one property for each entity set that the data service exposes. These properties make it easier to create an instance of a typed . + +A query is executed in the following scenarios: + +- When results are enumerated implicitly, such as: + + - When a property on the that represents and entity set is enumerated, such as during a `foreach` (C#) or `For Each` (Visual Basic) loop. + + - When the query is assigned to a `List` collection. + +- When the or method is explicitly called. + +- When a LINQ query execution operator, such as or is called. + +The following query, when it is executed, returns all `Customers` entities in the Northwind data service: + +[!code-csharp[Astoria Northwind Client#GetAllCustomersSpecific](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_client/cs/source.cs#getallcustomersspecific)] +[!code-vb[Astoria Northwind Client#GetAllCustomersSpecific](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_client/vb/source.vb#getallcustomersspecific)] + +For more information, see [How to: Execute Data Service Queries](../../../../docs/framework/data/wcf/how-to-execute-data-service-queries-wcf-data-services.md). + +The [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] client supports queries for late-bound objects, such as when you use the *dynamic* type in C#. However, for performance reasons you should always compose strongly-typed queries against the data service. The type and dynamic objects are not supported by the client. + +## LINQ Queries + +Because the class implements the interface defined by LINQ, the [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] client library is able to transform LINQ queries against entity set data into a URI that represents a query expression evaluated against a data service resource. The following example is a LINQ query that is equivalent to the previous that returns `Orders` that have a freight cost of more than $30 and orders the results by the freight cost: + +[!code-csharp[Astoria Northwind Client#AddQueryOptionsLinqSpecific](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_client/cs/source.cs#addqueryoptionslinqspecific)] +[!code-vb[Astoria Northwind Client#AddQueryOptionsLinqSpecific](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_client/vb/source.vb#addqueryoptionslinqspecific)] + +This LINQ query is translated into the following query URI that is executed against the Northwind-based [quickstart](../../../../docs/framework/data/wcf/quickstart-wcf-data-services.md) data service: + +``` +http://localhost:12345/Northwind.svc/Orders?Orderby=ShippedDate&?filter=Freight gt 30 +``` + > [!NOTE] -> The set of queries expressible in the LINQ syntax is broader than those enabled in the representational state transfer (REST)-based URI syntax that is used by data services. A is raised when the query cannot be mapped to a URI in the target data service. - - For more information, see [LINQ Considerations](../../../../docs/framework/data/wcf/linq-considerations-wcf-data-services.md). - -## Adding Query Options - Data service queries support all the query options that [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)]s provides. You call the method to append query options to a instance. returns a new instance that is equivalent to the original query but with the new query option set. The following query, when executed, returns `Orders` that are filtered by the `Freight` value and ordered by the `OrderID`, descending: - - [!code-csharp[Astoria Northwind Client#AddQueryOptionsSpecific](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_client/cs/source.cs#addqueryoptionsspecific)] - [!code-vb[Astoria Northwind Client#AddQueryOptionsSpecific](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_client/vb/source.vb#addqueryoptionsspecific)] - - You can use the `$orderby` query option to both order and filter a query based on a single property, as in the following example that filters and orders the returned `Orders` objects based on the value of the `Freight` property: - - [!code-csharp[Astoria Northwind Client#OrderWithFilter](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_client/cs/source.cs#orderwithfilter)] - [!code-vb[Astoria Northwind Client#OrderWithFilter](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_client/vb/source.vb#orderwithfilter)] - - You can call the method consecutively to construct complex query expressions. For more information, see [How to: Add Query Options to a Data Service Query](../../../../docs/framework/data/wcf/how-to-add-query-options-to-a-data-service-query-wcf-data-services.md). - - Query options give you another way to express the syntactic components of a LINQ query. For more information, see [LINQ Considerations](../../../../docs/framework/data/wcf/linq-considerations-wcf-data-services.md). - +> The set of queries expressible in the LINQ syntax is broader than those enabled in the representational state transfer (REST)-based URI syntax that is used by data services. A is raised when the query cannot be mapped to a URI in the target data service. + +For more information, see [LINQ Considerations](../../../../docs/framework/data/wcf/linq-considerations-wcf-data-services.md). + +## Adding Query Options + +Data service queries support all the query options that [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)]s provides. You call the method to append query options to a instance. returns a new instance that is equivalent to the original query but with the new query option set. The following query, when executed, returns `Orders` that are filtered by the `Freight` value and ordered by the `OrderID`, descending: + +[!code-csharp[Astoria Northwind Client#AddQueryOptionsSpecific](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_client/cs/source.cs#addqueryoptionsspecific)] +[!code-vb[Astoria Northwind Client#AddQueryOptionsSpecific](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_client/vb/source.vb#addqueryoptionsspecific)] + +You can use the `$orderby` query option to both order and filter a query based on a single property, as in the following example that filters and orders the returned `Orders` objects based on the value of the `Freight` property: + +[!code-csharp[Astoria Northwind Client#OrderWithFilter](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_client/cs/source.cs#orderwithfilter)] +[!code-vb[Astoria Northwind Client#OrderWithFilter](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_client/vb/source.vb#orderwithfilter)] + +You can call the method consecutively to construct complex query expressions. For more information, see [How to: Add Query Options to a Data Service Query](../../../../docs/framework/data/wcf/how-to-add-query-options-to-a-data-service-query-wcf-data-services.md). + +Query options give you another way to express the syntactic components of a LINQ query. For more information, see [LINQ Considerations](../../../../docs/framework/data/wcf/linq-considerations-wcf-data-services.md). + > [!NOTE] -> The `$select` query option cannot be added to a query URI by using the method. We recommend that you use the LINQ method to have the client generate the `$select` query option in the request URI. - - -## Client versus Server Execution - The client executes a query in two parts. Whenever possible, expressions in a query are first evaluated on the client, and then a URI-based query is generated and sent to the data service for evaluation against data in the service. Consider the following LINQ query: - - [!code-csharp[Astoria Northwind Client#LinqQueryClientEvalSpecific](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_client/cs/source.cs#linqqueryclientevalspecific)] - [!code-vb[Astoria Northwind Client#LinqQueryClientEvalSpecific](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_client/vb/source.vb#linqqueryclientevalspecific)] - - In this example, the expression `(basePrice – (basePrice * discount))` is evaluated on the client. Because of this, the actual query URI `http://localhost:12345/northwind.svc/Products()?$filter=(UnitPrice gt 90.00M) and substringof('bike',ProductName)` that is sent to the data service contains the already calculated decimal value of `90` in the filter clause. The other parts of the filtering expression, including the substring expression, are evaluated by the data service. Expressions that are evaluated on the client follow common language runtime (CLR) semantics, while expressions sent to the data service rely on the data service implementation of the [!INCLUDE[ssODataShort](../../../../includes/ssodatashort-md.md)] Protocol. You should also be aware of scenarios where this separate evaluation may cause unexpected results, such as when both the client and service perform time-based evaluations in different time zones. - -## Query Responses - When executed, the returns an of the requested entity type. This query result can be cast to a object, as in the following example: - - [!code-csharp[Astoria Northwind Client#GetResponseSpecific](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_client/cs/source.cs#getresponsespecific)] - [!code-vb[Astoria Northwind Client#GetResponseSpecific](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_client/vb/source.vb#getresponsespecific)] - - The entity type instances that represent entities in the data service are created on the client by a process called object materialization. For more information, see [Object Materialization](../../../../docs/framework/data/wcf/object-materialization-wcf-data-services.md). The object implements to provide access to the results of the query. - - The also has the following members that enable you to access additional information about a query result: - -- - gets an error thrown by the operation, if any has occurred. - -- - contains the collection of HTTP response headers associated with the query response. - -- - gets the original that generated the . - -- - gets the HTTP response code for the query response. - -- - gets the total number of entities in the entity set when the method was called on the . - -- - returns a object that contains the URI of the next page of results. - - By default, [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] only returns data that is explicitly selected by the query URI. This gives you the option to explicitly load additional data from the data service when it is needed. A request is sent to the data service each time you explicitly load data from the data service. Data that can be explicitly loaded includes related entities, paged response data, and binary data streams. - +> The `$select` query option cannot be added to a query URI by using the method. We recommend that you use the LINQ method to have the client generate the `$select` query option in the request URI. + + + +## Client versus Server Execution + +The client executes a query in two parts. Whenever possible, expressions in a query are first evaluated on the client, and then a URI-based query is generated and sent to the data service for evaluation against data in the service. Consider the following LINQ query: + +[!code-csharp[Astoria Northwind Client#LinqQueryClientEvalSpecific](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_client/cs/source.cs#linqqueryclientevalspecific)] +[!code-vb[Astoria Northwind Client#LinqQueryClientEvalSpecific](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_client/vb/source.vb#linqqueryclientevalspecific)] + +In this example, the expression `(basePrice – (basePrice * discount))` is evaluated on the client. Because of this, the actual query URI `http://localhost:12345/northwind.svc/Products()?$filter=(UnitPrice gt 90.00M) and substringof('bike',ProductName)` that is sent to the data service contains the already calculated decimal value of `90` in the filter clause. The other parts of the filtering expression, including the substring expression, are evaluated by the data service. Expressions that are evaluated on the client follow common language runtime (CLR) semantics, while expressions sent to the data service rely on the data service implementation of the [!INCLUDE[ssODataShort](../../../../includes/ssodatashort-md.md)] Protocol. You should also be aware of scenarios where this separate evaluation may cause unexpected results, such as when both the client and service perform time-based evaluations in different time zones. + +## Query Responses + +When executed, the returns an of the requested entity type. This query result can be cast to a object, as in the following example: + +[!code-csharp[Astoria Northwind Client#GetResponseSpecific](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_client/cs/source.cs#getresponsespecific)] +[!code-vb[Astoria Northwind Client#GetResponseSpecific](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_client/vb/source.vb#getresponsespecific)] + +The entity type instances that represent entities in the data service are created on the client by a process called object materialization. For more information, see [Object Materialization](../../../../docs/framework/data/wcf/object-materialization-wcf-data-services.md). The object implements to provide access to the results of the query. + +The also has the following members that enable you to access additional information about a query result: + +- - gets an error thrown by the operation, if any has occurred. + +- - contains the collection of HTTP response headers associated with the query response. + +- - gets the original that generated the . + +- - gets the HTTP response code for the query response. + +- - gets the total number of entities in the entity set when the method was called on the . + +- - returns a object that contains the URI of the next page of results. + +By default, [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] only returns data that is explicitly selected by the query URI. This gives you the option to explicitly load additional data from the data service when it is needed. A request is sent to the data service each time you explicitly load data from the data service. Data that can be explicitly loaded includes related entities, paged response data, and binary data streams. + > [!NOTE] -> Because a data service may return a paged response, we recommend that your application use the programming pattern to handle a paged data service response. For more information, see [Loading Deferred Content](../../../../docs/framework/data/wcf/loading-deferred-content-wcf-data-services.md). - - The amount of data returned by a query can also be reduced by specifying that only certain properties of an entity are returned in the response. For more information, see [Query Projections](../../../../docs/framework/data/wcf/query-projections-wcf-data-services.md). - -## Getting a Count of the Total Number of Entities in the Set - In some scenarios, it is helpful to know the total number of entities in an entity set and not merely the number returned by the query. Call the method on the to request that this total count of entities in the set be included with the query result. In this case, the property of the returned returns the total number of entities in the set. - - You can also get only the total count of entities in the set either as an or as a value by calling the or methods respectively. When these methods are called, a is not returned; only the count value is returned. For more information, see [How to: Determine the Number of Entities Returned by a Query](../../../../docs/framework/data/wcf/number-of-entities-returned-by-a-query-wcf.md). - -## In This Section - [Query Projections](../../../../docs/framework/data/wcf/query-projections-wcf-data-services.md) - - [Object Materialization](../../../../docs/framework/data/wcf/object-materialization-wcf-data-services.md) - - [LINQ Considerations](../../../../docs/framework/data/wcf/linq-considerations-wcf-data-services.md) - - [How to: Execute Data Service Queries](../../../../docs/framework/data/wcf/how-to-execute-data-service-queries-wcf-data-services.md) - - [How to: Add Query Options to a Data Service Query](../../../../docs/framework/data/wcf/how-to-add-query-options-to-a-data-service-query-wcf-data-services.md) - - [How to: Determine the Number of Entities Returned by a Query](../../../../docs/framework/data/wcf/number-of-entities-returned-by-a-query-wcf.md) - - [How to: Specify Client Credentials for a Data Service Request](../../../../docs/framework/data/wcf/specify-client-creds-for-a-data-service-request-wcf.md) - - [How to: Set Headers in the Client Request](../../../../docs/framework/data/wcf/how-to-set-headers-in-the-client-request-wcf-data-services.md) - - [How to: Project Query Results](../../../../docs/framework/data/wcf/how-to-project-query-results-wcf-data-services.md) - +> Because a data service may return a paged response, we recommend that your application use the programming pattern to handle a paged data service response. For more information, see [Loading Deferred Content](../../../../docs/framework/data/wcf/loading-deferred-content-wcf-data-services.md). + +The amount of data returned by a query can also be reduced by specifying that only certain properties of an entity are returned in the response. For more information, see [Query Projections](../../../../docs/framework/data/wcf/query-projections-wcf-data-services.md). + +## Getting a Count of the Total Number of Entities in the Set + +In some scenarios, it is helpful to know the total number of entities in an entity set and not merely the number returned by the query. Call the method on the to request that this total count of entities in the set be included with the query result. In this case, the property of the returned returns the total number of entities in the set. + +You can also get only the total count of entities in the set either as an or as a value by calling the or methods respectively. When these methods are called, a is not returned; only the count value is returned. For more information, see [How to: Determine the Number of Entities Returned by a Query](../../../../docs/framework/data/wcf/number-of-entities-returned-by-a-query-wcf.md). + +## In This Section + +- [Query Projections](../../../../docs/framework/data/wcf/query-projections-wcf-data-services.md) + +- [Object Materialization](../../../../docs/framework/data/wcf/object-materialization-wcf-data-services.md) + +- [LINQ Considerations](../../../../docs/framework/data/wcf/linq-considerations-wcf-data-services.md) + +- [How to: Execute Data Service Queries](../../../../docs/framework/data/wcf/how-to-execute-data-service-queries-wcf-data-services.md) + +- [How to: Add Query Options to a Data Service Query](../../../../docs/framework/data/wcf/how-to-add-query-options-to-a-data-service-query-wcf-data-services.md) + +- [How to: Determine the Number of Entities Returned by a Query](../../../../docs/framework/data/wcf/number-of-entities-returned-by-a-query-wcf.md) + +- [How to: Specify Client Credentials for a Data Service Request](../../../../docs/framework/data/wcf/specify-client-creds-for-a-data-service-request-wcf.md) + +- [How to: Set Headers in the Client Request](../../../../docs/framework/data/wcf/how-to-set-headers-in-the-client-request-wcf-data-services.md) + +- [How to: Project Query Results](../../../../docs/framework/data/wcf/how-to-project-query-results-wcf-data-services.md) + ## See also - [WCF Data Services Client Library](../../../../docs/framework/data/wcf/wcf-data-services-client-library.md) diff --git a/docs/framework/data/wcf/reflection-provider-wcf-data-services.md b/docs/framework/data/wcf/reflection-provider-wcf-data-services.md index ee9c22b2379ef..54342c1325ac3 100644 --- a/docs/framework/data/wcf/reflection-provider-wcf-data-services.md +++ b/docs/framework/data/wcf/reflection-provider-wcf-data-services.md @@ -1,93 +1,99 @@ --- title: "Reflection Provider (WCF Data Services)" ms.date: "03/30/2017" -helpviewer_keywords: +helpviewer_keywords: - "WCF Data Services, providers" ms.assetid: ef5ba300-6d7c-455e-a7bd-d0cc6d211ad4 --- # Reflection Provider (WCF Data Services) -In addition to exposing data from a data model through the Entity Framework, [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] can expose data that is not strictly defined in an entity-based model. The reflection provider exposes data in classes that return types that implement the interface. [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] uses reflection to infer a data model for these classes and can translate address-based queries against resources into language integrated query (LINQ)-based queries against the exposed types. - + +In addition to exposing data from a data model through the Entity Framework, [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] can expose data that is not strictly defined in an entity-based model. The reflection provider exposes data in classes that return types that implement the interface. [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] uses reflection to infer a data model for these classes and can translate address-based queries against resources into language integrated query (LINQ)-based queries against the exposed types. + > [!NOTE] -> You can use the method to return an interface from any class that implements the interface. This enables most generic collection types to be used as a data source for your data service. - - The reflection provider supports type hierarchies. For more information, see [How to: Create a Data Service Using the Reflection Provider](../../../../docs/framework/data/wcf/create-a-data-service-using-rp-wcf-data-services.md). - -## Inferring the Data Model - When you create the data service, the provider infers the data model by using reflection. The following list shows how the reflection provider infers the data model: - -- Entity container - the class that exposes the data as properties that return an instance. When you address a reflection-based data model, the entity container represents the root of the service. Only one entity container class is supported for a given namespace. - -- Entity sets - properties that return instances are treated as entity sets. Entity sets are addressed directly as resources in the query. Only one property on the entity container can return an instance of a given type. - -- Entity types - the type `T` of the that the entity set returns. Classes that are part of an inheritance hierarchy are translated by the reflection provider into an equivalent entity type hierarchy. - -- Entity keys - each data class that is an entity type must have a key property. This property is attributed with the attribute (`[DataServiceKeyAttribute]`). - +> You can use the method to return an interface from any class that implements the interface. This enables most generic collection types to be used as a data source for your data service. + +The reflection provider supports type hierarchies. For more information, see [How to: Create a Data Service Using the Reflection Provider](../../../../docs/framework/data/wcf/create-a-data-service-using-rp-wcf-data-services.md). + +## Inferring the Data Model + +When you create the data service, the provider infers the data model by using reflection. The following list shows how the reflection provider infers the data model: + +- Entity container - the class that exposes the data as properties that return an instance. When you address a reflection-based data model, the entity container represents the root of the service. Only one entity container class is supported for a given namespace. + +- Entity sets - properties that return instances are treated as entity sets. Entity sets are addressed directly as resources in the query. Only one property on the entity container can return an instance of a given type. + +- Entity types - the type `T` of the that the entity set returns. Classes that are part of an inheritance hierarchy are translated by the reflection provider into an equivalent entity type hierarchy. + +- Entity keys - each data class that is an entity type must have a key property. This property is attributed with the attribute (`[DataServiceKeyAttribute]`). + > [!NOTE] - > You should only apply the attribute to a property that can be used to uniquely identify an instance of the entity type. This attribute is ignored when applied to a navigation property. - -- Entity type properties - other than the entity key, the reflection provider treats the accessible, non-indexer properties of a class that is an entity type as follows: - - - If the property returns a primitive type, then the property is assumed to be a property of an entity type. - - - If the property returns a type that is also an entity type, then the property is assumed to be a navigation property that represents the "one" end of a many-to-one or one-to-one relationship. - - - If the property returns an of an entity type, then the property is assumed to be a navigation property that represents the "many" end of a one-to-many or many-to-many relationship. - - - If the return type of the property is a value type, then the property represents a complex type. - + > You should only apply the attribute to a property that can be used to uniquely identify an instance of the entity type. This attribute is ignored when applied to a navigation property. + +- Entity type properties - other than the entity key, the reflection provider treats the accessible, non-indexer properties of a class that is an entity type as follows: + + - If the property returns a primitive type, then the property is assumed to be a property of an entity type. + + - If the property returns a type that is also an entity type, then the property is assumed to be a navigation property that represents the "one" end of a many-to-one or one-to-one relationship. + + - If the property returns an of an entity type, then the property is assumed to be a navigation property that represents the "many" end of a one-to-many or many-to-many relationship. + + - If the return type of the property is a value type, then the property represents a complex type. + > [!NOTE] -> Unlike a data model that is based on the entity-relational model, models that are based on the reflection provider do not understand relational data. You should use the Entity Framework to expose relational data through [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)]. - -## Data Type Mapping - When a data model is inferred from .NET Framework classes, the primitive types in the data model are mapped to .NET Framework data types as follows: - -|.NET Framework data type|Data model type| -|------------------------------|---------------------| -| `[]`|`Edm.Binary`| -||`Edm.Boolean`| -||`Edm.Byte`| -||`Edm.DateTime`| -||`Edm.Decimal`| -||`Edm.Double`| -||`Edm.Guid`| -||`Edm.Int16`| -||`Edm.Int32`| -||`Edm.Int64`| -||`Edm.SByte`| -||`Edm.Single`| -||`Edm.String`| - +> Unlike a data model that is based on the entity-relational model, models that are based on the reflection provider do not understand relational data. You should use the Entity Framework to expose relational data through [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)]. + +## Data Type Mapping + +When a data model is inferred from .NET Framework classes, the primitive types in the data model are mapped to .NET Framework data types as follows: + +|.NET Framework data type|Data model type| +|------------------------------|---------------------| +| `[]`|`Edm.Binary`| +||`Edm.Boolean`| +||`Edm.Byte`| +||`Edm.DateTime`| +||`Edm.Decimal`| +||`Edm.Double`| +||`Edm.Guid`| +||`Edm.Int16`| +||`Edm.Int32`| +||`Edm.Int64`| +||`Edm.SByte`| +||`Edm.Single`| +||`Edm.String`| + > [!NOTE] -> .NET Framework nullable value types are mapped to the same data model types as the corresponding value types that cannot be assigned a null. - -## Enabling Updates in the Data Model - To allow updates to data that is exposed through this kind of data model, the reflection provider defines an interface. This interface instructs the data service on how to persist updates to the exposed types. To enable updates to resources that are defined by the data model, the entity container class must implement the interface. For an example of an implementation of the interface, see [How to: Create a Data Service Using a LINQ to SQL Data Source](../../../../docs/framework/data/wcf/create-a-data-service-using-linq-to-sql-wcf.md). - - The interface requires that the following members be implemented so that updates can be propagated to the data source by using the reflection provider: - -|Member|Description| -|------------|-----------------| -||Provides the functionality to add an object to a collection of related objects that are accessed from a navigation property.| -||Provides the functionality that cancels pending changes to the data.| -||Provides the functionality to create a new resource in the specified container.| -||Provides the functionality to delete a resource.| -||Provides the functionality to retrieve a resource that is identified by a specific query and type name.| -||Provides the functionality to return the value of a property of a resource.| -||Provides the functionality to remove an object to a collection of related objects accessed from a navigation property.| -||Provides the functionality to update a specified resource.| -||Provides the functionality to return the resource that is represented by a specific object instance.| -||Provides the functionality to save all pending changes.| -||Provides the functionality to set a related object reference by using a navigation property.| -||Provides the functionality to set the value of the property of a resource.| - -## Handling Concurrency - [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] supports an optimistic concurrency model by enabling you to define a concurrency token for an entity. This concurrency token, which includes one or more properties of the entity, is used by the data service to determine whether a change has occurred in the data that is being requested, updated, or deleted. When token values obtained from the eTag in the request differ from the current values of the entity, an exception is raised by the data service. The is applied to an entity type to define a concurrency token in the reflection provider. The concurrency token cannot include a key property or a navigation property. For more information, see [Updating the Data Service](../../../../docs/framework/data/wcf/updating-the-data-service-wcf-data-services.md). - -## Using LINQ to SQL with the Reflection Provider - Because the Entity Framework is natively supported by default, it is the recommended data provider for using relational data with [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)]. However, you can use the reflection provider to use LINQ to SQL classes with a data service. The result sets that are returned by methods on the generated by the LINQ to SQL Object Relational Designer (O/R Designer) implement the interface. This enables the reflection provider to access these methods and return entity data from SQL Server by using the generated LINQ to SQL classes. However, because LINQ to SQL does not implement the interface, you need to add a partial class that extends the existing partial class to add the implementation. For more information, see [How to: Create a Data Service Using a LINQ to SQL Data Source](../../../../docs/framework/data/wcf/create-a-data-service-using-linq-to-sql-wcf.md). - +> .NET Framework nullable value types are mapped to the same data model types as the corresponding value types that cannot be assigned a null. + +## Enabling Updates in the Data Model + +To allow updates to data that is exposed through this kind of data model, the reflection provider defines an interface. This interface instructs the data service on how to persist updates to the exposed types. To enable updates to resources that are defined by the data model, the entity container class must implement the interface. For an example of an implementation of the interface, see [How to: Create a Data Service Using a LINQ to SQL Data Source](../../../../docs/framework/data/wcf/create-a-data-service-using-linq-to-sql-wcf.md). + +The interface requires that the following members be implemented so that updates can be propagated to the data source by using the reflection provider: + +|Member|Description| +|------------|-----------------| +||Provides the functionality to add an object to a collection of related objects that are accessed from a navigation property.| +||Provides the functionality that cancels pending changes to the data.| +||Provides the functionality to create a new resource in the specified container.| +||Provides the functionality to delete a resource.| +||Provides the functionality to retrieve a resource that is identified by a specific query and type name.| +||Provides the functionality to return the value of a property of a resource.| +||Provides the functionality to remove an object to a collection of related objects accessed from a navigation property.| +||Provides the functionality to update a specified resource.| +||Provides the functionality to return the resource that is represented by a specific object instance.| +||Provides the functionality to save all pending changes.| +||Provides the functionality to set a related object reference by using a navigation property.| +||Provides the functionality to set the value of the property of a resource.| + +## Handling Concurrency + +[!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] supports an optimistic concurrency model by enabling you to define a concurrency token for an entity. This concurrency token, which includes one or more properties of the entity, is used by the data service to determine whether a change has occurred in the data that is being requested, updated, or deleted. When token values obtained from the eTag in the request differ from the current values of the entity, an exception is raised by the data service. The is applied to an entity type to define a concurrency token in the reflection provider. The concurrency token cannot include a key property or a navigation property. For more information, see [Updating the Data Service](../../../../docs/framework/data/wcf/updating-the-data-service-wcf-data-services.md). + +## Using LINQ to SQL with the Reflection Provider + +Because the Entity Framework is natively supported by default, it is the recommended data provider for using relational data with [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)]. However, you can use the reflection provider to use LINQ to SQL classes with a data service. The result sets that are returned by methods on the generated by the LINQ to SQL Object Relational Designer (O/R Designer) implement the interface. This enables the reflection provider to access these methods and return entity data from SQL Server by using the generated LINQ to SQL classes. However, because LINQ to SQL does not implement the interface, you need to add a partial class that extends the existing partial class to add the implementation. For more information, see [How to: Create a Data Service Using a LINQ to SQL Data Source](../../../../docs/framework/data/wcf/create-a-data-service-using-linq-to-sql-wcf.md). + ## See also - [Data Services Providers](../../../../docs/framework/data/wcf/data-services-providers-wcf-data-services.md) diff --git a/docs/framework/data/wcf/service-operations-wcf-data-services.md b/docs/framework/data/wcf/service-operations-wcf-data-services.md index 72c4af2179665..862957bce0f66 100644 --- a/docs/framework/data/wcf/service-operations-wcf-data-services.md +++ b/docs/framework/data/wcf/service-operations-wcf-data-services.md @@ -1,103 +1,108 @@ --- title: "Service Operations (WCF Data Services)" ms.date: "03/30/2017" -dev_langs: +dev_langs: - "csharp" - "vb" -helpviewer_keywords: +helpviewer_keywords: - "service operations [WCF Data Services]" - "WCF Data Services, service operations" ms.assetid: 583a690a-e60f-4990-8991-d6efce069d76 --- # Service Operations (WCF Data Services) -[!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] enables you to define service operations on a data service to expose methods on the server. Like other data service resources, service operations are addressed by URIs. Service operations enable you to expose business logic in a data service, such as to implement validation logic, to apply role-based security, or to expose specialized querying capabilities. Service operations are methods added to the data service class that derives from . Like all other data service resources, you can supply parameters to the service operation method. For example, the following service operation URI (based on the [quickstart](../../../../docs/framework/data/wcf/quickstart-wcf-data-services.md) data service) passes the value `London` to the `city` parameter: - -``` -http://localhost:12345/Northwind.svc/GetOrdersByCity?city='London' -``` - - The definition for this service operation is as follows: - - [!code-csharp[Astoria Northwind Service#ServiceOperationDef](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_service/cs/northwind2.svc.cs#serviceoperationdef)] - [!code-vb[Astoria Northwind Service#ServiceOperationDef](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_service/vb/northwind2.svc.vb#serviceoperationdef)] - - You can use the of the to directly access the data source that the data service is using. For more information, see [How to: Define a Service Operation](../../../../docs/framework/data/wcf/how-to-define-a-service-operation-wcf-data-services.md). - - For information on how to call a service operation from a .NET Framework client application, see [Calling Service Operations](../../../../docs/framework/data/wcf/calling-service-operations-wcf-data-services.md). - -## Service Operation Requirements - The following requirements apply when defining service operations on the data service. If a method does not meet these requirements, it will not be exposed as a service operation for the data service. - -- The operation must be a public instance method that is a member of the data service class. - -- The operation method may only accept input parameters. Data sent in the message body cannot be accessed by the data service. - -- If parameters are defined, the type of each parameter must be a primitive type. Any data of a non-primitive type must be serialized and passed into a string parameter. - -- The method must return one of the following: - - - `void` (`Nothing` in Visual Basic) - - - - - - - - - An entity type in the data model that the data service exposes. - - - A primitive class such as integer or string. - -- In order to support query options such as sorting, paging, and filtering, service operation methods should return . Requests to service operations that include query options are rejected for operations that only return . - -- In order to support accessing related entities by using navigation properties, the service operation must return . - -- The method must be annotated with the `[WebGet]` or `[WebInvoke]` attribute. - - - `[WebGet]` enables the method to be invoked by using a GET request. - - - `[WebInvoke(Method = "POST")]` enables the method to be invoked by using a POST request. Other methods are not supported. - -- A service operation may be annotated with the that specifies that the return value from the method is a single entity rather than a collection of entities. This distinction dictates the resulting serialization of the response and the manner in which additional navigation property traversals are represented in the URI. For example, when using AtomPub serialization, a single resource type instance is represented as an entry element and a set of instances as a feed element. - -## Addressing Service Operations - You can address service operations by placing the name of the method in the first path segment of a URI. As an example, the following URI accesses a `GetOrdersByState` operation that returns an collection of `Orders` objects. - -``` -http://localhost:12345/Northwind.svc/GetOrdersByState?state='CA'&includeItems=true -``` - - When calling a service operation, parameters are supplied as query options. The previous service operation accepts both a string parameter `state` and a Boolean parameter `includeItems` that indicates whether to include related `Order_Detail` objects in the response. - - The following are valid return types for a service operation: - -|Valid Return Types|URI Rules| -|------------------------|---------------| -|`void` (`Nothing` in Visual Basic)

-or-

Entity types

-or-

Primitive types|The URI must be a single path segment that is the name of the service operation. Query options are not allowed.| -||The URI must be a single path segment that is the name of the service operation. Because the result type is not an type, query options are not allowed.| -||Query path segments in addition to the path that is the name of the service operation are allowed. Query options are also allowed.| - - Additional path segments or query options may be added to the URI depending on the return type of the service operation. For example, the following URI accesses a `GetOrdersByCity` operation that returns an collection of `Orders` objects, ordered by `RequiredDate` in descending order, along with the related `Order_Details` objects: - -``` -http://localhost:12345/Northwind.svc/GetOrdersByCity?city='London'&$expand=Order_Details&$orderby=RequiredDate desc -``` - -## Service Operations Access Control - Service-wide visibility of service operations is controlled by the method on the class in much the same way that entity set visibility is controlled by using the method. For example, the following line of code in the data service definition enables access to the `CustomersByCity` service operation. - - [!code-csharp[Astoria Northwind Service#ServiceOperationConfig](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_service/cs/northwind2.svc.cs#serviceoperationconfig)] - [!code-vb[Astoria Northwind Service#ServiceOperationConfig](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_service/vb/northwind2.svc.vb#serviceoperationconfig)] - + +[!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] enables you to define service operations on a data service to expose methods on the server. Like other data service resources, service operations are addressed by URIs. Service operations enable you to expose business logic in a data service, such as to implement validation logic, to apply role-based security, or to expose specialized querying capabilities. Service operations are methods added to the data service class that derives from . Like all other data service resources, you can supply parameters to the service operation method. For example, the following service operation URI (based on the [quickstart](../../../../docs/framework/data/wcf/quickstart-wcf-data-services.md) data service) passes the value `London` to the `city` parameter: + +``` +http://localhost:12345/Northwind.svc/GetOrdersByCity?city='London' +``` + +The definition for this service operation is as follows: + +[!code-csharp[Astoria Northwind Service#ServiceOperationDef](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_service/cs/northwind2.svc.cs#serviceoperationdef)] +[!code-vb[Astoria Northwind Service#ServiceOperationDef](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_service/vb/northwind2.svc.vb#serviceoperationdef)] + +You can use the of the to directly access the data source that the data service is using. For more information, see [How to: Define a Service Operation](../../../../docs/framework/data/wcf/how-to-define-a-service-operation-wcf-data-services.md). + +For information on how to call a service operation from a .NET Framework client application, see [Calling Service Operations](../../../../docs/framework/data/wcf/calling-service-operations-wcf-data-services.md). + +## Service Operation Requirements + +The following requirements apply when defining service operations on the data service. If a method does not meet these requirements, it will not be exposed as a service operation for the data service. + +- The operation must be a public instance method that is a member of the data service class. + +- The operation method may only accept input parameters. Data sent in the message body cannot be accessed by the data service. + +- If parameters are defined, the type of each parameter must be a primitive type. Any data of a non-primitive type must be serialized and passed into a string parameter. + +- The method must return one of the following: + + - `void` (`Nothing` in Visual Basic) + + - + + - + + - An entity type in the data model that the data service exposes. + + - A primitive class such as integer or string. + +- In order to support query options such as sorting, paging, and filtering, service operation methods should return . Requests to service operations that include query options are rejected for operations that only return . + +- In order to support accessing related entities by using navigation properties, the service operation must return . + +- The method must be annotated with the `[WebGet]` or `[WebInvoke]` attribute. + + - `[WebGet]` enables the method to be invoked by using a GET request. + + - `[WebInvoke(Method = "POST")]` enables the method to be invoked by using a POST request. Other methods are not supported. + +- A service operation may be annotated with the that specifies that the return value from the method is a single entity rather than a collection of entities. This distinction dictates the resulting serialization of the response and the manner in which additional navigation property traversals are represented in the URI. For example, when using AtomPub serialization, a single resource type instance is represented as an entry element and a set of instances as a feed element. + +## Addressing Service Operations + +You can address service operations by placing the name of the method in the first path segment of a URI. As an example, the following URI accesses a `GetOrdersByState` operation that returns an collection of `Orders` objects. + +``` +http://localhost:12345/Northwind.svc/GetOrdersByState?state='CA'&includeItems=true +``` + +When calling a service operation, parameters are supplied as query options. The previous service operation accepts both a string parameter `state` and a Boolean parameter `includeItems` that indicates whether to include related `Order_Detail` objects in the response. + +The following are valid return types for a service operation: + +|Valid Return Types|URI Rules| +|------------------------|---------------| +|`void` (`Nothing` in Visual Basic)

-or-

Entity types

-or-

Primitive types|The URI must be a single path segment that is the name of the service operation. Query options are not allowed.| +||The URI must be a single path segment that is the name of the service operation. Because the result type is not an type, query options are not allowed.| +||Query path segments in addition to the path that is the name of the service operation are allowed. Query options are also allowed.| + +Additional path segments or query options may be added to the URI depending on the return type of the service operation. For example, the following URI accesses a `GetOrdersByCity` operation that returns an collection of `Orders` objects, ordered by `RequiredDate` in descending order, along with the related `Order_Details` objects: + +``` +http://localhost:12345/Northwind.svc/GetOrdersByCity?city='London'&$expand=Order_Details&$orderby=RequiredDate desc +``` + +## Service Operations Access Control + +Service-wide visibility of service operations is controlled by the method on the class in much the same way that entity set visibility is controlled by using the method. For example, the following line of code in the data service definition enables access to the `CustomersByCity` service operation. + +[!code-csharp[Astoria Northwind Service#ServiceOperationConfig](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_service/cs/northwind2.svc.cs#serviceoperationconfig)] +[!code-vb[Astoria Northwind Service#ServiceOperationConfig](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_service/vb/northwind2.svc.vb#serviceoperationconfig)] + > [!NOTE] -> If a service operation has a return type that has been hidden by restricting access on the underlying entity sets, then the service operation will not be available to client applications. - - For more information, see [How to: Define a Service Operation](../../../../docs/framework/data/wcf/how-to-define-a-service-operation-wcf-data-services.md). - -## Raising Exceptions - We recommend that you use the class whenever you raise an exception in the data service execution. This is because the data service runtime knows how to map properties of this exception object correctly to the HTTP response message. When you raise a in a service operation, the returned exception is wrapped in a . To return the base without the enclosing , you must override the method in the , extract the from the , and return it as the top-level error, as in the following example: - - [!code-csharp[Astoria Northwind Service#HandleExceptions](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_service/cs/northwind2.svc.cs#handleexceptions)] - [!code-vb[Astoria Northwind Service#HandleExceptions](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_service/vb/northwind2.svc.vb#handleexceptions)] - +> If a service operation has a return type that has been hidden by restricting access on the underlying entity sets, then the service operation will not be available to client applications. + +For more information, see [How to: Define a Service Operation](../../../../docs/framework/data/wcf/how-to-define-a-service-operation-wcf-data-services.md). + +## Raising Exceptions + +We recommend that you use the class whenever you raise an exception in the data service execution. This is because the data service runtime knows how to map properties of this exception object correctly to the HTTP response message. When you raise a in a service operation, the returned exception is wrapped in a . To return the base without the enclosing , you must override the method in the , extract the from the , and return it as the top-level error, as in the following example: + +[!code-csharp[Astoria Northwind Service#HandleExceptions](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_northwind_service/cs/northwind2.svc.cs#handleexceptions)] +[!code-vb[Astoria Northwind Service#HandleExceptions](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_northwind_service/vb/northwind2.svc.vb#handleexceptions)] + ## See also - [Interceptors](../../../../docs/framework/data/wcf/interceptors-wcf-data-services.md) diff --git a/docs/framework/data/wcf/streaming-provider-wcf-data-services.md b/docs/framework/data/wcf/streaming-provider-wcf-data-services.md index 9fbc1ce3e1314..d9d09305e289c 100644 --- a/docs/framework/data/wcf/streaming-provider-wcf-data-services.md +++ b/docs/framework/data/wcf/streaming-provider-wcf-data-services.md @@ -1,10 +1,10 @@ --- title: "Streaming Provider (WCF Data Services)" ms.date: "03/30/2017" -dev_langs: +dev_langs: - "csharp" - "vb" -helpviewer_keywords: +helpviewer_keywords: - "WCF Data Services, providers" - "WCF Data Services, binary data" - "streaming data provider [WCF Data Services]" @@ -12,113 +12,125 @@ helpviewer_keywords: ms.assetid: f0978fe4-5f9f-42aa-a5c2-df395d7c9495 --- # Streaming Provider (WCF Data Services) -A data service can expose large object binary data. This binary data might represent video and audio streams, images, document files, or other types of binary media. When an entity in the data model includes one or more binary properties, the data service returns this binary data encoded as base-64 inside the entry in the response feed. Because loading and serializing large binary data in this manner can affect performance, the [!INCLUDE[ssODataFull](../../../../includes/ssodatafull-md.md)] defines a mechanism for retrieving binary data independent of the entity to which it belongs. This is accomplished by separating the binary data from the entity into one or more data streams. - -- Media resource - binary data that belongs to an entity, such as a video, audio, image or other type of media resource stream. - -- Media link entry - an entity that has a reference to a related media resource stream. - - With [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)], you define a binary resource stream by implementing a streaming data provider. The streaming provider implementation supplies the data service with the media resource stream associated with a specific entity as an object. This implementation enables the data service to accept and return media resources over HTTP as binary data streams of a specified MIME type. - - Configuring a data service to support the streaming of binary data requires the following steps: - -1. Attribute one or more entities in the data model as a media link entry. These entities should not include the binary data to be streamed. Any binary properties of an entity are always returned in the entry as base-64 encoded binary. - -2. Implement the T:System.Data.Services.Providers.IDataServiceStreamProvider interface. - -3. Define a data service that implements the interface. The data service uses the implementation to access the streaming data provider implementation. This method returns the appropriate streaming provider implementation. - -4. Enable large message streams in the Web application configuration. - -5. Enable access to binary resources on the server or in a data source. - - The examples in this topic are based on a sample streaming photo service, which is discussed in depth in the post [Data Services Streaming Provider Series: Implementing a Streaming Provider (Part 1)](https://go.microsoft.com/fwlink/?LinkID=198989). The source code for this sample service is available on the [Streaming Photo Data Service Sample page](https://go.microsoft.com/fwlink/?LinkID=198988) on MSDN Code Gallery. - -## Defining a Media Link Entry in the Data Model - The data source provider determines the way that an entity is defined as a media link entry in the data model. - - **Entity Framework Provider** - To indicate that an entity is a media link entry, add the `HasStream` attribute to the entity type definition in the conceptual model, as in the following example: - - [!code-xml[Astoria Photo Streaming Service#HasStream](../../../../samples/snippets/xml/VS_Snippets_Misc/astoria_photo_streaming_service/xml/photodata.edmx#hasstream)] - - You must also add the namespace `xmlns:m=http://schemas.microsoft.com/ado/2007/08/dataservices/metadata` either to the entity or to the root of the .edmx or .csdl file that defines the data model. - - For an example of a data service that uses the [!INCLUDE[adonet_ef](../../../../includes/adonet-ef-md.md)] provider and exposes a media resource, see the post [Data Services Streaming Provider Series: Implementing a Streaming Provider (Part 1)](https://go.microsoft.com/fwlink/?LinkID=198989). - - **Reflection Provider** - To indicate that an entity is a media link entry, add the to the class that defines the entity type in the reflection provider. - - **Custom Data Service Provider** - When using custom service providers, you implement the interface to define the metadata for your data service. For more information, see [Custom Data Service Providers](../../../../docs/framework/data/wcf/custom-data-service-providers-wcf-data-services.md). You indicate that a binary resource stream belongs to a by setting the property to `true` on the that represents the entity type, which is a media link entry. - -## Implementing the IDataServiceStreamProvider Interface - To create a data service that supports binary data streams, you must implement the interface. This implementation enables the data service to return binary data as a stream to the client and consume binary data as a stream sent from the client. The data service creates an instance of this interface whenever it needs to access binary data as a stream. The interface specifies the following members: - -|Member name|Description| -|-----------------|-----------------| -||This method is invoked by the data service to delete the corresponding media resource when its media link entry is deleted. When you implement , this method contains the code that deletes the media resource associated with the supplied media link entry.| -||This method is invoked by the data service to return a media resource as a stream. When you implement , this method contains the code that provides a stream that is used by the data service to the return media resource that is associated with the provided media link entry.| -||This method is invoked by the data service to return the URI that is used to request the media resource for the media link entry. This value is used to create the `src` attribute in the content element of the media link entry and that is used to request the data stream. When this method returns `null`, the data service automatically determines the URI. Use this method when you need to provide clients with direct access to binary data without using the steam provider.| -||This method is invoked by the data service to return the Content-Type value of the media resource that is associated with the specified media link entry.| -||This method is invoked by the data service to return the eTag of the data stream that is associated with the specified entity. This method is used when you manage concurrency for the binary data. When this method returns null, the data service does not track concurrency.| -||This method is invoked by the data service to obtain the stream that is used when receiving the stream sent from the client. When you implement , you must return a writable stream to which the data service writes received stream data.| -||Returns a namespace-qualified type name that represents the type that the data service runtime must create for the media link entry that is associated with the data stream for the media resource that is being inserted.| - -## Creating the Streaming Data Service - To provide the [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] runtime with access to the implementation, the data service that you create must also implement the interface. The following example shows how to implement the method to return an instance of the `PhotoServiceStreamProvider` class that implements . - - [!code-csharp[Astoria Photo Streaming Service#PhotoServiceStreamingProvider](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_photo_streaming_service/cs/photodata.svc.cs#photoservicestreamingprovider)] - [!code-vb[Astoria Photo Streaming Service#PhotoServiceStreamingProvider](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_photo_streaming_service/vb/photodata.svc.vb#photoservicestreamingprovider)] - - For general information about how to create a data service, see [Configuring the Data Service](../../../../docs/framework/data/wcf/configuring-the-data-service-wcf-data-services.md). - -## Enabling Large Binary Streams in the Hosting Environment - When you create a data service in an [!INCLUDE[vstecasp](../../../../includes/vstecasp-md.md)] Web application, Windows Communication Foundation (WCF) is used to provide the HTTP protocol implementation. By default, WCF limits the size of HTTP messages to only 65K bytes. To be able to stream large binary data to and from the data service, you must also configure the Web application to enable large binary files and to use streams for transfer. To do this, add the following in the `` element of the application's Web.config file: + +A data service can expose large object binary data. This binary data might represent video and audio streams, images, document files, or other types of binary media. When an entity in the data model includes one or more binary properties, the data service returns this binary data encoded as base-64 inside the entry in the response feed. Because loading and serializing large binary data in this manner can affect performance, the [!INCLUDE[ssODataFull](../../../../includes/ssodatafull-md.md)] defines a mechanism for retrieving binary data independent of the entity to which it belongs. This is accomplished by separating the binary data from the entity into one or more data streams. + +- Media resource - binary data that belongs to an entity, such as a video, audio, image or other type of media resource stream. + +- Media link entry - an entity that has a reference to a related media resource stream. + +With [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)], you define a binary resource stream by implementing a streaming data provider. The streaming provider implementation supplies the data service with the media resource stream associated with a specific entity as an object. This implementation enables the data service to accept and return media resources over HTTP as binary data streams of a specified MIME type. + +Configuring a data service to support the streaming of binary data requires the following steps: + +1. Attribute one or more entities in the data model as a media link entry. These entities should not include the binary data to be streamed. Any binary properties of an entity are always returned in the entry as base-64 encoded binary. + +2. Implement the T:System.Data.Services.Providers.IDataServiceStreamProvider interface. + +3. Define a data service that implements the interface. The data service uses the implementation to access the streaming data provider implementation. This method returns the appropriate streaming provider implementation. + +4. Enable large message streams in the Web application configuration. + +5. Enable access to binary resources on the server or in a data source. + +The examples in this topic are based on a sample streaming photo service, which is discussed in depth in the post [Data Services Streaming Provider Series: Implementing a Streaming Provider (Part 1)](https://go.microsoft.com/fwlink/?LinkID=198989). The source code for this sample service is available on the [Streaming Photo Data Service Sample page](https://go.microsoft.com/fwlink/?LinkID=198988) on MSDN Code Gallery. + +## Defining a Media Link Entry in the Data Model + +The data source provider determines the way that an entity is defined as a media link entry in the data model. + +**Entity Framework Provider** + +To indicate that an entity is a media link entry, add the `HasStream` attribute to the entity type definition in the conceptual model, as in the following example: + +[!code-xml[Astoria Photo Streaming Service#HasStream](../../../../samples/snippets/xml/VS_Snippets_Misc/astoria_photo_streaming_service/xml/photodata.edmx#hasstream)] + +You must also add the namespace `xmlns:m=http://schemas.microsoft.com/ado/2007/08/dataservices/metadata` either to the entity or to the root of the .edmx or .csdl file that defines the data model. + +For an example of a data service that uses the [!INCLUDE[adonet_ef](../../../../includes/adonet-ef-md.md)] provider and exposes a media resource, see the post [Data Services Streaming Provider Series: Implementing a Streaming Provider (Part 1)](https://go.microsoft.com/fwlink/?LinkID=198989). + +**Reflection Provider** + +To indicate that an entity is a media link entry, add the to the class that defines the entity type in the reflection provider. + +**Custom Data Service Provider** + +When using custom service providers, you implement the interface to define the metadata for your data service. For more information, see [Custom Data Service Providers](../../../../docs/framework/data/wcf/custom-data-service-providers-wcf-data-services.md). You indicate that a binary resource stream belongs to a by setting the property to `true` on the that represents the entity type, which is a media link entry. + +## Implementing the IDataServiceStreamProvider Interface + +To create a data service that supports binary data streams, you must implement the interface. This implementation enables the data service to return binary data as a stream to the client and consume binary data as a stream sent from the client. The data service creates an instance of this interface whenever it needs to access binary data as a stream. The interface specifies the following members: + +|Member name|Description| +|-----------------|-----------------| +||This method is invoked by the data service to delete the corresponding media resource when its media link entry is deleted. When you implement , this method contains the code that deletes the media resource associated with the supplied media link entry.| +||This method is invoked by the data service to return a media resource as a stream. When you implement , this method contains the code that provides a stream that is used by the data service to the return media resource that is associated with the provided media link entry.| +||This method is invoked by the data service to return the URI that is used to request the media resource for the media link entry. This value is used to create the `src` attribute in the content element of the media link entry and that is used to request the data stream. When this method returns `null`, the data service automatically determines the URI. Use this method when you need to provide clients with direct access to binary data without using the steam provider.| +||This method is invoked by the data service to return the Content-Type value of the media resource that is associated with the specified media link entry.| +||This method is invoked by the data service to return the eTag of the data stream that is associated with the specified entity. This method is used when you manage concurrency for the binary data. When this method returns null, the data service does not track concurrency.| +||This method is invoked by the data service to obtain the stream that is used when receiving the stream sent from the client. When you implement , you must return a writable stream to which the data service writes received stream data.| +||Returns a namespace-qualified type name that represents the type that the data service runtime must create for the media link entry that is associated with the data stream for the media resource that is being inserted.| + +## Creating the Streaming Data Service + +To provide the [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] runtime with access to the implementation, the data service that you create must also implement the interface. The following example shows how to implement the method to return an instance of the `PhotoServiceStreamProvider` class that implements . + +[!code-csharp[Astoria Photo Streaming Service#PhotoServiceStreamingProvider](../../../../samples/snippets/csharp/VS_Snippets_Misc/astoria_photo_streaming_service/cs/photodata.svc.cs#photoservicestreamingprovider)] +[!code-vb[Astoria Photo Streaming Service#PhotoServiceStreamingProvider](../../../../samples/snippets/visualbasic/VS_Snippets_Misc/astoria_photo_streaming_service/vb/photodata.svc.vb#photoservicestreamingprovider)] + +For general information about how to create a data service, see [Configuring the Data Service](../../../../docs/framework/data/wcf/configuring-the-data-service-wcf-data-services.md). + +## Enabling Large Binary Streams in the Hosting Environment + +When you create a data service in an [!INCLUDE[vstecasp](../../../../includes/vstecasp-md.md)] Web application, Windows Communication Foundation (WCF) is used to provide the HTTP protocol implementation. By default, WCF limits the size of HTTP messages to only 65K bytes. To be able to stream large binary data to and from the data service, you must also configure the Web application to enable large binary files and to use streams for transfer. To do this, add the following in the `` element of the application's Web.config file: > [!NOTE] -> You must use a transfer mode to ensure that the binary data in both the request and response messages are streamed and not buffered by WCF. - - For more information, see [Streaming Message Transfer](../../../../docs/framework/wcf/feature-details/streaming-message-transfer.md) and [Transport Quotas](../../../../docs/framework/wcf/feature-details/transport-quotas.md). - - By default, Internet Information Services (IIS) also limits the size of requests to 4MB. To enable your data service to receive streams larger than 4MB when running on IIS, you must also set the `maxRequestLength` attribute of the [httpRuntime Element (ASP.NET Settings Schema)](https://docs.microsoft.com/previous-versions/dotnet/netframework-4.0/e1f13641(v=vs.100)) in the `` configuration section, as shown in the following example: - -## Using Data Streams in a Client Application - The [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] client library enables you to both retrieve and update these exposed resources as binary streams on the client. For more information, see [Working with Binary Data](../../../../docs/framework/data/wcf/working-with-binary-data-wcf-data-services.md). - -## Considerations for Working with a Streaming Provider - The following are things to consider when you implement a streaming provider and when you access media resources from a data service. - -- MERGE requests are not supported for media resources. Use a PUT request to change the media resource of an existing entity. - -- A POST request cannot be used to create a new media link entry. Instead, you must issue a POST request to create a new media resource, and the data service creates a new media link entry with default values. This new entity can be updated by a subsequent MERGE or PUT request. You may also consider caching the entity and make updates in the disposer, such as setting the property value to the value of the Slug header in the POST request. - -- When a POST request is received, the data service calls to create the media resource before it calls to create the media link entry. - -- An implementation of should not return a object. When you use this kind of stream, memory resource issues will occur when the service receives very large data streams. - -- The following are things to consider when storing media resources in a database: - - - A binary property that is a media resource should not be included in the data model. All properties exposed in a data model are returned in the entry in a response feed. - - - To improve performance with a large binary stream, we recommend that you create a custom stream class to store binary data in the database. This class is returned by your implementation and sends the binary data to the database in chunks. For a SQL Server database, we recommend that you use a FILESTREAM to stream data into the database when the binary data is larger than 1MB. - - - Ensure that your database is designed to store the binary large streams that are to be received by your data service. - - - When a client sends a POST request to insert a media link entry with a media resource in a single request, is called to obtain the stream before the data service inserts the new entity into the database. A streaming provider implementation must be able to handle this data service behavior. Consider using a separate data table to store the binary data or store the data stream in a file until after the entity has been inserted into the database. - -- When you implement the , , or methods, you must use the eTag and Content-Type values that are supplied as method parameters. Do not set eTag or Content-Type headers in your provider implementation. - -- By default, the client sends large binary streams by using a chunked HTTP Transfer-Encoding. Because the [!INCLUDE[vstecasp](../../../../includes/vstecasp-md.md)] Development Server does not support this kind of encoding, you cannot use this Web server to host a streaming data service that must accept large binary streams. For more information on [!INCLUDE[vstecasp](../../../../includes/vstecasp-md.md)] Development Server, see [Web Servers in Visual Studio for ASP.NET Web Projects](https://docs.microsoft.com/previous-versions/aspnet/58wxa9w5(v=vs.120)). - - -## Versioning Requirements - The streaming provider has the following [!INCLUDE[ssODataShort](../../../../includes/ssodatashort-md.md)] protocol versioning requirements: - -- The streaming provider requires that the data service support version 2.0 of the [!INCLUDE[ssODataShort](../../../../includes/ssodatashort-md.md)] protocol and later versions. - - For more information, see [Data Service Versioning](../../../../docs/framework/data/wcf/data-service-versioning-wcf-data-services.md). - +> You must use a transfer mode to ensure that the binary data in both the request and response messages are streamed and not buffered by WCF. + +For more information, see [Streaming Message Transfer](../../../../docs/framework/wcf/feature-details/streaming-message-transfer.md) and [Transport Quotas](../../../../docs/framework/wcf/feature-details/transport-quotas.md). + +By default, Internet Information Services (IIS) also limits the size of requests to 4MB. To enable your data service to receive streams larger than 4MB when running on IIS, you must also set the `maxRequestLength` attribute of the [httpRuntime Element (ASP.NET Settings Schema)](https://docs.microsoft.com/previous-versions/dotnet/netframework-4.0/e1f13641(v=vs.100)) in the `` configuration section, as shown in the following example: + +## Using Data Streams in a Client Application + +The [!INCLUDE[ssAstoria](../../../../includes/ssastoria-md.md)] client library enables you to both retrieve and update these exposed resources as binary streams on the client. For more information, see [Working with Binary Data](../../../../docs/framework/data/wcf/working-with-binary-data-wcf-data-services.md). + +## Considerations for Working with a Streaming Provider + +The following are things to consider when you implement a streaming provider and when you access media resources from a data service. + +- MERGE requests are not supported for media resources. Use a PUT request to change the media resource of an existing entity. + +- A POST request cannot be used to create a new media link entry. Instead, you must issue a POST request to create a new media resource, and the data service creates a new media link entry with default values. This new entity can be updated by a subsequent MERGE or PUT request. You may also consider caching the entity and make updates in the disposer, such as setting the property value to the value of the Slug header in the POST request. + +- When a POST request is received, the data service calls to create the media resource before it calls to create the media link entry. + +- An implementation of should not return a object. When you use this kind of stream, memory resource issues will occur when the service receives very large data streams. + +- The following are things to consider when storing media resources in a database: + + - A binary property that is a media resource should not be included in the data model. All properties exposed in a data model are returned in the entry in a response feed. + + - To improve performance with a large binary stream, we recommend that you create a custom stream class to store binary data in the database. This class is returned by your implementation and sends the binary data to the database in chunks. For a SQL Server database, we recommend that you use a FILESTREAM to stream data into the database when the binary data is larger than 1MB. + + - Ensure that your database is designed to store the binary large streams that are to be received by your data service. + + - When a client sends a POST request to insert a media link entry with a media resource in a single request, is called to obtain the stream before the data service inserts the new entity into the database. A streaming provider implementation must be able to handle this data service behavior. Consider using a separate data table to store the binary data or store the data stream in a file until after the entity has been inserted into the database. + +- When you implement the , , or methods, you must use the eTag and Content-Type values that are supplied as method parameters. Do not set eTag or Content-Type headers in your provider implementation. + +- By default, the client sends large binary streams by using a chunked HTTP Transfer-Encoding. Because the [!INCLUDE[vstecasp](../../../../includes/vstecasp-md.md)] Development Server does not support this kind of encoding, you cannot use this Web server to host a streaming data service that must accept large binary streams. For more information on [!INCLUDE[vstecasp](../../../../includes/vstecasp-md.md)] Development Server, see [Web Servers in Visual Studio for ASP.NET Web Projects](https://docs.microsoft.com/previous-versions/aspnet/58wxa9w5(v=vs.120)). + + + +## Versioning Requirements + +The streaming provider has the following [!INCLUDE[ssODataShort](../../../../includes/ssodatashort-md.md)] protocol versioning requirements: + +- The streaming provider requires that the data service support version 2.0 of the [!INCLUDE[ssODataShort](../../../../includes/ssodatashort-md.md)] protocol and later versions. + +For more information, see [Data Service Versioning](../../../../docs/framework/data/wcf/data-service-versioning-wcf-data-services.md). + ## See also - [Data Services Providers](../../../../docs/framework/data/wcf/data-services-providers-wcf-data-services.md) diff --git a/docs/framework/debug-trace-profile/code-contracts.md b/docs/framework/debug-trace-profile/code-contracts.md index 13decedc876a0..a46456b81b7f0 100644 --- a/docs/framework/debug-trace-profile/code-contracts.md +++ b/docs/framework/debug-trace-profile/code-contracts.md @@ -1,197 +1,212 @@ --- title: "Code Contracts" ms.date: "09/05/2018" -dev_langs: +dev_langs: - "csharp" - "vb" -helpviewer_keywords: +helpviewer_keywords: - "Code contracts" ms.assetid: 84526045-496f-489d-8517-a258cf76f040 author: "mairaw" ms.author: "mairaw" --- # Code Contracts -Code contracts provide a way to specify preconditions, postconditions, and object invariants in your code. Preconditions are requirements that must be met when entering a method or property. Postconditions describe expectations at the time the method or property code exits. Object invariants describe the expected state for a class that is in a good state. - - Code contracts include classes for marking your code, a static analyzer for compile-time analysis, and a runtime analyzer. The classes for code contracts can be found in the namespace. - - The benefits of code contracts include the following: - -- Improved testing: Code contracts provide static contract verification, runtime checking, and documentation generation. - -- Automatic testing tools: You can use code contracts to generate more meaningful unit tests by filtering out meaningless test arguments that do not satisfy preconditions. - -- Static verification: The static checker can decide whether there are any contract violations without running the program. It checks for implicit contracts, such as null dereferences and array bounds, and explicit contracts. - -- Reference documentation: The documentation generator augments existing XML documentation files with contract information. There are also style sheets that can be used with [Sandcastle](https://github.com/EWSoftware/SHFB) so that the generated documentation pages have contract sections. - - All .NET Framework languages can immediately take advantage of contracts; you do not have to write a special parser or compiler. A Visual Studio add-in lets you specify the level of code contract analysis to be performed. The analyzers can confirm that the contracts are well-formed (type checking and name resolution) and can produce a compiled form of the contracts in Microsoft intermediate language (MSIL) format. Authoring contracts in Visual Studio lets you take advantage of the standard IntelliSense provided by the tool. - - Most methods in the contract class are conditionally compiled; that is, the compiler emits calls to these methods only when you define a special symbol, CONTRACTS_FULL, by using the `#define` directive. CONTRACTS_FULL lets you write contracts in your code without using `#ifdef` directives; you can produce different builds, some with contracts, and some without. - - For tools and detailed instructions for using code contracts, see [Code Contracts](https://go.microsoft.com/fwlink/?LinkId=152461) on the MSDN DevLabs Web site. - -## Preconditions - You can express preconditions by using the method. Preconditions specify state when a method is invoked. They are generally used to specify valid parameter values. All members that are mentioned in preconditions must be at least as accessible as the method itself; otherwise, the precondition might not be understood by all callers of a method. The condition must have no side-effects. The run-time behavior of failed preconditions is determined by the runtime analyzer. - - For example, the following precondition expresses that parameter `x` must be non-null. - - ```csharp - Contract.Requires(x != null); - ``` - - If your code must throw a particular exception on failure of a precondition, you can use the generic overload of as follows. - - ```csharp - Contract.Requires(x != null, "x"); - ``` - -### Legacy Requires Statements - Most code contains some parameter validation in the form of `if`-`then`-`throw` code. The contract tools recognize these statements as preconditions in the following cases: - -- The statements appear before any other statements in a method. - -- The entire set of such statements is followed by an explicit method call, such as a call to the , , , or method. - - When `if`-`then`-`throw` statements appear in this form, the tools recognize them as legacy `requires` statements. If no other contracts follow the `if`-`then`-`throw` sequence, end the code with the method. - + +Code contracts provide a way to specify preconditions, postconditions, and object invariants in your code. Preconditions are requirements that must be met when entering a method or property. Postconditions describe expectations at the time the method or property code exits. Object invariants describe the expected state for a class that is in a good state. + +Code contracts include classes for marking your code, a static analyzer for compile-time analysis, and a runtime analyzer. The classes for code contracts can be found in the namespace. + +The benefits of code contracts include the following: + +- Improved testing: Code contracts provide static contract verification, runtime checking, and documentation generation. + +- Automatic testing tools: You can use code contracts to generate more meaningful unit tests by filtering out meaningless test arguments that do not satisfy preconditions. + +- Static verification: The static checker can decide whether there are any contract violations without running the program. It checks for implicit contracts, such as null dereferences and array bounds, and explicit contracts. + +- Reference documentation: The documentation generator augments existing XML documentation files with contract information. There are also style sheets that can be used with [Sandcastle](https://github.com/EWSoftware/SHFB) so that the generated documentation pages have contract sections. + +All .NET Framework languages can immediately take advantage of contracts; you do not have to write a special parser or compiler. A Visual Studio add-in lets you specify the level of code contract analysis to be performed. The analyzers can confirm that the contracts are well-formed (type checking and name resolution) and can produce a compiled form of the contracts in Microsoft intermediate language (MSIL) format. Authoring contracts in Visual Studio lets you take advantage of the standard IntelliSense provided by the tool. + +Most methods in the contract class are conditionally compiled; that is, the compiler emits calls to these methods only when you define a special symbol, CONTRACTS_FULL, by using the `#define` directive. CONTRACTS_FULL lets you write contracts in your code without using `#ifdef` directives; you can produce different builds, some with contracts, and some without. + +For tools and detailed instructions for using code contracts, see [Code Contracts](https://go.microsoft.com/fwlink/?LinkId=152461) on the MSDN DevLabs Web site. + +## Preconditions + +You can express preconditions by using the method. Preconditions specify state when a method is invoked. They are generally used to specify valid parameter values. All members that are mentioned in preconditions must be at least as accessible as the method itself; otherwise, the precondition might not be understood by all callers of a method. The condition must have no side-effects. The run-time behavior of failed preconditions is determined by the runtime analyzer. + +For example, the following precondition expresses that parameter `x` must be non-null. + +```csharp +Contract.Requires(x != null); +``` + +If your code must throw a particular exception on failure of a precondition, you can use the generic overload of as follows. + +```csharp +Contract.Requires(x != null, "x"); +``` + +### Legacy Requires Statements + +Most code contains some parameter validation in the form of `if`-`then`-`throw` code. The contract tools recognize these statements as preconditions in the following cases: + +- The statements appear before any other statements in a method. + +- The entire set of such statements is followed by an explicit method call, such as a call to the , , , or method. + +When `if`-`then`-`throw` statements appear in this form, the tools recognize them as legacy `requires` statements. If no other contracts follow the `if`-`then`-`throw` sequence, end the code with the method. + ```csharp if (x == null) throw new ... Contract.EndContractBlock(); // All previous "if" checks are preconditions ``` - - Note that the condition in the preceding test is a negated precondition. (The actual precondition would be `x != null`.) A negated precondition is highly restricted: It must be written as shown in the previous example; that is, it should contain no `else` clauses, and the body of the `then` clause must be a single `throw` statement. The `if` test is subject to both purity and visibility rules (see [Usage Guidelines](#usage_guidelines)), but the `throw` expression is subject only to purity rules. However, the type of the exception thrown must be as visible as the method in which the contract occurs. - -## Postconditions - Postconditions are contracts for the state of a method when it terminates. The postcondition is checked just before exiting a method. The run-time behavior of failed postconditions is determined by the runtime analyzer. - - Unlike preconditions, postconditions may reference members with less visibility. A client may not be able to understand or make use of some of the information expressed by a postcondition using private state, but this does not affect the client's ability to use the method correctly. - -### Standard Postconditions - You can express standard postconditions by using the method. Postconditions express a condition that must be `true` upon normal termination of the method. - - ```csharp - Contract.Ensures(this.F > 0); - ``` - -### Exceptional Postconditions - Exceptional postconditions are postconditions that should be `true` when a particular exception is thrown by a method. You can specify these postconditions by using the method, as the following example shows. - - ```csharp - Contract.EnsuresOnThrow(this.F > 0); - ``` - - The argument is the condition that must be `true` whenever an exception that is a subtype of `T` is thrown. - - There are some exception types that are difficult to use in an exceptional postcondition. For example, using the type for `T` requires the method to guarantee the condition regardless of the type of exception that is thrown, even if it is a stack overflow or other impossible-to-control exception. You should use exceptional postconditions only for specific exceptions that might be thrown when a member is called, for example, when an is thrown for a method call. - -### Special Postconditions - The following methods may be used only within postconditions: - -- You can refer to method return values in postconditions by using the expression `Contract.Result()`, where `T` is replaced by the return type of the method. When the compiler is unable to infer the type, you must explicitly provide it. For example, the C# compiler is unable to infer types for methods that do not take any arguments, so it requires the following postcondition: `Contract.Ensures(0 ())` Methods with a return type of `void` cannot refer to `Contract.Result()` in their postconditions. - -- A prestate value in a postcondition refers to the value of an expression at the start of a method or property. It uses the expression `Contract.OldValue(e)`, where `T` is the type of `e`. You can omit the generic type argument whenever the compiler is able to infer its type. (For example, the C# compiler always infers the type because it takes an argument.) There are several restrictions on what can occur in `e` and the contexts in which an old expression may appear. An old expression cannot contain another old expression. Most importantly, an old expression must refer to a value that existed in the method's precondition state. In other words, it must be an expression that can be evaluated as long as the method's precondition is `true`. Here are several instances of that rule. - - - The value must exist in the method's precondition state. In order to reference a field on an object, the preconditions must guarantee that the object is always non-null. - - - You cannot refer to the method's return value in an old expression: - - ```csharp - Contract.OldValue(Contract.Result() + x) // ERROR - ``` - - - You cannot refer to `out` parameters in an old expression. - - - An old expression cannot depend on the bound variable of a quantifier if the range of the quantifier depends on the return value of the method: - - ```csharp - Contract.ForAll(0, Contract.Result(), i => Contract.OldValue(xs[i]) > 3); // ERROR - ``` - - - An old expression cannot refer to the parameter of the anonymous delegate in a or call unless it is used as an indexer or argument to a method call: - - ```csharp - Contract.ForAll(0, xs.Length, i => Contract.OldValue(xs[i]) > 3); // OK - Contract.ForAll(0, xs.Length, i => Contract.OldValue(i) > 3); // ERROR - ``` - - - An old expression cannot occur in the body of an anonymous delegate if the value of the old expression depends on any of the parameters of the anonymous delegate, unless the anonymous delegate is an argument to the or method: - - ```csharp - Method(... (T t) => Contract.OldValue(... t ...) ...); // ERROR - ``` - - - `Out` parameters present a problem because contracts appear before the body of the method, and most compilers do not allow references to `out` parameters in postconditions. To solve this problem, the class provides the method, which allows a postcondition based on an `out` parameter. - - ```csharp - public void OutParam(out int x) - { - Contract.Ensures(Contract.ValueAtReturn(out x) == 3); - x = 3; - } - ``` - - As with the method, you can omit the generic type parameter whenever the compiler is able to infer its type. The contract rewriter replaces the method call with the value of the `out` parameter. The method may appear only in postconditions. The argument to the method must be an `out` parameter or a field of a structure `out` parameter. The latter is also useful when referring to fields in the postcondition of a structure constructor. - - > [!NOTE] - > Currently, the code contract analysis tools do not check whether `out` parameters are initialized properly and disregard their mention in the postcondition. Therefore, in the previous example, if the line after the contract had used the value of `x` instead of assigning an integer to it, a compiler would not issue the correct error. However, on a build where the CONTRACTS_FULL preprocessor symbol is not defined (such asa release build), the compiler will issue an error. - -## Invariants - Object invariants are conditions that should be true for each instance of a class whenever that object is visible to a client. They express the conditions under which the object is considered to be correct. - - The invariant methods are identified by being marked with the attribute. The invariant methods must contain no code except for a sequence of calls to the method, each of which specifies an individual invariant, as shown in the following example. - + +Note that the condition in the preceding test is a negated precondition. (The actual precondition would be `x != null`.) A negated precondition is highly restricted: It must be written as shown in the previous example; that is, it should contain no `else` clauses, and the body of the `then` clause must be a single `throw` statement. The `if` test is subject to both purity and visibility rules (see [Usage Guidelines](#usage_guidelines)), but the `throw` expression is subject only to purity rules. However, the type of the exception thrown must be as visible as the method in which the contract occurs. + +## Postconditions + +Postconditions are contracts for the state of a method when it terminates. The postcondition is checked just before exiting a method. The run-time behavior of failed postconditions is determined by the runtime analyzer. + +Unlike preconditions, postconditions may reference members with less visibility. A client may not be able to understand or make use of some of the information expressed by a postcondition using private state, but this does not affect the client's ability to use the method correctly. + +### Standard Postconditions + +You can express standard postconditions by using the method. Postconditions express a condition that must be `true` upon normal termination of the method. + ```csharp -[ContractInvariantMethod] -protected void ObjectInvariant () -{ +Contract.Ensures(this.F > 0); +``` + +### Exceptional Postconditions + +Exceptional postconditions are postconditions that should be `true` when a particular exception is thrown by a method. You can specify these postconditions by using the method, as the following example shows. + +```csharp +Contract.EnsuresOnThrow(this.F > 0); +``` + +The argument is the condition that must be `true` whenever an exception that is a subtype of `T` is thrown. + +There are some exception types that are difficult to use in an exceptional postcondition. For example, using the type for `T` requires the method to guarantee the condition regardless of the type of exception that is thrown, even if it is a stack overflow or other impossible-to-control exception. You should use exceptional postconditions only for specific exceptions that might be thrown when a member is called, for example, when an is thrown for a method call. + +### Special Postconditions + +The following methods may be used only within postconditions: + +- You can refer to method return values in postconditions by using the expression `Contract.Result()`, where `T` is replaced by the return type of the method. When the compiler is unable to infer the type, you must explicitly provide it. For example, the C# compiler is unable to infer types for methods that do not take any arguments, so it requires the following postcondition: `Contract.Ensures(0 ())` Methods with a return type of `void` cannot refer to `Contract.Result()` in their postconditions. + +- A prestate value in a postcondition refers to the value of an expression at the start of a method or property. It uses the expression `Contract.OldValue(e)`, where `T` is the type of `e`. You can omit the generic type argument whenever the compiler is able to infer its type. (For example, the C# compiler always infers the type because it takes an argument.) There are several restrictions on what can occur in `e` and the contexts in which an old expression may appear. An old expression cannot contain another old expression. Most importantly, an old expression must refer to a value that existed in the method's precondition state. In other words, it must be an expression that can be evaluated as long as the method's precondition is `true`. Here are several instances of that rule. + + - The value must exist in the method's precondition state. In order to reference a field on an object, the preconditions must guarantee that the object is always non-null. + + - You cannot refer to the method's return value in an old expression: + + ```csharp + Contract.OldValue(Contract.Result() + x) // ERROR + ``` + + - You cannot refer to `out` parameters in an old expression. + + - An old expression cannot depend on the bound variable of a quantifier if the range of the quantifier depends on the return value of the method: + + ```csharp + Contract.ForAll(0, Contract.Result(), i => Contract.OldValue(xs[i]) > 3); // ERROR + ``` + + - An old expression cannot refer to the parameter of the anonymous delegate in a or call unless it is used as an indexer or argument to a method call: + + ```csharp + Contract.ForAll(0, xs.Length, i => Contract.OldValue(xs[i]) > 3); // OK + Contract.ForAll(0, xs.Length, i => Contract.OldValue(i) > 3); // ERROR + ``` + + - An old expression cannot occur in the body of an anonymous delegate if the value of the old expression depends on any of the parameters of the anonymous delegate, unless the anonymous delegate is an argument to the or method: + + ```csharp + Method(... (T t) => Contract.OldValue(... t ...) ...); // ERROR + ``` + + - `Out` parameters present a problem because contracts appear before the body of the method, and most compilers do not allow references to `out` parameters in postconditions. To solve this problem, the class provides the method, which allows a postcondition based on an `out` parameter. + + ```csharp + public void OutParam(out int x) + { + Contract.Ensures(Contract.ValueAtReturn(out x) == 3); + x = 3; + } + ``` + + As with the method, you can omit the generic type parameter whenever the compiler is able to infer its type. The contract rewriter replaces the method call with the value of the `out` parameter. The method may appear only in postconditions. The argument to the method must be an `out` parameter or a field of a structure `out` parameter. The latter is also useful when referring to fields in the postcondition of a structure constructor. + + > [!NOTE] + > Currently, the code contract analysis tools do not check whether `out` parameters are initialized properly and disregard their mention in the postcondition. Therefore, in the previous example, if the line after the contract had used the value of `x` instead of assigning an integer to it, a compiler would not issue the correct error. However, on a build where the CONTRACTS_FULL preprocessor symbol is not defined (such asa release build), the compiler will issue an error. + +## Invariants + +Object invariants are conditions that should be true for each instance of a class whenever that object is visible to a client. They express the conditions under which the object is considered to be correct. + +The invariant methods are identified by being marked with the attribute. The invariant methods must contain no code except for a sequence of calls to the method, each of which specifies an individual invariant, as shown in the following example. + +```csharp +[ContractInvariantMethod] +protected void ObjectInvariant () +{ Contract.Invariant(this.y >= 0); Contract.Invariant(this.x > this.y); ... } -``` - - Invariants are conditionally defined by the CONTRACTS_FULL preprocessor symbol. During run-time checking, invariants are checked at the end of each public method. If an invariant mentions a public method in the same class, the invariant check that would normally happen at the end of that public method is disabled. Instead, the check occurs only at the end of the outermost method call to that class. This also happens if the class is re-entered because of a call to a method on another class. Invariants are not checked for an object finalizer and an implementation. - - -## Usage Guidelines - -### Contract Ordering - The following table shows the order of elements you should use when you write method contracts. - -|`If-then-throw statements`|Backward-compatible public preconditions| -|-|-| -||All public preconditions.| -||All public (normal) postconditions.| -||All public exceptional postconditions.| -||All private/internal (normal) postconditions.| -||All private/internal exceptional postconditions.| -||If using `if`-`then`-`throw` style preconditions without any other contracts, place a call to to indicate that all previous if checks are preconditions.| - - -### Purity - All methods that are called within a contract must be pure; that is, they must not update any preexisting state. A pure method is allowed to modify objects that have been created after entry into the pure method. - - Code contract tools currently assume that the following code elements are pure: - -- Methods that are marked with the . - -- Types that are marked with the (the attribute applies to all the type's methods). - -- Property get accessors. - -- Operators (static methods whose names start with "op", and that have one or two parameters and a non-void return type). - -- Any method whose fully qualified name begins with "System.Diagnostics.Contracts.Contract", "System.String", "System.IO.Path", or "System.Type". - -- Any invoked delegate, provided that the delegate type itself is attributed with the . The delegate types and are considered pure. - - -### Visibility - All members mentioned in a contract must be at least as visible as the method in which they appear. For example, a private field cannot be mentioned in a precondition for a public method; clients cannot validate such a contract before they call the method. However, if the field is marked with the , it is exempt from these rules. - -## Example - The following example shows the use of code contracts. - - [!code-csharp[ContractExample#1](../../../samples/snippets/csharp/VS_Snippets_CLR/contractexample/cs/program.cs#1)] - [!code-vb[ContractExample#1](../../../samples/snippets/visualbasic/VS_Snippets_CLR/contractexample/vb/program.vb#1)] +``` + +Invariants are conditionally defined by the CONTRACTS_FULL preprocessor symbol. During run-time checking, invariants are checked at the end of each public method. If an invariant mentions a public method in the same class, the invariant check that would normally happen at the end of that public method is disabled. Instead, the check occurs only at the end of the outermost method call to that class. This also happens if the class is re-entered because of a call to a method on another class. Invariants are not checked for an object finalizer and an implementation. + + + +## Usage Guidelines + +### Contract Ordering + +The following table shows the order of elements you should use when you write method contracts. + +|`If-then-throw statements`|Backward-compatible public preconditions| +|-|-| +||All public preconditions.| +||All public (normal) postconditions.| +||All public exceptional postconditions.| +||All private/internal (normal) postconditions.| +||All private/internal exceptional postconditions.| +||If using `if`-`then`-`throw` style preconditions without any other contracts, place a call to to indicate that all previous if checks are preconditions.| + + + +### Purity + +All methods that are called within a contract must be pure; that is, they must not update any preexisting state. A pure method is allowed to modify objects that have been created after entry into the pure method. + +Code contract tools currently assume that the following code elements are pure: + +- Methods that are marked with the . + +- Types that are marked with the (the attribute applies to all the type's methods). + +- Property get accessors. + +- Operators (static methods whose names start with "op", and that have one or two parameters and a non-void return type). + +- Any method whose fully qualified name begins with "System.Diagnostics.Contracts.Contract", "System.String", "System.IO.Path", or "System.Type". + +- Any invoked delegate, provided that the delegate type itself is attributed with the . The delegate types and are considered pure. + + + +### Visibility + +All members mentioned in a contract must be at least as visible as the method in which they appear. For example, a private field cannot be mentioned in a precondition for a public method; clients cannot validate such a contract before they call the method. However, if the field is marked with the , it is exempt from these rules. + +## Example + +The following example shows the use of code contracts. + +[!code-csharp[ContractExample#1](../../../samples/snippets/csharp/VS_Snippets_CLR/contractexample/cs/program.cs#1)] +[!code-vb[ContractExample#1](../../../samples/snippets/visualbasic/VS_Snippets_CLR/contractexample/vb/program.vb#1)] diff --git a/docs/framework/debug-trace-profile/how-to-create-and-initialize-trace-listeners.md b/docs/framework/debug-trace-profile/how-to-create-and-initialize-trace-listeners.md index 9e07241d2db22..bffddcc891938 100644 --- a/docs/framework/debug-trace-profile/how-to-create-and-initialize-trace-listeners.md +++ b/docs/framework/debug-trace-profile/how-to-create-and-initialize-trace-listeners.md @@ -1,10 +1,10 @@ --- title: "How to: Create and Initialize Trace Listeners" ms.date: "03/30/2017" -dev_langs: +dev_langs: - "csharp" - "vb" -helpviewer_keywords: +helpviewer_keywords: - "initializing trace listeners" - "trace listeners, creating" - "trace listeners, initializing" @@ -15,79 +15,80 @@ author: "mairaw" ms.author: "mairaw" --- # How to: Create and Initialize Trace Listeners -The and classes send messages to objects called listeners that receive and process these messages. One such listener, the , is automatically created and initialized when tracing or debugging is enabled. If you want or output to be directed to any additional sources, you must create and initialize additional trace listeners. - - The listeners you create should reflect your application's needs. For example, if you want a text record of all trace output, create a listener, which writes all output to a new text file when it is enabled. On the other hand, if you want to view output only during application execution, create a listener, which directs all output to a console window. The can direct trace output to an event log. For more information, see [Trace Listeners](../../../docs/framework/debug-trace-profile/trace-listeners.md). - - You can create trace listeners in an [application configuration file](../../../docs/framework/configure-apps/index.md) or in your code. We recommend the use of application configuration files, because they let you add, modify, or remove trace listeners without having to change your code. - -### To create and use a trace listener by using a configuration file - -1. Declare your trace listener in your application configuration file. If the listener you are creating requires any other objects, declare them as well. The following example shows how to create a listener called `myListener` that writes to the text file `TextWriterOutput.log`. - - ```xml - - - - - - - - - - - ``` - -2. Use the class in your code to write a message to the trace listeners. - - ```vb - Trace.TraceInformation("Test message.") - ' You must close or flush the trace to empty the output buffer. - Trace.Flush() - ``` - - ```csharp - Trace.TraceInformation("Test message."); - // You must close or flush the trace to empty the output buffer. - Trace.Flush(); - ``` - -### To create and use a trace listener in code - -- Add the trace listener to the collection and send trace information to the listeners. - - ```vb - Trace.Listeners.Add(New TextWriterTraceListener("TextWriterOutput.log", "myListener")) - Trace.TraceInformation("Test message.") - ' You must close or flush the trace to empty the output buffer. - Trace.Flush() - ``` - - ```csharp - Trace.Listeners.Add(new TextWriterTraceListener("TextWriterOutput.log", "myListener")); - Trace.TraceInformation("Test message."); - // You must close or flush the trace to empty the output buffer. - Trace.Flush(); - ``` - - - or - - -- If you do not want your listener to receive trace output, do not add it to the collection. You can emit output through a listener independent of the collection by calling the listener's own output methods. The following example shows how to write a line to a listener that is not in the collection. - - ```vb - Dim myListener As New TextWriterTraceListener("TextWriterOutput.log", "myListener") - myListener.WriteLine("Test message.") - ' You must close or flush the trace listener to empty the output buffer. - myListener.Flush() - ``` - - ```csharp - TextWriterTraceListener myListener = new TextWriterTraceListener("TextWriterOutput.log", "myListener"); - myListener.WriteLine("Test message."); - // You must close or flush the trace listener to empty the output buffer. - myListener.Flush(); - ``` - + +The and classes send messages to objects called listeners that receive and process these messages. One such listener, the , is automatically created and initialized when tracing or debugging is enabled. If you want or output to be directed to any additional sources, you must create and initialize additional trace listeners. + +The listeners you create should reflect your application's needs. For example, if you want a text record of all trace output, create a listener, which writes all output to a new text file when it is enabled. On the other hand, if you want to view output only during application execution, create a listener, which directs all output to a console window. The can direct trace output to an event log. For more information, see [Trace Listeners](../../../docs/framework/debug-trace-profile/trace-listeners.md). + +You can create trace listeners in an [application configuration file](../../../docs/framework/configure-apps/index.md) or in your code. We recommend the use of application configuration files, because they let you add, modify, or remove trace listeners without having to change your code. + +### To create and use a trace listener by using a configuration file + +1. Declare your trace listener in your application configuration file. If the listener you are creating requires any other objects, declare them as well. The following example shows how to create a listener called `myListener` that writes to the text file `TextWriterOutput.log`. + + ```xml + + + + + + + + + + + ``` + +2. Use the class in your code to write a message to the trace listeners. + + ```vb + Trace.TraceInformation("Test message.") + ' You must close or flush the trace to empty the output buffer. + Trace.Flush() + ``` + + ```csharp + Trace.TraceInformation("Test message."); + // You must close or flush the trace to empty the output buffer. + Trace.Flush(); + ``` + +### To create and use a trace listener in code + +- Add the trace listener to the collection and send trace information to the listeners. + + ```vb + Trace.Listeners.Add(New TextWriterTraceListener("TextWriterOutput.log", "myListener")) + Trace.TraceInformation("Test message.") + ' You must close or flush the trace to empty the output buffer. + Trace.Flush() + ``` + + ```csharp + Trace.Listeners.Add(new TextWriterTraceListener("TextWriterOutput.log", "myListener")); + Trace.TraceInformation("Test message."); + // You must close or flush the trace to empty the output buffer. + Trace.Flush(); + ``` + + \- or - + +- If you do not want your listener to receive trace output, do not add it to the collection. You can emit output through a listener independent of the collection by calling the listener's own output methods. The following example shows how to write a line to a listener that is not in the collection. + + ```vb + Dim myListener As New TextWriterTraceListener("TextWriterOutput.log", "myListener") + myListener.WriteLine("Test message.") + ' You must close or flush the trace listener to empty the output buffer. + myListener.Flush() + ``` + + ```csharp + TextWriterTraceListener myListener = new TextWriterTraceListener("TextWriterOutput.log", "myListener"); + myListener.WriteLine("Test message."); + // You must close or flush the trace listener to empty the output buffer. + myListener.Flush(); + ``` + ## See also - [Trace Listeners](../../../docs/framework/debug-trace-profile/trace-listeners.md) diff --git a/docs/framework/deployment/deployment-guide-for-developers.md b/docs/framework/deployment/deployment-guide-for-developers.md index 3403e7a680f8c..a8836a38f12f1 100644 --- a/docs/framework/deployment/deployment-guide-for-developers.md +++ b/docs/framework/deployment/deployment-guide-for-developers.md @@ -2,7 +2,7 @@ title: ".NET Framework deployment guide for developers" ms.custom: "updateeachrelease" ms.date: "04/10/2018" -helpviewer_keywords: +helpviewer_keywords: - "developer's guide, deploying .NET Framework" - "deployment [.NET Framework], developer's guide" ms.assetid: 094d043e-33c4-40ba-a503-e0b20b55f4cf @@ -10,6 +10,7 @@ author: "rpetrusha" ms.author: "ronpet" --- # .NET Framework deployment guide for developers + This topic provides information for developers who want to install any version of the .NET Framework from the .NET Framework 4.5 to the [!INCLUDE[net_current](../../../includes/net-current-version.md)] with their apps. For download links, see the section [Redistributable Packages](#redistributable-packages). You can also download the redistributable packages and language packs from these Microsoft Download Center pages: @@ -53,10 +54,11 @@ For download links, see the section [Redistributable Packages](#redistributable- - The .NET Framework 4.5 redistributable was updated on October 9, 2012 to correct an issue related to an improper timestamp on a digital certificate, which caused the digital signature on files produced and signed by Microsoft to expire prematurely. If you previously installed the .NET Framework 4.5 redistributable package dated August 16, 2012, we recommend that you update your copy with the latest redistributable from the [Microsoft Download Center](https://go.microsoft.com/fwlink/p/?LinkId=245484). For more information about this issue, see [Microsoft Security Advisory 2749655](https://docs.microsoft.com/security-updates/SecurityAdvisories/2012/2749655). - For information about how a system administrator can deploy the .NET Framework and its system dependencies across a network, see [Deployment Guide for Administrators](../../../docs/framework/deployment/guide-for-administrators.md). +For information about how a system administrator can deploy the .NET Framework and its system dependencies across a network, see [Deployment Guide for Administrators](../../../docs/framework/deployment/guide-for-administrators.md). ## Deployment options for your app - When you're ready to publish your app to a web server or other centralized location so that users can install it, you can choose from several deployment methods. Some of these are provided with Visual Studio. The following table lists the deployment options for your app and specifies the .NET Framework redistributable package that supports each option. In addition to these, you can write a custom setup program for your app; for more information, see the section [Chaining the .NET Framework Installation to Your App's Setup](#chaining). + +When you're ready to publish your app to a web server or other centralized location so that users can install it, you can choose from several deployment methods. Some of these are provided with Visual Studio. The following table lists the deployment options for your app and specifies the .NET Framework redistributable package that supports each option. In addition to these, you can write a custom setup program for your app; for more information, see the section [Chaining the .NET Framework Installation to Your App's Setup](#chaining). |Deployment strategy for your app|Deployment methods available|.NET Framework redistributable to use| |--------------------------------------|----------------------------------|-------------------------------------------| @@ -65,7 +67,8 @@ For download links, see the section [Redistributable Packages](#redistributable- |Install from a local area network (for enterprise apps)|- [ClickOnce](#clickonce-deployment)|Either [web installer](#redistributable-packages) (see [ClickOnce](#clickonce-deployment) for restrictions) or [offline installer](#redistributable-packages)| ## Redistributable Packages - The .NET Framework is available in two redistributable packages: web installer (bootstrapper) and offline installer (stand-alone redistributable). The following table compares the two packages. + +The .NET Framework is available in two redistributable packages: web installer (bootstrapper) and offline installer (stand-alone redistributable). The following table compares the two packages. ||Web installer|Offline installer| |-|-------------------|-----------------------| @@ -76,40 +79,43 @@ For download links, see the section [Redistributable Packages](#redistributable- |Deployment method|Supports all methods:

- [ClickOnce](#clickonce-deployment)
- [InstallAware](#installaware-deployment)
- [InstallShield](#installshield-deployment)
- [Windows Installer XML (WiX)](#wix)
- [Manual installation](#installing_manually)
- [Custom setup (chaining)](#chaining)|Supports all methods:

- [ClickOnce](#clickonce-deployment)
- [InstallAware](#installaware-deployment)
- [InstallShield](#installshield-deployment)
- [Windows Installer XML (WiX)](#wix)
- [Manual installation](#installing_manually)
- [Custom setup (chaining)](#chaining)| |Location of download for ClickOnce deployment|Microsoft Download Center:

- [.NET Framework 4.7.2](https://go.microsoft.com/fwlink/?LinkId=863262)
- [.NET Framework 4.7.1](https://go.microsoft.com/fwlink/?LinkId=852092)
- [.NET Framework 4.7](https://go.microsoft.com/fwlink/?LinkId=825298)
- [.NET Framework 4.6.2](https://go.microsoft.com/fwlink/?LinkId=780596)
- [.NET Framework 4.6.1](https://go.microsoft.com/fwlink/?LinkId=671728)
- [.NET Framework 4.6](https://go.microsoft.com/fwlink/?LinkId=528222)
- [.NET Framework 4.5.2](https://go.microsoft.com/fwlink/?LinkId=397703)
- [.NET Framework 4.5.1](https://go.microsoft.com/fwlink/p/?LinkId=310158)
- [.NET Framework 4.5](https://go.microsoft.com/fwlink/p/?LinkId=245484)|Your own server or the Microsoft Download Center:

- [.NET Framework 4.7.2](https://go.microsoft.com/fwlink/?LinkId=863265)
- [.NET Framework 4.7.1](https://go.microsoft.com/fwlink/?LinkId=852104)
- [.NET Framework 4.7](https://go.microsoft.com/fwlink/?LinkId=825302)
- [.NET Framework 4.6.2](https://go.microsoft.com/fwlink/?LinkId=780600)
- [.NET Framework 4.6.1](https://go.microsoft.com/fwlink/?LinkId=671743)
- [.NET Framework 4.6](https://go.microsoft.com/fwlink/?LinkId=528232)
- [.NET Framework 4.5.2](https://go.microsoft.com/fwlink/p/?LinkId=397706)
- [.NET Framework 4.5.1](https://go.microsoft.com/fwlink/p/?LinkId=310159)
- [.NET Framework 4.5](https://go.microsoft.com/fwlink/p/?LinkId=245484)| - \* The offline installer is larger because it contains the components for all the target platforms. When you finish running setup, the Windows operating system caches only the installer that was used. If the offline installer is deleted after the installation, the disk space used is the same as that used by the web installer. If the tool you use (for example, [InstallAware](#installaware-deployment) or [InstallShield](#installshield-deployment)) to create your app's setup program provides a setup file folder that is removed after installation, the offline installer can be automatically deleted by placing it into the setup folder. +\* The offline installer is larger because it contains the components for all the target platforms. When you finish running setup, the Windows operating system caches only the installer that was used. If the offline installer is deleted after the installation, the disk space used is the same as that used by the web installer. If the tool you use (for example, [InstallAware](#installaware-deployment) or [InstallShield](#installshield-deployment)) to create your app's setup program provides a setup file folder that is removed after installation, the offline installer can be automatically deleted by placing it into the setup folder. - ** If you're using the web installer with custom setup, you can use default language settings based on the user's Multilingual User Interface (MUI) setting, or specify another language pack by using the `/LCID` option on the command line. See the section [Chaining by Using the Default .NET Framework UI](#chaining_default) for examples. +\*\* If you're using the web installer with custom setup, you can use default language settings based on the user's Multilingual User Interface (MUI) setting, or specify another language pack by using the `/LCID` option on the command line. See the section [Chaining by Using the Default .NET Framework UI](#chaining_default) for examples. ## Deployment methods + Four deployment methods are available: - You can set a dependency on the .NET Framework. You can specify the .NET Framework as a prerequisite in your app's installation, using one of these methods: - - Use [ClickOnce deployment](#clickonce-deployment) (available with Visual Studio) + - Use [ClickOnce deployment](#clickonce-deployment) (available with Visual Studio) - - Create an [InstallAware project](#installaware-deployment) (free edition available for Visual Studio users) + - Create an [InstallAware project](#installaware-deployment) (free edition available for Visual Studio users) - - Create an [InstallShield project](#installshield-deployment) (available with Visual Studio) + - Create an [InstallShield project](#installshield-deployment) (available with Visual Studio) - - Use the [Windows Installer XML (WiX) toolset](#wix) + - Use the [Windows Installer XML (WiX) toolset](#wix) - You can ask your users to [install the .NET Framework manually](#installing_manually). - You can chain (include) the .NET Framework setup process in your app's setup, and decide how you want to handle the .NET Framework installation experience: - - [Use the default UI](#chaining_default). Let the .NET Framework installer provide the installation experience. + - [Use the default UI](#chaining_default). Let the .NET Framework installer provide the installation experience. - - [Customize the UI](#chaining_custom) to present a unified installation experience and to monitor the .NET Framework installation progress. + - [Customize the UI](#chaining_custom) to present a unified installation experience and to monitor the .NET Framework installation progress. - These deployment methods are discussed in detail in the following sections. +These deployment methods are discussed in detail in the following sections. ## Setting a dependency on the .NET Framework + If you use ClickOnce, InstallAware, InstallShield, or WiX to deploy your app, you can add a dependency on the .NET Framework so it can be installed as part of your app. ### ClickOnce deployment - ClickOnce deployment is available for projects that are created with Visual Basic and Visual C#, but it is not available for Visual C++. - In Visual Studio, to choose ClickOnce deployment and add a dependency on the .NET Framework: +ClickOnce deployment is available for projects that are created with Visual Basic and Visual C#, but it is not available for Visual C++. + +In Visual Studio, to choose ClickOnce deployment and add a dependency on the .NET Framework: 1. Open the app project you want to publish. @@ -129,12 +135,15 @@ If you use ClickOnce, InstallAware, InstallShield, or WiX to deploy your app, yo 8. In the **Property Pages** dialog box, choose **OK**. - + + ### InstallAware deployment + InstallAware builds Windows app (APPX), Windows Installer (MSI), Native Code (EXE), and App-V (Application Virtualization) packages from a single source. Easily [include any version of the .NET Framework](https://www.installaware.com/one-click-pre-requisite-installer.htm) in your setup, optionally customizing the installation by [editing the default scripts](https://www.installaware.com/msicode.htm). For example, InstallAware pre-installs certificates on Windows 7, without which the .NET Framework 4.7 setup fails. For more information on InstallAware, see the [InstallAware for Windows Installer](https://www.installaware.com/) website. ### InstallShield deployment - In Visual Studio, to choose InstallShield deployment and add a dependency on the .NET Framework: + +In Visual Studio, to choose InstallShield deployment and add a dependency on the .NET Framework: 1. On the Visual Studio menu bar, choose **File**, **New**, **Project**. @@ -149,44 +158,52 @@ InstallAware builds Windows app (APPX), Windows Installer (MSI), Native Code (EX 6. Go to **Installation Requirements** and select the operating systems and the version of the .NET Framework you want to install. 7. Open the shortcut menu for your setup project and choose **Build**. - - + + + ### Windows Installer XML (WiX) deployment - The Windows Installer XML (WiX) toolset builds Windows installation packages from XML source code. WiX supports a command-line environment that can be integrated into your build processes to build MSI and MSM setup packages. By using WiX, you can [specify the .NET Framework as a prerequisite](http://wixtoolset.org/documentation/manual/v3/howtos/redistributables_and_install_checks/install_dotnet.html), or [create a chainer](http://wixtoolset.org/documentation/manual/v3/xsd/wix/exepackage.html) to fully control the .NET Framework deployment experience. For more information about WiX, see the [Windows Installer XML (WiX) toolset](http://wixtoolset.org/) website. - +The Windows Installer XML (WiX) toolset builds Windows installation packages from XML source code. WiX supports a command-line environment that can be integrated into your build processes to build MSI and MSM setup packages. By using WiX, you can [specify the .NET Framework as a prerequisite](http://wixtoolset.org/documentation/manual/v3/howtos/redistributables_and_install_checks/install_dotnet.html), or [create a chainer](http://wixtoolset.org/documentation/manual/v3/xsd/wix/exepackage.html) to fully control the .NET Framework deployment experience. For more information about WiX, see the [Windows Installer XML (WiX) toolset](http://wixtoolset.org/) website. + + + ## Installing the .NET Framework manually - In some situations, it might be impractical to automatically install the .NET Framework with your app. In that case, you can have users install the .NET Framework themselves. The redistributable package is available in [two packages](#redistributable-packages). In your setup process, provide instructions for how users should locate and install the .NET Framework. - +In some situations, it might be impractical to automatically install the .NET Framework with your app. In that case, you can have users install the .NET Framework themselves. The redistributable package is available in [two packages](#redistributable-packages). In your setup process, provide instructions for how users should locate and install the .NET Framework. + + + ## Chaining the .NET Framework installation to your app's setup - If you're creating a custom setup program for your app, you can chain (include) the .NET Framework setup process in your app's setup process. Chaining provides two UI options for the .NET Framework installation: + +If you're creating a custom setup program for your app, you can chain (include) the .NET Framework setup process in your app's setup process. Chaining provides two UI options for the .NET Framework installation: - Use the default UI provided by the .NET Framework installer. - Create a custom UI for the .NET Framework installation for consistency with your app's setup program. - Both methods allow you to use either the web installer or the offline installer. Each package has its advantages: +Both methods allow you to use either the web installer or the offline installer. Each package has its advantages: - If you use the web installer, the .NET Framework setup process will decide which installation package is required, and download and install only that package from the web. - If you use the offline installer, you can include the complete set of .NET Framework installation packages with your redistribution media so that your users don't have to download any additional files from the web during setup. - + + ### Chaining by using the default .NET Framework UI - To silently chain the .NET Framework installation process and let the .NET Framework installer provide the UI, add the following command to your setup program: + +To silently chain the .NET Framework installation process and let the .NET Framework installer provide the UI, add the following command to your setup program: ``` <.NET Framework redistributable> /q /norestart /ChainingPackage ``` - For example, if your executable program is Contoso.exe and you want to silently install the [!INCLUDE[net_v45](../../../includes/net-v45-md.md)] offline redistributable package, use the command: +For example, if your executable program is Contoso.exe and you want to silently install the [!INCLUDE[net_v45](../../../includes/net-v45-md.md)] offline redistributable package, use the command: ``` dotNetFx45_Full_x86_x64.exe /q /norestart /ChainingPackage Contoso ``` - You can use additional command-line options to customize the installation. For example: +You can use additional command-line options to customize the installation. For example: - To provide a way for users to close running .NET Framework apps to minimize system restarts, set passive mode and use the `/showrmui` option as follows: @@ -207,13 +224,15 @@ dotNetFx45_Full_x86_x64.exe /q /norestart /ChainingPackage Contoso > [!NOTE] > Different language packs may have different release dates. If the language pack you specify is not available at the download center, setup will install the .NET Framework without the language pack. If the .NET Framework is already installed on the user’s computer, the setup will install only the language pack. - For a complete list of options, see the [Command-Line Options](#command-line-options) section. +For a complete list of options, see the [Command-Line Options](#command-line-options) section. - For common return codes, see the [Return Codes](#return-codes) section. +For common return codes, see the [Return Codes](#return-codes) section. + ### Chaining by Using a Custom UI - If you have a custom setup package, you may want to silently launch and track the .NET Framework setup while showing your own view of the setup progress. If this is the case, make sure that your code covers the following: + +If you have a custom setup package, you may want to silently launch and track the .NET Framework setup while showing your own view of the setup progress. If this is the case, make sure that your code covers the following: - Check for [.NET Framework hardware and software requirements](../../../docs/framework/get-started/system-requirements.md). @@ -233,8 +252,10 @@ dotNetFx45_Full_x86_x64.exe /q /norestart /ChainingPackage Contoso - [Troubleshoot](#troubleshooting). + ### Detecting the .NET Framework - The .NET Framework installer writes registry keys when installation is successful. You can test whether the [!INCLUDE[net_v45](../../../includes/net-v45-md.md)] or later is installed by checking the `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full` folder in the registry for a `DWORD` value named `Release`. (Note that "NET Framework Setup" doesn't begin with a period.) The existence of this key indicates that the [!INCLUDE[net_v45](../../../includes/net-v45-md.md)] or a later version has been installed on that computer. The value of `Release` indicates which version of the .NET Framework is installed. + +The .NET Framework installer writes registry keys when installation is successful. You can test whether the [!INCLUDE[net_v45](../../../includes/net-v45-md.md)] or later is installed by checking the `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full` folder in the registry for a `DWORD` value named `Release`. (Note that "NET Framework Setup" doesn't begin with a period.) The existence of this key indicates that the [!INCLUDE[net_v45](../../../includes/net-v45-md.md)] or a later version has been installed on that computer. The value of `Release` indicates which version of the .NET Framework is installed. > [!IMPORTANT] > You should check for a value **greater than or equal to** the release keyword value when attempting to detect whether a specific version is present. @@ -259,9 +280,10 @@ dotNetFx45_Full_x86_x64.exe /q /norestart /ChainingPackage Contoso |[!INCLUDE[net_v45](../../../includes/net-v45-md.md)]|378389| ### Detecting the language packs - You can test whether a specific language pack is installed by checking the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\\*LCID* folder in the registry for a DWORD value named `Release`. (Note that "NET Framework Setup" doesn't begin with a period.) *LCID* specifies a locale identifier; see [supported languages](#supported-languages) for a list of these. - For example, to detect whether the full Japanese language pack (LCID=1041) is installed, check for the following values in the registry: +You can test whether a specific language pack is installed by checking the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\\*LCID* folder in the registry for a DWORD value named `Release`. (Note that "NET Framework Setup" doesn't begin with a period.) *LCID* specifies a locale identifier; see [supported languages](#supported-languages) for a list of these. + +For example, to detect whether the full Japanese language pack (LCID=1041) is installed, check for the following values in the registry: ``` Key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\1041 @@ -269,11 +291,13 @@ Name: Release Type: DWORD ``` - To determine whether the final release version of a language pack is installed for a particular version of the .NET Framework from 4.5 through 4.7.2, check the value of the RELEASE key DWORD value described in the previous section, [Detecting the .NET Framework](#detect_net). +To determine whether the final release version of a language pack is installed for a particular version of the .NET Framework from 4.5 through 4.7.2, check the value of the RELEASE key DWORD value described in the previous section, [Detecting the .NET Framework](#detect_net). + + - ### Chaining the language packs to your app setup - The .NET Framework provides a set of stand-alone language pack executable files that contain localized resources for specific cultures. The language packs are available from the Microsoft Download Center: + +The .NET Framework provides a set of stand-alone language pack executable files that contain localized resources for specific cultures. The language packs are available from the Microsoft Download Center: - [.NET Framework 4.7.2 language packs](https://go.microsoft.com/fwlink/p/?LinkId=863258) @@ -296,22 +320,23 @@ Type: DWORD > [!IMPORTANT] > The language packs don't contain the .NET Framework components that are required to run an app; you must install the .NET Framework by using the web or offline installer before you install a language pack. - Starting with the [!INCLUDE[net_v451](../../../includes/net-v451-md.md)], the package names take the form NDP<`version`>-KB<`number`>-x86-x64-AllOS-<`culture`>.exe, where `version` is the version number of the .NET Framework, `number` is a Microsoft Knowledge Base article number, and `culture` specifies a [country/region](#supported-languages). An example of one of these packages is `NDP452-KB2901907-x86-x64-AllOS-JPN.exe`. Package names are listed in the [Redistributable Packages](#redistributable-packages) section earlier in this article. +Starting with the [!INCLUDE[net_v451](../../../includes/net-v451-md.md)], the package names take the form NDP<`version`>-KB<`number`>-x86-x64-AllOS-<`culture`>.exe, where `version` is the version number of the .NET Framework, `number` is a Microsoft Knowledge Base article number, and `culture` specifies a [country/region](#supported-languages). An example of one of these packages is `NDP452-KB2901907-x86-x64-AllOS-JPN.exe`. Package names are listed in the [Redistributable Packages](#redistributable-packages) section earlier in this article. - To install a language pack with the .NET Framework offline installer, you must chain it to your app's setup. For example, to deploy the [!INCLUDE[net_v451](../../../includes/net-v451-md.md)] offline installer with the Japanese language pack, use the following command: +To install a language pack with the .NET Framework offline installer, you must chain it to your app's setup. For example, to deploy the [!INCLUDE[net_v451](../../../includes/net-v451-md.md)] offline installer with the Japanese language pack, use the following command: ``` NDP451-KB2858728-x86-x64-AllOS-JPN.exe /q /norestart /ChainingPackage ``` - You do not have to chain the language packs if you use the web installer; setup will install the language pack that matches the user's MUI setting. If you want to install a different language, you can use the `/LCID` option to specify a language pack. +You do not have to chain the language packs if you use the web installer; setup will install the language pack that matches the user's MUI setting. If you want to install a different language, you can use the `/LCID` option to specify a language pack. - For a complete list of command-line options, see the [Command-Line Options](#command-line-options) section. +For a complete list of command-line options, see the [Command-Line Options](#command-line-options) section. ### Troubleshooting #### Return codes - The following table lists the most common return codes for the .NET Framework redistributable installer. The return codes are the same for all versions of the installer. For links to detailed information, see the next section. + +The following table lists the most common return codes for the .NET Framework redistributable installer. The return codes are the same for all versions of the installer. For links to detailed information, see the next section. |Return code|Description| |-----------------|-----------------| @@ -323,7 +348,8 @@ NDP451-KB2858728-x86-x64-AllOS-JPN.exe /q /norestart /ChainingPackage [!IMPORTANT] > For Windows 7 and earlier operating systems, uninstalling the [!INCLUDE[net_v451](../../../includes/net-v451-md.md)], 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, or 4.7.2 doesn't restore [!INCLUDE[net_v45](../../../includes/net-v45-md.md)] files, and uninstalling the [!INCLUDE[net_v45](../../../includes/net-v45-md.md)] doesn't restore [!INCLUDE[net_v40_short](../../../includes/net-v40-short-md.md)] files. If you want to go back to the older version, you must reinstall it and any updates to it. @@ -347,7 +375,8 @@ NDP451-KB2858728-x86-x64-AllOS-JPN.exe /q /norestart /ChainingPackage -## Type Library Exporter - The [Type Library Exporter (Tlbexp.exe)](../tools/tlbexp-exe-type-library-exporter.md) is a command-line tool that converts the classes and interfaces contained in an assembly to a COM type library. Once the type information of the class is available, COM clients can create an instance of the .NET class and call the methods of the instance, just as if it were a COM object. Tlbexp.exe converts an entire assembly at one time. You cannot use Tlbexp.exe to generate type information for a subset of the types defined in an assembly. - - -## TypeLibConverter Class - The class, located in the **System.Runtime.Interop** namespace, converts the classes and interfaces contained in an assembly to a COM type library. This API produces the same type information as the Type Library Exporter, described in the previous section. - - The **TypeLibConverter class** implements the . - - -## Assembly Registration Tool - The [Assembly Registration Tool (Regasm.exe)](../tools/regasm-exe-assembly-registration-tool.md) can generate and register a type library when you apply the **/tlb:** option. COM clients require that type libraries be installed in the Windows registry. Without this option, Regasm.exe only registers the types in an assembly, not the type library. Registering the types in an assembly and registering the type library are distinct activities. - - -## .NET Services Installation Tool - The [.NET Services Installation Tool (Regsvcs.exe)](../tools/regsvcs-exe-net-services-installation-tool.md) adds managed classes to Windows 2000 Component Services and combines several tasks within a single tool. In addition to loading and registering an assembly, Regsvcs.exe can generate, register, and install the type library into an existing COM+ 1.0 application. - + +COM developers can benefit from the following information about the managed types they plan to incorporate in their application: + +- A list of types that COM applications can consume + + Some managed types are invisible to COM; some are visible but not creatable; and some are both visible and creatable. An assembly can comprise any combination of invisible, visible, not creatable, and creatable types. For completeness, identify the types in an assembly that you intend to expose to COM, especially when those types are a subset of the types exposed to the .NET Framework. + + For additional information, see [Qualifying .NET Types for Interoperation](qualifying-net-types-for-interoperation.md). + +- Versioning instructions + + Managed classes that implement the class interface (a COM interop-generated interface) are subject to versioning restrictions. + + For guidelines on using the class interface, see [Introducing the class interface](com-callable-wrapper.md#introducing-the-class-interface). + +- Deployment instructions + + Strong-named assemblies that are signed by a publisher can be installed into the global assembly cache. Unsigned assemblies must be installed on the user's machine as private assemblies. + + For additional information, see [Assembly Security Considerations](../app-domains/assembly-security-considerations.md). + +- Type library inclusion + + Most types require a type library when consumed by a COM application. You can generate a type library or have COM developers perform this task. The [!INCLUDE[winsdklong](../../../includes/winsdklong-md.md)] provides the following options for generating a type library: + + - [Type Library Exporter](#cpconpackagingassemblyforcomanchor1) + + - [TypeLibConverter Class](#cpconpackagingassemblyforcomanchor2) + + - [Assembly Registration Tool](#cpconpackagingassemblyforcomanchor3) + + - [.NET Services Installation Tool](#cpconpackagingassemblyforcomanchor4) + + Regardless of the mechanism you choose, only public types defined in the assembly you supply are included in the generated type library. + + You can package a type library as a separate file or embed it as Win32 resource file within a .NET-based application. Microsoft Visual Basic 6.0 performed this task for you automatically; however, when using [!INCLUDE[vbprvbext](../../../includes/vbprvbext-md.md)], you must embed your type library manually. For instructions, see [How to: Embed Type Libraries as Win32 Resources in .NET-Based Applications](https://docs.microsoft.com/previous-versions/dotnet/netframework-4.0/ww9a897z(v=vs.100)). + + + +## Type Library Exporter + +The [Type Library Exporter (Tlbexp.exe)](../tools/tlbexp-exe-type-library-exporter.md) is a command-line tool that converts the classes and interfaces contained in an assembly to a COM type library. Once the type information of the class is available, COM clients can create an instance of the .NET class and call the methods of the instance, just as if it were a COM object. Tlbexp.exe converts an entire assembly at one time. You cannot use Tlbexp.exe to generate type information for a subset of the types defined in an assembly. + + + +## TypeLibConverter Class + +The class, located in the **System.Runtime.Interop** namespace, converts the classes and interfaces contained in an assembly to a COM type library. This API produces the same type information as the Type Library Exporter, described in the previous section. + +The **TypeLibConverter class** implements the . + + + +## Assembly Registration Tool + +The [Assembly Registration Tool (Regasm.exe)](../tools/regasm-exe-assembly-registration-tool.md) can generate and register a type library when you apply the **/tlb:** option. COM clients require that type libraries be installed in the Windows registry. Without this option, Regasm.exe only registers the types in an assembly, not the type library. Registering the types in an assembly and registering the type library are distinct activities. + + + +## .NET Services Installation Tool + +The [.NET Services Installation Tool (Regsvcs.exe)](../tools/regsvcs-exe-net-services-installation-tool.md) adds managed classes to Windows 2000 Component Services and combines several tasks within a single tool. In addition to loading and registering an assembly, Regsvcs.exe can generate, register, and install the type library into an existing COM+ 1.0 application. + ## See also - diff --git a/docs/framework/migration-guide/how-to-determine-which-versions-are-installed.md b/docs/framework/migration-guide/how-to-determine-which-versions-are-installed.md index b0e65404c7cad..b4701a0539da5 100644 --- a/docs/framework/migration-guide/how-to-determine-which-versions-are-installed.md +++ b/docs/framework/migration-guide/how-to-determine-which-versions-are-installed.md @@ -1,11 +1,11 @@ --- title: "How to: Determine which .NET Framework versions are installed" ms.date: "04/02/2019" -dev_langs: +dev_langs: - "csharp" - "vb" ms.custom: "updateeachrelease" -helpviewer_keywords: +helpviewer_keywords: - "versions, determining for .NET Framework" - ".NET Framework, determining version" ms.assetid: 40a67826-e4df-4f59-a651-d9eb0fdc755d @@ -14,43 +14,44 @@ ms.author: "ronpet" --- # How to: Determine which .NET Framework versions are installed -Users can [install](https://docs.microsoft.com/dotnet/framework/install) and run multiple versions of the .NET Framework on their computers. When you develop or deploy your app, you might need to know which .NET Framework versions are installed on the user’s computer. +Users can [install](https://docs.microsoft.com/dotnet/framework/install) and run multiple versions of the .NET Framework on their computers. When you develop or deploy your app, you might need to know which .NET Framework versions are installed on the user’s computer. -The .NET Framework consists of two main components, which are versioned separately: - -- A set of assemblies, which are collections of types and resources that provide the functionality for your apps. The .NET Framework and assemblies share the same version number. - -- The common language runtime (CLR), which manages and executes your app's code. The CLR is identified by its own version number (see [Versions and Dependencies](~/docs/framework/migration-guide/versions-and-dependencies.md)). +The .NET Framework consists of two main components, which are versioned separately: + +- A set of assemblies, which are collections of types and resources that provide the functionality for your apps. The .NET Framework and assemblies share the same version number. + +- The common language runtime (CLR), which manages and executes your app's code. The CLR is identified by its own version number (see [Versions and Dependencies](~/docs/framework/migration-guide/versions-and-dependencies.md)). > [!NOTE] > Each new version of the .NET Framework retains features from the previous versions and adds new features. You can load multiple versions of the .NET Framework on a single computer at the same time, which means that you can install the .NET Framework without having to uninstall previous versions. In general, you shouldn't uninstall previous versions of the .NET Framework, because an application you use may depend on a specific version and may break if that version is removed. > -> There is a difference between the .NET Framework version and the CLR version: -> - The .NET Framework version is based on the set of assemblies that form the .NET Framework class library. For example, .NET Framework versions include 4.5, 4.6.1, and 4.7.2. ->- The CLR version is based on the runtime on which .NET Framework applications execute. A single CLR version typically supports multiple .NET Framework versions. For example, CLR version 4.0.30319.*xxxxx* supports .NET Framework versions 4 through 4.5.2 and CLR version 4.0.30319.42000 supports .NET Framework versions starting with .NET Framework 4.6. +> There is a difference between the .NET Framework version and the CLR version: +> - The .NET Framework version is based on the set of assemblies that form the .NET Framework class library. For example, .NET Framework versions include 4.5, 4.6.1, and 4.7.2. +>- The CLR version is based on the runtime on which .NET Framework applications execute. A single CLR version typically supports multiple .NET Framework versions. For example, CLR version 4.0.30319.*xxxxx* supports .NET Framework versions 4 through 4.5.2 and CLR version 4.0.30319.42000 supports .NET Framework versions starting with .NET Framework 4.6. > > For more information about versions, see [.NET Framework versions and dependencies](versions-and-dependencies.md). To get a list of the .NET Framework versions installed on a computer, you access the registry. You can either use the Registry Editor to view the registry or use code to query it: - -- Find newer .NET Framework versions (4.5 and later): - - [Use the Registry Editor to find .NET Framework versions](#net_b) - - [Use code to query the registry for .NET Framework versions](#net_d) - - [Use PowerShell to query the registry for .NET Framework versions](#ps_a) + +- Find newer .NET Framework versions (4.5 and later): + - [Use the Registry Editor to find .NET Framework versions](#net_b) + - [Use code to query the registry for .NET Framework versions](#net_d) + - [Use PowerShell to query the registry for .NET Framework versions](#ps_a) - Find older .NET Framework versions (1–4): - - [Use the Registry Editor to find .NET Framework versions](#net_a) - - [Use code to query the registry for .NET Framework versions](#net_c) + - [Use the Registry Editor to find .NET Framework versions](#net_a) + - [Use code to query the registry for .NET Framework versions](#net_c) + +To get a list of the CLR versions installed on a computer, use a tool or code: -To get a list of the CLR versions installed on a computer, use a tool or code: - -- [Use the Clrver tool](#clr_a) -- [Use code to query the Environment class](#clr_b) +- [Use the Clrver tool](#clr_a) +- [Use code to query the Environment class](#clr_b) -For information about detecting the installed updates for each version of the .NET Framework, see [How to: Determine which .NET Framework updates are installed](how-to-determine-which-net-framework-updates-are-installed.md). +For information about detecting the installed updates for each version of the .NET Framework, see [How to: Determine which .NET Framework updates are installed](how-to-determine-which-net-framework-updates-are-installed.md). ## Find newer .NET Framework versions (4.5 and later) - + + ### Find .NET Framework versions 4.5 and later in the registry 1. From the **Start** menu, choose **Run**, enter *regedit*, and then select **OK**. @@ -62,7 +63,7 @@ For information about detecting the installed updates for each version of the .N > [!NOTE] > The **NET Framework Setup** folder in the registry does *not* begin with a period. -3. Check for a DWORD entry named **Release**. If it exists, then you have .NET Framework 4.5 or later versions installed. Its value is a release key that corresponds to a particular version of the .NET Framework. In the following figure, for example, the value of the **Release** entry is *378389*, which is the release key for .NET Framework 4.5. +3. Check for a DWORD entry named **Release**. If it exists, then you have .NET Framework 4.5 or later versions installed. Its value is a release key that corresponds to a particular version of the .NET Framework. In the following figure, for example, the value of the **Release** entry is *378389*, which is the release key for .NET Framework 4.5. ![Registry entry for the .NET Framework 4.5](media/clr-installdir.png "Registry entry for the .NET Framework 4.5") @@ -80,9 +81,9 @@ The following table lists the value of the **Release** DWORD on individual opera |.NET Framework 4.6|On Windows 10: 393295
On all other Windows operating systems: 393297| |.NET Framework 4.6.1|On Windows 10 November Update systems: 394254
On all other Windows operating systems (including Windows 10): 394271| |.NET Framework 4.6.2|On Windows 10 Anniversary Update and Windows Server 2016: 394802
On all other Windows operating systems (including other Windows 10 operating systems): 394806| -|.NET Framework 4.7|On Windows 10 Creators Update: 460798
On all other Windows operating systems (including other Windows 10 operating systems): 460805| +|.NET Framework 4.7|On Windows 10 Creators Update: 460798
On all other Windows operating systems (including other Windows 10 operating systems): 460805| |.NET Framework 4.7.1|On Windows 10 Fall Creators Update and Windows Server, version 1709: 461308
On all other Windows operating systems (including other Windows 10 operating systems): 461310| -|.NET Framework 4.7.2|On Windows 10 April 2018 Update and Windows Server, version 1803: 461808
On all Windows operating systems other than Windows 10 April 2018 Update and Windows Server, version 1803: 461814| +|.NET Framework 4.7.2|On Windows 10 April 2018 Update and Windows Server, version 1803: 461808
On all Windows operating systems other than Windows 10 April 2018 Update and Windows Server, version 1803: 461814| You can use these values as follows: @@ -92,12 +93,13 @@ You can use these values as follows: - To test for multiple versions, begin by testing for a value that is *greater than or equal to* the smaller DWORD value for the latest .NET Framework version, and then compare the value with the smaller DWORD value for each successive earlier version. For example, if your application requires .NET Framework 4.7 or later and you want to determine the specific version of .NET Framework present, start by testing for a **RELEASE** DWORD value that is *great than or equal to* to 461808 (the smaller DWORD value for .NET Framework 4.7.2). Then compare the **RELEASE** DWORD value with the smaller value for each later .NET Framework version. For a table that lists only the minimum **RELEASE** DWORD value for each .NET Framework version, see [The minimum values of the Release DWORD for .NET Framework 4.5 and later versions](minimum-release-dword.md). - + + ### Find .NET Framework versions 4.5 and later with code 1. Use the and methods to access the **HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full** subkey in the Windows registry. - The existence of the **Release** DWORD entry in the **HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full** subkey indicates that the .NET Framework 4.5 or a later version is installed on a computer. + The existence of the **Release** DWORD entry in the **HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full** subkey indicates that the .NET Framework 4.5 or a later version is installed on a computer. 2. Check the value of the **Release** entry to determine the installed version. To be forward-compatible, check for a value greater than or equal to the value listed in the [.NET Framework version table](#version_table). @@ -112,7 +114,8 @@ This example follows the recommended practice for version checking: - It checks in order from most recent version to earliest version. - + + ### Check for a minimum-required .NET Framework version (4.5 and later) with PowerShell - Use PowerShell commands to check the value of the **Release** entry of the **HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full** subkey. @@ -121,7 +124,7 @@ The following examples check the value of the **Release** entry to determine whe ```PowerShell # PowerShell 5 - Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\' | Get-ItemPropertyValue -Name Release | Foreach-Object { $_ -ge 394802 } + Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\' | Get-ItemPropertyValue -Name Release | Foreach-Object { $_ -ge 394802 } ``` ```PowerShell @@ -134,16 +137,17 @@ To check for a different minimum-required .NET Framework version, replace *39480 ## Find older .NET Framework versions (1–4) -### Find .NET Framework versions 1–4 in the registry - + +### Find .NET Framework versions 1–4 in the registry + 1. From the **Start** menu, choose **Run**, enter *regedit*, and then select **OK**. - - You must have administrative credentials to run regedit. -2. In the Registry Editor, open the following subkey: **HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP**: + You must have administrative credentials to run regedit. + +2. In the Registry Editor, open the following subkey: **HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP**: + + - For .NET Framework versions 1.1 through 3.5, each installed version is listed as a subkey under the **HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP** subkey. For example, **HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5**. The version number is stored as a value in the version subkey's **Version** entry. - - For .NET Framework versions 1.1 through 3.5, each installed version is listed as a subkey under the **HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP** subkey. For example, **HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5**. The version number is stored as a value in the version subkey's **Version** entry. - - For .NET Framework 4, the **Version** entry is under the **HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4.0\Client** subkey, the **HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4.0\Full** subkey, or under both subkeys. > [!NOTE] @@ -153,7 +157,8 @@ To check for a different minimum-required .NET Framework version, replace *39480 ![The registry entry for the .NET Framework 3.5.](media/net-4-and-earlier.png ".NET Framework 3.5 and earlier versions") - + + ### Find .NET Framework versions 1–4 with code - Use the class to access the **HKEY_LOCAL_MACHINE\Software\Microsoft\NET Framework Setup\NDP** subkey in the Windows registry. @@ -164,8 +169,9 @@ The following example finds the .NET Framework 1–4 versions that are insta [!code-vb[ListVersions](../../../samples/snippets/visualbasic/framework/migration-guide/versions-installed1.vb)] ## Find CLR versions - - + + + ### Find the current CLR version with Clrver.exe Use the [CLR Version tool (Clrver.exe)](../tools/clrver-exe-clr-version-tool.md) to determine which versions of the CLR are installed on a computer: @@ -180,17 +186,18 @@ Use the [CLR Version tool (Clrver.exe)](../tools/clrver-exe-clr-version-tool.md) v4.0.30319 ``` - + + ### Find the current CLR version with the Environment class > [!IMPORTANT] > For the .NET Framework 4.5 and later versions, don't use the property to detect the version of the CLR. Instead, query the registry as described in [Find .NET Framework versions 4.5 and later with code](#net_d). -1. Query the property to retrieve a object. +1. Query the property to retrieve a object. The returned `System.Version` object identifies the version of the runtime that's currently executing the code. It doesn't return assembly versions or other versions of the runtime that may have been installed on the computer. - For the .NET Framework versions 4, 4.5, 4.5.1, and 4.5.2, the string representation of the returned object has the form 4.0.30319.*xxxxx*. For the .NET Framework 4.6 and later versions, it has the form 4.0.30319.42000. + For the .NET Framework versions 4, 4.5, 4.5.1, and 4.5.2, the string representation of the returned object has the form 4.0.30319.*xxxxx*. For the .NET Framework 4.6 and later versions, it has the form 4.0.30319.42000. 2. After you have the `Version` object, query it as follows: diff --git a/docs/framework/migration-guide/mitigation-custom-imessagefilter-prefiltermessage-implementations.md b/docs/framework/migration-guide/mitigation-custom-imessagefilter-prefiltermessage-implementations.md index 7bb115caaa1e9..8ea18b71ad518 100644 --- a/docs/framework/migration-guide/mitigation-custom-imessagefilter-prefiltermessage-implementations.md +++ b/docs/framework/migration-guide/mitigation-custom-imessagefilter-prefiltermessage-implementations.md @@ -6,38 +6,41 @@ author: "rpetrusha" ms.author: "ronpet" --- # Mitigation: Custom IMessageFilter.PreFilterMessage Implementations -In Windows Forms apps that target versions of the .NET Framework starting with the [!INCLUDE[net_v461](../../../includes/net-v461-md.md)], a custom implementation can safely filter messages when the method is called if the implementation: - -- Does one or both of the following: - - - Adds a message filter by calling the method. - - - Removes a message filter by calling the method. method. - -- **And** pumps messages by calling the method. - -## Impact - This change only affects Windows Forms apps that target versions of the .NET Framework starting with the [!INCLUDE[net_v461](../../../includes/net-v461-md.md)]. - - For Windows Forms apps that target previous versions of the .NET Framework, such implementations in some cases throw an exception when the method is called - -## Mitigation - If this change is undesirable, apps that target the [!INCLUDE[net_v461](../../../includes/net-v461-md.md)] or a later version can opt out of it by adding the following configuration setting to the [\](../../../docs/framework/configure-apps/file-schema/runtime/runtime-element.md) section of the app’s configuration file: - -```xml - - - -``` - - In addition, apps that target previous versions of the .NET Framework but are running under the [!INCLUDE[net_v461](../../../includes/net-v461-md.md)] or a later version can opt in to this behavior by adding the following configuration setting to the [\](../../../docs/framework/configure-apps/file-schema/runtime/runtime-element.md) section of the app’s configuration file: - -```xml - - - -``` - + +In Windows Forms apps that target versions of the .NET Framework starting with the [!INCLUDE[net_v461](../../../includes/net-v461-md.md)], a custom implementation can safely filter messages when the method is called if the implementation: + +- Does one or both of the following: + + - Adds a message filter by calling the method. + + - Removes a message filter by calling the method. method. + +- **And** pumps messages by calling the method. + +## Impact + +This change only affects Windows Forms apps that target versions of the .NET Framework starting with the [!INCLUDE[net_v461](../../../includes/net-v461-md.md)]. + +For Windows Forms apps that target previous versions of the .NET Framework, such implementations in some cases throw an exception when the method is called + +## Mitigation + +If this change is undesirable, apps that target the [!INCLUDE[net_v461](../../../includes/net-v461-md.md)] or a later version can opt out of it by adding the following configuration setting to the [\](../../../docs/framework/configure-apps/file-schema/runtime/runtime-element.md) section of the app’s configuration file: + +```xml + + + +``` + +In addition, apps that target previous versions of the .NET Framework but are running under the [!INCLUDE[net_v461](../../../includes/net-v461-md.md)] or a later version can opt in to this behavior by adding the following configuration setting to the [\](../../../docs/framework/configure-apps/file-schema/runtime/runtime-element.md) section of the app’s configuration file: + +```xml + + + +``` + ## See also - [Retargeting Changes](../../../docs/framework/migration-guide/retargeting-changes-in-the-net-framework-4-6-1.md) diff --git a/docs/framework/migration-guide/mitigation-wpf-window-rendering.md b/docs/framework/migration-guide/mitigation-wpf-window-rendering.md index b12930f1acc65..266d3424ac5de 100644 --- a/docs/framework/migration-guide/mitigation-wpf-window-rendering.md +++ b/docs/framework/migration-guide/mitigation-wpf-window-rendering.md @@ -6,32 +6,35 @@ author: "rpetrusha" ms.author: "ronpet" --- # Mitigation: WPF Window Rendering -In the [!INCLUDE[net_v46](../../../includes/net-v46-md.md)] running on Windows 8 and above, the entire window is rendered without clipping when it extends outside of single display in a multi-monitor scenario. - -## Impact - In general, rendering an entire window across multiple monitors without clipping is the expected behavior. However, on Windows 7 and earlier versions, WPF windows are clipped when they extend beyond a single display because rendering a portion of the window on the second monitor has a significant performance impact. - - The precise impact of rendering WPF windows across monitors on Windows 8 and above is not precisely quantifiable since it depends on a large number of factors. In some cases, it may still produce an undesirable impact on performance, particularly for users who run graphics-intensive applications and have windows straddling monitors. In other cases, you may simply want a consistent behavior across .NET Framework versions. - -## Mitigation - You can disable this change and revert to the previous behavior of clipping a WPF window when it extends beyond a single display. There are two ways to do this: - -- By adding the `` element to the `` section of your application configuration file, you can disable or enable this behavior on apps running on Windows 8 or later. For example, the following configuration section disables rendering without clipping: - - ```xml - - - - ``` - - The `` configuration setting can have either of two values: - - - `true`, to enable clipping of windows to monitor bounds during rendering. - - - `false`, to disable clipping of windows to monitor bounds during rendering. - -- By setting the property to `true` at app startup. - + +In the [!INCLUDE[net_v46](../../../includes/net-v46-md.md)] running on Windows 8 and above, the entire window is rendered without clipping when it extends outside of single display in a multi-monitor scenario. + +## Impact + +In general, rendering an entire window across multiple monitors without clipping is the expected behavior. However, on Windows 7 and earlier versions, WPF windows are clipped when they extend beyond a single display because rendering a portion of the window on the second monitor has a significant performance impact. + +The precise impact of rendering WPF windows across monitors on Windows 8 and above is not precisely quantifiable since it depends on a large number of factors. In some cases, it may still produce an undesirable impact on performance, particularly for users who run graphics-intensive applications and have windows straddling monitors. In other cases, you may simply want a consistent behavior across .NET Framework versions. + +## Mitigation + +You can disable this change and revert to the previous behavior of clipping a WPF window when it extends beyond a single display. There are two ways to do this: + +- By adding the `` element to the `` section of your application configuration file, you can disable or enable this behavior on apps running on Windows 8 or later. For example, the following configuration section disables rendering without clipping: + + ```xml + + + + ``` + + The `` configuration setting can have either of two values: + + - `true`, to enable clipping of windows to monitor bounds during rendering. + + - `false`, to disable clipping of windows to monitor bounds during rendering. + +- By setting the property to `true` at app startup. + ## See also - [Runtime Changes](../../../docs/framework/migration-guide/runtime-changes-in-the-net-framework-4-6.md) diff --git a/docs/framework/misc/security-transparent-code-level-2.md b/docs/framework/misc/security-transparent-code-level-2.md index 8d4de94642848..812d149c622bf 100644 --- a/docs/framework/misc/security-transparent-code-level-2.md +++ b/docs/framework/misc/security-transparent-code-level-2.md @@ -1,7 +1,7 @@ --- title: "Security-Transparent Code, Level 2" ms.date: "03/30/2017" -helpviewer_keywords: +helpviewer_keywords: - "transparency" - "level 2 transparency" - "security-transparent code" @@ -11,180 +11,194 @@ author: "mairaw" ms.author: "mairaw" --- # Security-Transparent Code, Level 2 + -[!INCLUDE[net_security_note](../../../includes/net-security-note-md.md)] - - Level 2 transparency was introduced in the [!INCLUDE[net_v40_long](../../../includes/net-v40-long-md.md)]. The three tenets of this model are transparent code, security-safe-critical code, and security-critical code. - -- Transparent code, including code that is running as full trust, can call other transparent code or security-safe-critical code only. It can only perform actions allowed by the domain’s partial trust permission set (if one exists). Transparent code cannot do the following: - - - Perform an or elevation of privilege. - - - Contain unsafe or unverifiable code. - - - Directly call critical code. - - - Call native code or code with the attribute. - - - Call a member that is protected by a . - - - Inherit from critical types. - - In addition, transparent methods cannot override critical virtual methods or implement critical interface methods. - -- Safe-critical code is fully trusted but is callable by transparent code. It exposes a limited surface area of full-trust code; correctness and security verifications happen in safe-critical code. - -- Security-critical code can call any code and is fully trusted, but it cannot be called by transparent code. - - This topic contains the following sections: - -- [Usage Examples and Behaviors](#examples) - -- [Override Patterns](#override) - -- [Inheritance Rules](#inheritance) - -- [Additional Information and Rules](#additional) - - -## Usage Examples and Behaviors - To specify [!INCLUDE[net_v40_short](../../../includes/net-v40-short-md.md)] rules (level 2 transparency), use the following annotation for an assembly: - -``` -[assembly: SecurityRules(SecurityRuleSet.Level2)] -``` - - To lock into the .NET Framework 2.0 rules (level 1 transparency), use the following annotation: - -``` -[assembly: SecurityRules(SecurityRuleSet.Level1)] -``` - - If you do not annotate an assembly, the [!INCLUDE[net_v40_short](../../../includes/net-v40-short-md.md)] rules are used by default. However, the recommended best practice is to use the attribute instead of depending on the default. - -### Assembly-wide Annotation - The following rules apply to the use of attributes at the assembly level: - -- No attributes: If you do not specify any attributes, the runtime interprets all code as security-critical, except where being security-critical violates an inheritance rule (for example, when overriding or implementing a transparent virtual or interface method). In those cases, the methods are safe-critical. Specifying no attribute causes the common language runtime to determine the transparency rules for you. - -- `SecurityTransparent`: All code is transparent; the entire assembly will not do anything privileged or unsafe. - -- `SecurityCritical`: All code that is introduced by types in this assembly is critical; all other code is transparent. This scenario is similar to not specifying any attributes; however, the common language runtime does not automatically determine the transparency rules. For example, if you override a virtual or abstract method or implement an interface method, by default, that method is transparent. You must explicitly annotate the method as `SecurityCritical` or `SecuritySafeCritical`; otherwise, a will be thrown at load time. This rule also applies when both the base class and the derived class are in the same assembly. - -- `AllowPartiallyTrustedCallers` (level 2 only): All code defaults to transparent. However, individual types and members can have other attributes. - - The following table compares the assembly level behavior for Level 2 with Level 1. - -|Assembly attribute|Level 2|Level 1| -|------------------------|-------------|-------------| -|No attribute on a partially trusted assembly|Types and members are by default transparent, but can be security-critical or security-safe-critical.|All types and members are transparent.| -|No attribute|Specifying no attribute causes the common language runtime to determine the transparency rules for you. All types and members are security-critical, except where being security-critical violates an inheritance rule.|On a fully trusted assembly (in the global assembly cache or identified as full trust in the `AppDomain`) all types are transparent and all members are security-safe-critical.| -|`SecurityTransparent`|All types and members are transparent.|All types and members are transparent.| -|`SecurityCritical(SecurityCriticalScope.Everything)`|Not applicable.|All types and members are security-critical.| -|`SecurityCritical`|All code that is introduced by types in this assembly is critical; all other code is transparent. If you override a virtual or abstract method or implement an interface method, you must explicitly annotate the method as `SecurityCritical` or `SecuritySafeCritical`.|All code defaults to transparent. However, individual types and members can have other attributes.| - -### Type and Member Annotation - The security attributes that are applied to a type also apply to the members that are introduced by the type. However, they do not apply to virtual or abstract overrides of the base class or interface implementations. The following rules apply to the use of attributes at the type and member level: - -- `SecurityCritical`: The type or member is critical and can be called only by full-trust code. Methods that are introduced in a security-critical type are critical. - + +[!INCLUDE[net_security_note](../../../includes/net-security-note-md.md)] + +Level 2 transparency was introduced in the [!INCLUDE[net_v40_long](../../../includes/net-v40-long-md.md)]. The three tenets of this model are transparent code, security-safe-critical code, and security-critical code. + +- Transparent code, including code that is running as full trust, can call other transparent code or security-safe-critical code only. It can only perform actions allowed by the domain’s partial trust permission set (if one exists). Transparent code cannot do the following: + + - Perform an or elevation of privilege. + + - Contain unsafe or unverifiable code. + + - Directly call critical code. + + - Call native code or code with the attribute. + + - Call a member that is protected by a . + + - Inherit from critical types. + + In addition, transparent methods cannot override critical virtual methods or implement critical interface methods. + +- Safe-critical code is fully trusted but is callable by transparent code. It exposes a limited surface area of full-trust code; correctness and security verifications happen in safe-critical code. + +- Security-critical code can call any code and is fully trusted, but it cannot be called by transparent code. + +This topic contains the following sections: + +- [Usage Examples and Behaviors](#examples) + +- [Override Patterns](#override) + +- [Inheritance Rules](#inheritance) + +- [Additional Information and Rules](#additional) + + + +## Usage Examples and Behaviors + +To specify [!INCLUDE[net_v40_short](../../../includes/net-v40-short-md.md)] rules (level 2 transparency), use the following annotation for an assembly: + +```csharp +[assembly: SecurityRules(SecurityRuleSet.Level2)] +``` + +To lock into the .NET Framework 2.0 rules (level 1 transparency), use the following annotation: + +```csharp +[assembly: SecurityRules(SecurityRuleSet.Level1)] +``` + +If you do not annotate an assembly, the [!INCLUDE[net_v40_short](../../../includes/net-v40-short-md.md)] rules are used by default. However, the recommended best practice is to use the attribute instead of depending on the default. + +### Assembly-wide Annotation + +The following rules apply to the use of attributes at the assembly level: + +- No attributes: If you do not specify any attributes, the runtime interprets all code as security-critical, except where being security-critical violates an inheritance rule (for example, when overriding or implementing a transparent virtual or interface method). In those cases, the methods are safe-critical. Specifying no attribute causes the common language runtime to determine the transparency rules for you. + +- `SecurityTransparent`: All code is transparent; the entire assembly will not do anything privileged or unsafe. + +- `SecurityCritical`: All code that is introduced by types in this assembly is critical; all other code is transparent. This scenario is similar to not specifying any attributes; however, the common language runtime does not automatically determine the transparency rules. For example, if you override a virtual or abstract method or implement an interface method, by default, that method is transparent. You must explicitly annotate the method as `SecurityCritical` or `SecuritySafeCritical`; otherwise, a will be thrown at load time. This rule also applies when both the base class and the derived class are in the same assembly. + +- `AllowPartiallyTrustedCallers` (level 2 only): All code defaults to transparent. However, individual types and members can have other attributes. + +The following table compares the assembly level behavior for Level 2 with Level 1. + +|Assembly attribute|Level 2|Level 1| +|------------------------|-------------|-------------| +|No attribute on a partially trusted assembly|Types and members are by default transparent, but can be security-critical or security-safe-critical.|All types and members are transparent.| +|No attribute|Specifying no attribute causes the common language runtime to determine the transparency rules for you. All types and members are security-critical, except where being security-critical violates an inheritance rule.|On a fully trusted assembly (in the global assembly cache or identified as full trust in the `AppDomain`) all types are transparent and all members are security-safe-critical.| +|`SecurityTransparent`|All types and members are transparent.|All types and members are transparent.| +|`SecurityCritical(SecurityCriticalScope.Everything)`|Not applicable.|All types and members are security-critical.| +|`SecurityCritical`|All code that is introduced by types in this assembly is critical; all other code is transparent. If you override a virtual or abstract method or implement an interface method, you must explicitly annotate the method as `SecurityCritical` or `SecuritySafeCritical`.|All code defaults to transparent. However, individual types and members can have other attributes.| + +### Type and Member Annotation + +The security attributes that are applied to a type also apply to the members that are introduced by the type. However, they do not apply to virtual or abstract overrides of the base class or interface implementations. The following rules apply to the use of attributes at the type and member level: + +- `SecurityCritical`: The type or member is critical and can be called only by full-trust code. Methods that are introduced in a security-critical type are critical. + > [!IMPORTANT] - > Virtual and abstract methods that are introduced in base classes or interfaces, and overridden or implemented in a security-critical class are transparent by default. They must be identified as either `SecuritySafeCritical` or `SecurityCritical`. - -- `SecuritySafeCritical`: The type or member is safe-critical. However, the type or member can be called from transparent (partially trusted) code and is as capable as any other critical code. The code must be audited for security. - - [Back to top](#top) - - -## Override Patterns - The following table shows the method overrides allowed for level 2 transparency. - -|Base virtual/interface member|Override/interface| -|------------------------------------|-------------------------| -|`Transparent`|`Transparent`| -|`Transparent`|`SafeCritical`| -|`SafeCritical`|`Transparent`| -|`SafeCritical`|`SafeCritical`| -|`Critical`|`Critical`| - - [Back to top](#top) - - -## Inheritance Rules - In this section, the following order is assigned to `Transparent`, `Critical`, and `SafeCritical` code based on access and capabilities: - - `Transparent` < `SafeCritical` < `Critical` - -- Rules for types: Going from left to right, access becomes more restrictive. Derived types must be at least as restrictive as the base type. - -- Rules for methods: Derived methods cannot change accessibility from the base method. For default behavior, all derived methods that are not annotated are `Transparent`. Derivatives of critical types cause an exception to be thrown if the overridden method is not explicitly annotated as `SecurityCritical`. - - The following table shows the allowed type inheritance patterns. - -|Base class|Derived class can be| -|----------------|--------------------------| -|`Transparent`|`Transparent`| -|`Transparent`|`SafeCritical`| -|`Transparent`|`Critical`| -|`SafeCritical`|`SafeCritical`| -|`SafeCritical`|`Critical`| -|`Critical`|`Critical`| - - The following table shows the disallowed type inheritance patterns. - -|Base class|Derived class cannot be| -|----------------|-----------------------------| -|`SafeCritical`|`Transparent`| -|`Critical`|`Transparent`| -|`Critical`|`SafeCritical`| - - The following table shows the allowed method inheritance patterns. - -|Base method|Derived method can be| -|-----------------|---------------------------| -|`Transparent`|`Transparent`| -|`Transparent`|`SafeCritical`| -|`SafeCritical`|`Transparent`| -|`SafeCritical`|`SafeCritical`| -|`Critical`|`Critical`| - - The following table shows the disallowed method inheritance patterns. - -|Base method|Derived method cannot be| -|-----------------|------------------------------| -|`Transparent`|`Critical`| -|`SafeCritical`|`Critical`| -|`Critical`|`Transparent`| -|`Critical`|`SafeCritical`| - + > Virtual and abstract methods that are introduced in base classes or interfaces, and overridden or implemented in a security-critical class are transparent by default. They must be identified as either `SecuritySafeCritical` or `SecurityCritical`. + +- `SecuritySafeCritical`: The type or member is safe-critical. However, the type or member can be called from transparent (partially trusted) code and is as capable as any other critical code. The code must be audited for security. + +[Back to top](#top) + + + +## Override Patterns + +The following table shows the method overrides allowed for level 2 transparency. + +|Base virtual/interface member|Override/interface| +|------------------------------------|-------------------------| +|`Transparent`|`Transparent`| +|`Transparent`|`SafeCritical`| +|`SafeCritical`|`Transparent`| +|`SafeCritical`|`SafeCritical`| +|`Critical`|`Critical`| + +[Back to top](#top) + + + +## Inheritance Rules + +In this section, the following order is assigned to `Transparent`, `Critical`, and `SafeCritical` code based on access and capabilities: + +`Transparent` < `SafeCritical` < `Critical` + +- Rules for types: Going from left to right, access becomes more restrictive. Derived types must be at least as restrictive as the base type. + +- Rules for methods: Derived methods cannot change accessibility from the base method. For default behavior, all derived methods that are not annotated are `Transparent`. Derivatives of critical types cause an exception to be thrown if the overridden method is not explicitly annotated as `SecurityCritical`. + +The following table shows the allowed type inheritance patterns. + +|Base class|Derived class can be| +|----------------|--------------------------| +|`Transparent`|`Transparent`| +|`Transparent`|`SafeCritical`| +|`Transparent`|`Critical`| +|`SafeCritical`|`SafeCritical`| +|`SafeCritical`|`Critical`| +|`Critical`|`Critical`| + +The following table shows the disallowed type inheritance patterns. + +|Base class|Derived class cannot be| +|----------------|-----------------------------| +|`SafeCritical`|`Transparent`| +|`Critical`|`Transparent`| +|`Critical`|`SafeCritical`| + +The following table shows the allowed method inheritance patterns. + +|Base method|Derived method can be| +|-----------------|---------------------------| +|`Transparent`|`Transparent`| +|`Transparent`|`SafeCritical`| +|`SafeCritical`|`Transparent`| +|`SafeCritical`|`SafeCritical`| +|`Critical`|`Critical`| + +The following table shows the disallowed method inheritance patterns. + +|Base method|Derived method cannot be| +|-----------------|------------------------------| +|`Transparent`|`Critical`| +|`SafeCritical`|`Critical`| +|`Critical`|`Transparent`| +|`Critical`|`SafeCritical`| + > [!NOTE] -> These inheritance rules apply to level 2 types and members. Types in level 1 assemblies can inherit from level 2 security-critical types and members. Therefore, level 2 types and members must have separate inheritance demands for level 1 inheritors. - - [Back to top](#top) - - -## Additional Information and Rules - -### LinkDemand Support - The level 2 transparency model replaces the with the attribute. In legacy (level 1) code, a is automatically treated as a . - -### Reflection - Invoking a critical method or reading a critical field triggers a demand for full trust (just as if you were invoking a private method or field). Therefore, full-trust code can invoke a critical method, whereas partial-trust code cannot. - - The following properties have been added to the namespace to determine whether the type, method, or field is `SecurityCritical`, `SecuritySafeCritical`, or `SecurityTransparent`: , , and . Use these properties to determine transparency by using reflection instead of checking for the presence of the attribute. The transparency rules are complex, and checking for the attribute may not be sufficient. - +> These inheritance rules apply to level 2 types and members. Types in level 1 assemblies can inherit from level 2 security-critical types and members. Therefore, level 2 types and members must have separate inheritance demands for level 1 inheritors. + +[Back to top](#top) + + + +## Additional Information and Rules + +### LinkDemand Support + +The level 2 transparency model replaces the with the attribute. In legacy (level 1) code, a is automatically treated as a . + +### Reflection + +Invoking a critical method or reading a critical field triggers a demand for full trust (just as if you were invoking a private method or field). Therefore, full-trust code can invoke a critical method, whereas partial-trust code cannot. + +The following properties have been added to the namespace to determine whether the type, method, or field is `SecurityCritical`, `SecuritySafeCritical`, or `SecurityTransparent`: , , and . Use these properties to determine transparency by using reflection instead of checking for the presence of the attribute. The transparency rules are complex, and checking for the attribute may not be sufficient. + > [!NOTE] -> A `SafeCritical` method returns `true` for both and , because `SafeCritical` is indeed critical (it has the same capabilities as critical code, but it can be called from transparent code). - - Dynamic methods inherit the transparency of the modules they are attached to; they do not inherit the transparency of the type (if they are attached to a type). - -### Skip Verification in Full Trust - You can skip verification for fully trusted transparent assemblies by setting the property to `true` in the attribute: - - `[assembly: SecurityRules(SecurityRuleSet.Level2, SkipVerificationInFullTrust = true)]` - - The property is `false` by default, so the property must be set to `true` to skip verification. This should be done for optimization purposes only. You should ensure that the transparent code in the assembly is verifiable by using the `transparent` option in the [PEVerify tool](../../../docs/framework/tools/peverify-exe-peverify-tool.md). - +> A `SafeCritical` method returns `true` for both and , because `SafeCritical` is indeed critical (it has the same capabilities as critical code, but it can be called from transparent code). + +Dynamic methods inherit the transparency of the modules they are attached to; they do not inherit the transparency of the type (if they are attached to a type). + +### Skip Verification in Full Trust + +You can skip verification for fully trusted transparent assemblies by setting the property to `true` in the attribute: + +`[assembly: SecurityRules(SecurityRuleSet.Level2, SkipVerificationInFullTrust = true)]` + +The property is `false` by default, so the property must be set to `true` to skip verification. This should be done for optimization purposes only. You should ensure that the transparent code in the assembly is verifiable by using the `transparent` option in the [PEVerify tool](../../../docs/framework/tools/peverify-exe-peverify-tool.md). + ## See also - [Security-Transparent Code, Level 1](../../../docs/framework/misc/security-transparent-code-level-1.md) diff --git a/docs/framework/misc/security-transparent-code.md b/docs/framework/misc/security-transparent-code.md index 274822992dd92..39bab9fcf1972 100644 --- a/docs/framework/misc/security-transparent-code.md +++ b/docs/framework/misc/security-transparent-code.md @@ -1,7 +1,7 @@ --- title: "Security-Transparent Code" ms.date: "03/30/2017" -helpviewer_keywords: +helpviewer_keywords: - "transparent code" - "security-transparent code" ms.assetid: 4f3dd841-82f7-4659-aab0-6d2db2166c65 @@ -9,97 +9,107 @@ author: "mairaw" ms.author: "mairaw" --- # Security-Transparent Code + -[!INCLUDE[net_security_note](../../../includes/net-security-note-md.md)] - - Security involves three interacting pieces: sandboxing, permissions, and enforcement. Sandboxing refers to the practice of creating isolated domains where some code is treated as fully trusted and other code is restricted to the permissions in the grant set for the sandbox. The application code that runs within the grant set of the sandbox is considered to be transparent; that is, it cannot perform any operations that can affect security. The grant set for the sandbox is determined by evidence ( class). Evidence identifies what specific permissions are required by sandboxes, and what kinds of sandboxes can be created. Enforcement refers to allowing transparent code to execute only within its grant set. - + +[!INCLUDE[net_security_note](../../../includes/net-security-note-md.md)] + +Security involves three interacting pieces: sandboxing, permissions, and enforcement. Sandboxing refers to the practice of creating isolated domains where some code is treated as fully trusted and other code is restricted to the permissions in the grant set for the sandbox. The application code that runs within the grant set of the sandbox is considered to be transparent; that is, it cannot perform any operations that can affect security. The grant set for the sandbox is determined by evidence ( class). Evidence identifies what specific permissions are required by sandboxes, and what kinds of sandboxes can be created. Enforcement refers to allowing transparent code to execute only within its grant set. + > [!IMPORTANT] -> Security policy was a key element in previous versions of the .NET Framework. Starting with the [!INCLUDE[net_v40_long](../../../includes/net-v40-long-md.md)], security policy is obsolete. The elimination of security policy is separate from security transparency. For information about the effects of this change, see [Code Access Security Policy Compatibility and Migration](../../../docs/framework/misc/code-access-security-policy-compatibility-and-migration.md). - - This topic describes the transparency model in more detail. It contains the following sections: - -- [Purpose of the Transparency Model](#purpose) - -- [Specifying the Transparency Level](#level) - -- [Transparency Enforcement](#enforcement) - - -## Purpose of the Transparency Model - Transparency is an enforcement mechanism that separates code that runs as part of the application from code that runs as part of the infrastructure. Transparency draws a barrier between code that can do privileged things (critical code), such as calling native code, and code that cannot (transparent code). Transparent code can execute commands within the bounds of the permission set it is operating in, but cannot execute, derive from, or contain critical code. - - The primary goal of transparency enforcement is to provide a simple, effective mechanism for isolating different groups of code based on privilege. Within the context of the sandboxing model, these privilege groups are either fully trusted (that is, not restricted) or partially trusted (that is, restricted to the permission set granted to the sandbox). - +> Security policy was a key element in previous versions of the .NET Framework. Starting with the [!INCLUDE[net_v40_long](../../../includes/net-v40-long-md.md)], security policy is obsolete. The elimination of security policy is separate from security transparency. For information about the effects of this change, see [Code Access Security Policy Compatibility and Migration](../../../docs/framework/misc/code-access-security-policy-compatibility-and-migration.md). + +This topic describes the transparency model in more detail. It contains the following sections: + +- [Purpose of the Transparency Model](#purpose) + +- [Specifying the Transparency Level](#level) + +- [Transparency Enforcement](#enforcement) + + + +## Purpose of the Transparency Model + +Transparency is an enforcement mechanism that separates code that runs as part of the application from code that runs as part of the infrastructure. Transparency draws a barrier between code that can do privileged things (critical code), such as calling native code, and code that cannot (transparent code). Transparent code can execute commands within the bounds of the permission set it is operating in, but cannot execute, derive from, or contain critical code. + +The primary goal of transparency enforcement is to provide a simple, effective mechanism for isolating different groups of code based on privilege. Within the context of the sandboxing model, these privilege groups are either fully trusted (that is, not restricted) or partially trusted (that is, restricted to the permission set granted to the sandbox). + > [!IMPORTANT] -> The transparency model transcends code access security. Transparency is enforced by the just-in-time compiler and remains in effect regardless of the grant set for an assembly, including full trust. - - Transparency was introduced in the .NET Framework version 2.0 to simplify the security model, and to make it easier to write and deploy secure libraries and applications. Transparent code is also used in Microsoft Silverlight, to simplify the development of partially trusted applications. - +> The transparency model transcends code access security. Transparency is enforced by the just-in-time compiler and remains in effect regardless of the grant set for an assembly, including full trust. + +Transparency was introduced in the .NET Framework version 2.0 to simplify the security model, and to make it easier to write and deploy secure libraries and applications. Transparent code is also used in Microsoft Silverlight, to simplify the development of partially trusted applications. + > [!NOTE] -> When you develop a partially trusted application, you have to be aware of the permission requirements for your target hosts. You can develop an application that uses resources that are not allowed by some hosts. This application will compile without error, but will fail when it is loaded into the hosted environment. If you have developed your application using Visual Studio, you can enable debugging in partial trust or in a restricted permission set from the development environment. For more information, see [How to: Debug a ClickOnce Application with Restricted Permissions](/visualstudio/deployment/how-to-debug-a-clickonce-application-with-restricted-permissions). The Calculate Permissions feature provided for ClickOnce applications is also available for any partially trusted application. - - [Back to top](#top) - - -## Specifying the Transparency Level - The assembly-level attribute explicitly selects the rules that the assembly will follow. The rules are organized under a numeric level system, where higher levels mean tighter enforcement of security rules. - - The levels are as follows: - -- Level 2 () – the [!INCLUDE[net_v40_short](../../../includes/net-v40-short-md.md)] transparency rules. - -- Level 1 () – the .NET Framework 2.0 transparency rules. - - The primary difference between the two transparency levels is that level 1 does not enforce transparency rules for calls from outside the assembly and is intended only for compatibility. - +> When you develop a partially trusted application, you have to be aware of the permission requirements for your target hosts. You can develop an application that uses resources that are not allowed by some hosts. This application will compile without error, but will fail when it is loaded into the hosted environment. If you have developed your application using Visual Studio, you can enable debugging in partial trust or in a restricted permission set from the development environment. For more information, see [How to: Debug a ClickOnce Application with Restricted Permissions](/visualstudio/deployment/how-to-debug-a-clickonce-application-with-restricted-permissions). The Calculate Permissions feature provided for ClickOnce applications is also available for any partially trusted application. + +[Back to top](#top) + + + +## Specifying the Transparency Level + +The assembly-level attribute explicitly selects the rules that the assembly will follow. The rules are organized under a numeric level system, where higher levels mean tighter enforcement of security rules. + +The levels are as follows: + +- Level 2 () – the [!INCLUDE[net_v40_short](../../../includes/net-v40-short-md.md)] transparency rules. + +- Level 1 () – the .NET Framework 2.0 transparency rules. + +The primary difference between the two transparency levels is that level 1 does not enforce transparency rules for calls from outside the assembly and is intended only for compatibility. + > [!IMPORTANT] -> You should specify level 1 transparency for compatibility only; that is, specify level 1 only for code that was developed with the .NET Framework 3.5 or earlier that uses the attribute or does not use the transparency model. For example, use level 1 transparency for .NET Framework 2.0 assemblies that allow calls from partially trusted callers (APTCA). For code that is developed for the [!INCLUDE[net_v40_short](../../../includes/net-v40-short-md.md)], always use level 2 transparency. - -### Level 2 Transparency - Level 2 transparency was introduced in the [!INCLUDE[net_v40_long](../../../includes/net-v40-long-md.md)]. The three tenets of this model are transparent code, security-safe-critical code, and security-critical code. - -- Transparent code, regardless of the permissions it is granted (including full trust), can call only other transparent code or security-safe-critical code. If the code is partially trusted, it can only perform actions that are allowed by the domain’s permission set. Transparent code cannot do the following: - - - Perform an operation or elevation of privilege. - - - Contain unsafe or unverifiable code. - - - Directly call critical code. - - - Call native code or code that has the attribute. - - - Call a member that is protected by a . - - - Inherit from critical types. - - In addition, transparent methods cannot override critical virtual methods or implement critical interface methods. - -- Security-safe-critical code is fully trusted but is callable by transparent code. It exposes a limited surface area of full-trust code. Correctness and security verifications happen in safe-critical code. - -- Security-critical code can call any code and is fully trusted, but it cannot be called by transparent code. - -### Level 1 Transparency - The level 1 transparency model was introduced in the .NET Framework version 2.0 to enable developers to reduce the amount of code that is subject to a security audit. Although level 1 transparency was publicly available in version 2.0, it was primarily used only within Microsoft for security auditing purposes. Through annotations, developers are able to declare which types and members can perform security elevations and other trusted actions (security-critical) and which cannot (security-transparent). Code that is identified as transparent does not require a high degree of security auditing. Level 1 transparency states that the transparency enforcement is limited to within the assembly. In other words, any public types or members that are identified as security-critical are security-critical only within the assembly. If you want to enforce security for those types and members when they are called from outside the assembly, you must use link demands for full trust. If you do not, publicly visible security-critical types and members are treated as security-safe-critical and can be called by partially trusted code outside the assembly. - - The level 1 transparency model has the following limitations: - -- Security-critical types and members that are public are accessible from security-transparent code. - -- The transparency annotations are enforced only within an assembly. - -- Security-critical types and members must use link demands to enforce security for calls from outside the assembly. - -- Inheritance rules are not enforced. - -- The potential exists for transparent code to do harmful things when run in full trust. - - [Back to top](#top) - - -## Transparency Enforcement - Transparency rules are not enforced until transparency is calculated. At that time, an is thrown if a transparency rule is violated. The time that transparency is calculated depends on multiple factors and cannot be predicted. It is calculated as late as possible. In the [!INCLUDE[net_v40_short](../../../includes/net-v40-short-md.md)], assembly-level transparency calculation occurs sooner than it does in the .NET Framework 2.0. The only guarantee is that transparency calculation will occur by the time it is needed. This is similar to how the just-in-time (JIT) compiler can change the point when a method is compiled and any errors in that method are detected. Transparency calculation is invisible if your code does not have any transparency errors. - +> You should specify level 1 transparency for compatibility only; that is, specify level 1 only for code that was developed with the .NET Framework 3.5 or earlier that uses the attribute or does not use the transparency model. For example, use level 1 transparency for .NET Framework 2.0 assemblies that allow calls from partially trusted callers (APTCA). For code that is developed for the [!INCLUDE[net_v40_short](../../../includes/net-v40-short-md.md)], always use level 2 transparency. + +### Level 2 Transparency + +Level 2 transparency was introduced in the [!INCLUDE[net_v40_long](../../../includes/net-v40-long-md.md)]. The three tenets of this model are transparent code, security-safe-critical code, and security-critical code. + +- Transparent code, regardless of the permissions it is granted (including full trust), can call only other transparent code or security-safe-critical code. If the code is partially trusted, it can only perform actions that are allowed by the domain’s permission set. Transparent code cannot do the following: + + - Perform an operation or elevation of privilege. + + - Contain unsafe or unverifiable code. + + - Directly call critical code. + + - Call native code or code that has the attribute. + + - Call a member that is protected by a . + + - Inherit from critical types. + + In addition, transparent methods cannot override critical virtual methods or implement critical interface methods. + +- Security-safe-critical code is fully trusted but is callable by transparent code. It exposes a limited surface area of full-trust code. Correctness and security verifications happen in safe-critical code. + +- Security-critical code can call any code and is fully trusted, but it cannot be called by transparent code. + +### Level 1 Transparency + +The level 1 transparency model was introduced in the .NET Framework version 2.0 to enable developers to reduce the amount of code that is subject to a security audit. Although level 1 transparency was publicly available in version 2.0, it was primarily used only within Microsoft for security auditing purposes. Through annotations, developers are able to declare which types and members can perform security elevations and other trusted actions (security-critical) and which cannot (security-transparent). Code that is identified as transparent does not require a high degree of security auditing. Level 1 transparency states that the transparency enforcement is limited to within the assembly. In other words, any public types or members that are identified as security-critical are security-critical only within the assembly. If you want to enforce security for those types and members when they are called from outside the assembly, you must use link demands for full trust. If you do not, publicly visible security-critical types and members are treated as security-safe-critical and can be called by partially trusted code outside the assembly. + +The level 1 transparency model has the following limitations: + +- Security-critical types and members that are public are accessible from security-transparent code. + +- The transparency annotations are enforced only within an assembly. + +- Security-critical types and members must use link demands to enforce security for calls from outside the assembly. + +- Inheritance rules are not enforced. + +- The potential exists for transparent code to do harmful things when run in full trust. + +[Back to top](#top) + + + +## Transparency Enforcement + +Transparency rules are not enforced until transparency is calculated. At that time, an is thrown if a transparency rule is violated. The time that transparency is calculated depends on multiple factors and cannot be predicted. It is calculated as late as possible. In the [!INCLUDE[net_v40_short](../../../includes/net-v40-short-md.md)], assembly-level transparency calculation occurs sooner than it does in the .NET Framework 2.0. The only guarantee is that transparency calculation will occur by the time it is needed. This is similar to how the just-in-time (JIT) compiler can change the point when a method is compiled and any errors in that method are detected. Transparency calculation is invisible if your code does not have any transparency errors. + ## See also - [Security-Transparent Code, Level 1](../../../docs/framework/misc/security-transparent-code-level-1.md) diff --git a/docs/framework/net-native/getting-started-with-net-native.md b/docs/framework/net-native/getting-started-with-net-native.md index dd1bd619bebad..4acd74b7c5013 100644 --- a/docs/framework/net-native/getting-started-with-net-native.md +++ b/docs/framework/net-native/getting-started-with-net-native.md @@ -6,106 +6,117 @@ author: "rpetrusha" ms.author: "ronpet" --- # Getting Started with .NET Native -Whether you are writing a new Windows app for Windows 10 or you are migrating an existing Windows Store app, you can follow the same set of procedures. To create a [!INCLUDE[net_native](../../../includes/net-native-md.md)] app, follow these steps: - -1. [Develop a Universal Windows Platform (UWP) app that targets Windows 10](#Step1), and test the debug builds of your app to ensure that it works properly. - -2. [Handle additional reflection and serialization usage](#Step2). - -3. [Deploy and test the release builds of your app](#Step3). - -4. [Manually resolve missing metadata](#Step4), and repeat [step 3](#Step3) until all issues are resolved. - + +Whether you are writing a new Windows app for Windows 10 or you are migrating an existing Windows Store app, you can follow the same set of procedures. To create a [!INCLUDE[net_native](../../../includes/net-native-md.md)] app, follow these steps: + +1. [Develop a Universal Windows Platform (UWP) app that targets Windows 10](#Step1), and test the debug builds of your app to ensure that it works properly. + +2. [Handle additional reflection and serialization usage](#Step2). + +3. [Deploy and test the release builds of your app](#Step3). + +4. [Manually resolve missing metadata](#Step4), and repeat [step 3](#Step3) until all issues are resolved. + > [!NOTE] -> If you are migrating an existing Windows Store app to [!INCLUDE[net_native](../../../includes/net-native-md.md)], be sure to review [Migrating Your Windows Store App to .NET Native](../../../docs/framework/net-native/migrating-your-windows-store-app-to-net-native.md). - - -## Step 1: Develop and test debug builds of your UWP app - Whether you are developing a new app or migrating an existing one, you follow the same process as for any Windows app. - -1. Create a new UWP project in Visual Studio by using the Universal Windows app template for Visual C# or Visual Basic. By default, all UWP applications target the CoreCLR and their release builds are compiled by using the .NET Native tool chain. - -2. Note that there are some known compatibility issues between compiling UWP app projects with the .NET Native tool chain and without it. Refer to the [migration guide](../../../docs/framework/net-native/migrating-your-windows-store-app-to-net-native.md) for more information. - - You can now write C# or Visual Basic code against the [!INCLUDE[net_native](../../../includes/net-native-md.md)] surface area that runs on the local system (or in the simulator). - +> If you are migrating an existing Windows Store app to [!INCLUDE[net_native](../../../includes/net-native-md.md)], be sure to review [Migrating Your Windows Store App to .NET Native](../../../docs/framework/net-native/migrating-your-windows-store-app-to-net-native.md). + + + +## Step 1: Develop and test debug builds of your UWP app + +Whether you are developing a new app or migrating an existing one, you follow the same process as for any Windows app. + +1. Create a new UWP project in Visual Studio by using the Universal Windows app template for Visual C# or Visual Basic. By default, all UWP applications target the CoreCLR and their release builds are compiled by using the .NET Native tool chain. + +2. Note that there are some known compatibility issues between compiling UWP app projects with the .NET Native tool chain and without it. Refer to the [migration guide](../../../docs/framework/net-native/migrating-your-windows-store-app-to-net-native.md) for more information. + +You can now write C# or Visual Basic code against the [!INCLUDE[net_native](../../../includes/net-native-md.md)] surface area that runs on the local system (or in the simulator). + > [!IMPORTANT] -> As you develop your app, note any use of serialization or reflection in your code. - - By default, debug builds are JIT-compiled to enable rapid F5 deployment, while release builds are compiled by using the [!INCLUDE[net_native](../../../includes/net-native-md.md)] pre-compilation technology. This means you should build and test the debug builds of your app to ensure that they work normally before compiling them with the .NET Native tool chain. - - -## Step 2: Handle additional reflection and serialization usage - A runtime directives file, Default.rd.xml, is automatically added to your project when you create it. If you develop in C#, it is found in your project's **Properties** folder. If you develop in Visual Basic, it is found in your project's **My Project** folder. - +> As you develop your app, note any use of serialization or reflection in your code. + +By default, debug builds are JIT-compiled to enable rapid F5 deployment, while release builds are compiled by using the [!INCLUDE[net_native](../../../includes/net-native-md.md)] pre-compilation technology. This means you should build and test the debug builds of your app to ensure that they work normally before compiling them with the .NET Native tool chain. + + + +## Step 2: Handle additional reflection and serialization usage + +A runtime directives file, Default.rd.xml, is automatically added to your project when you create it. If you develop in C#, it is found in your project's **Properties** folder. If you develop in Visual Basic, it is found in your project's **My Project** folder. + > [!NOTE] -> For an overview of the .NET Native compilation process that provides background on why a runtime directives file is needed, see [.NET Native and Compilation](../../../docs/framework/net-native/net-native-and-compilation.md). - - The runtime directives file is used to define the metadata that your app needs at run time. In some cases, the default version of the file may be adequate. However, some code that relies on serialization or reflection may require additional entries in the runtime directives file. - - **Serialization** - There are two categories of serializers, and both may require additional entries in the runtime directives file: - -- Non-reflection based serializers. The serializers found in the .NET Framework class library, such as the , , and classes, do not rely on reflection. However, they do require that code be generated based on the object to be serialized or deserialized. For more information, see the "Microsoft Serializers" section in [Serialization and Metadata](../../../docs/framework/net-native/serialization-and-metadata.md). - -- Third-party serializers. Third-party serialization libraries, the most common of which is the Newtonsoft JSON serializer, are generally reflection-based and require entries in the *.rd.xml file to support object serialization and deserialization. For more information, see the "Third-Party Serializers" section in [Serialization and Metadata](../../../docs/framework/net-native/serialization-and-metadata.md). - - **Methods that rely on reflection** - In some cases, the use of reflection in code is not obvious. Some common APIs or programming patterns aren't considered part of the reflection API but rely on reflection to execute successfully. This includes the following type instantiation and method construction methods: - -- The method - -- The and methods - -- The method. - - For more information, see [APIs That Rely on Reflection](../../../docs/framework/net-native/apis-that-rely-on-reflection.md). - +> For an overview of the .NET Native compilation process that provides background on why a runtime directives file is needed, see [.NET Native and Compilation](../../../docs/framework/net-native/net-native-and-compilation.md). + +The runtime directives file is used to define the metadata that your app needs at run time. In some cases, the default version of the file may be adequate. However, some code that relies on serialization or reflection may require additional entries in the runtime directives file. + +**Serialization** + +There are two categories of serializers, and both may require additional entries in the runtime directives file: + +- Non-reflection based serializers. The serializers found in the .NET Framework class library, such as the , , and classes, do not rely on reflection. However, they do require that code be generated based on the object to be serialized or deserialized. For more information, see the "Microsoft Serializers" section in [Serialization and Metadata](../../../docs/framework/net-native/serialization-and-metadata.md). + +- Third-party serializers. Third-party serialization libraries, the most common of which is the Newtonsoft JSON serializer, are generally reflection-based and require entries in the *.rd.xml file to support object serialization and deserialization. For more information, see the "Third-Party Serializers" section in [Serialization and Metadata](../../../docs/framework/net-native/serialization-and-metadata.md). + +**Methods that rely on reflection** + +In some cases, the use of reflection in code is not obvious. Some common APIs or programming patterns aren't considered part of the reflection API but rely on reflection to execute successfully. This includes the following type instantiation and method construction methods: + +- The method + +- The and methods + +- The method. + +For more information, see [APIs That Rely on Reflection](../../../docs/framework/net-native/apis-that-rely-on-reflection.md). + > [!NOTE] -> Type names used in runtime directives files must be fully qualified. For example, the file must specify "System.String" instead of "String". - - -## Step 3: Deploy and test the release builds of your app - After you’ve updated the runtime directives file, you can rebuild and deploy release builds of your app. .NET Native binaries are placed in the ILC.out subdirectory of the directory specified in the **Build output path** text box of the project's **Properties** dialog box, **Compile** tab. Binaries that aren't in this folder haven't been compiled with .NET Native. Test your app thoroughly, and test all scenarios, including failure scenarios, on each of its target platforms. - - If your app doesn’t work properly (particularly in cases where it throws [MissingMetadataException](../../../docs/framework/net-native/missingmetadataexception-class-net-native.md) or [MissingInteropDataException](../../../docs/framework/net-native/missinginteropdataexception-class-net-native.md) exceptions at run time), follow the instructions in the next section, [Step 4: Manually resolve missing metadata](#Step4). Enabling first-chance exceptions may help you find these bugs. - - When you’ve tested and debugged the debug builds of your app and you’re confident that you’ve eliminated the [MissingMetadataException](../../../docs/framework/net-native/missingmetadataexception-class-net-native.md) and [MissingInteropDataException](../../../docs/framework/net-native/missinginteropdataexception-class-net-native.md) exceptions, you should test your app as an optimized [!INCLUDE[net_native](../../../includes/net-native-md.md)] app. To do this, change your active project configuration from **Debug** to **Release**. - - -## Step 4: Manually resolve missing metadata - The most common failure you'll encounter with [!INCLUDE[net_native](../../../includes/net-native-md.md)] that you don't encounter on the desktop is a runtime [MissingMetadataException](../../../docs/framework/net-native/missingmetadataexception-class-net-native.md), [MissingInteropDataException](../../../docs/framework/net-native/missinginteropdataexception-class-net-native.md), or [MissingRuntimeArtifactException](../../../docs/framework/net-native/missingruntimeartifactexception-class-net-native.md) exception. In some cases, the absence of metadata can manifest itself in unpredictable behavior or even in app failures. This section discusses how you can debug and resolve these exceptions by adding directives to the runtime directives file. For information about the format of runtime directives, see [Runtime Directives (rd.xml) Configuration File Reference](../../../docs/framework/net-native/runtime-directives-rd-xml-configuration-file-reference.md). After you’ve added runtime directives, you should [deploy and test your app](#Step3) again and resolve any new [MissingMetadataException](../../../docs/framework/net-native/missingmetadataexception-class-net-native.md), [MissingInteropDataException](../../../docs/framework/net-native/missinginteropdataexception-class-net-native.md), and [MissingRuntimeArtifactException](../../../docs/framework/net-native/missingruntimeartifactexception-class-net-native.md) exceptions until you encounter no more exceptions. - +> Type names used in runtime directives files must be fully qualified. For example, the file must specify "System.String" instead of "String". + + + +## Step 3: Deploy and test the release builds of your app + +After you’ve updated the runtime directives file, you can rebuild and deploy release builds of your app. .NET Native binaries are placed in the ILC.out subdirectory of the directory specified in the **Build output path** text box of the project's **Properties** dialog box, **Compile** tab. Binaries that aren't in this folder haven't been compiled with .NET Native. Test your app thoroughly, and test all scenarios, including failure scenarios, on each of its target platforms. + +If your app doesn’t work properly (particularly in cases where it throws [MissingMetadataException](../../../docs/framework/net-native/missingmetadataexception-class-net-native.md) or [MissingInteropDataException](../../../docs/framework/net-native/missinginteropdataexception-class-net-native.md) exceptions at run time), follow the instructions in the next section, [Step 4: Manually resolve missing metadata](#Step4). Enabling first-chance exceptions may help you find these bugs. + +When you’ve tested and debugged the debug builds of your app and you’re confident that you’ve eliminated the [MissingMetadataException](../../../docs/framework/net-native/missingmetadataexception-class-net-native.md) and [MissingInteropDataException](../../../docs/framework/net-native/missinginteropdataexception-class-net-native.md) exceptions, you should test your app as an optimized [!INCLUDE[net_native](../../../includes/net-native-md.md)] app. To do this, change your active project configuration from **Debug** to **Release**. + + + +## Step 4: Manually resolve missing metadata + +The most common failure you'll encounter with [!INCLUDE[net_native](../../../includes/net-native-md.md)] that you don't encounter on the desktop is a runtime [MissingMetadataException](../../../docs/framework/net-native/missingmetadataexception-class-net-native.md), [MissingInteropDataException](../../../docs/framework/net-native/missinginteropdataexception-class-net-native.md), or [MissingRuntimeArtifactException](../../../docs/framework/net-native/missingruntimeartifactexception-class-net-native.md) exception. In some cases, the absence of metadata can manifest itself in unpredictable behavior or even in app failures. This section discusses how you can debug and resolve these exceptions by adding directives to the runtime directives file. For information about the format of runtime directives, see [Runtime Directives (rd.xml) Configuration File Reference](../../../docs/framework/net-native/runtime-directives-rd-xml-configuration-file-reference.md). After you’ve added runtime directives, you should [deploy and test your app](#Step3) again and resolve any new [MissingMetadataException](../../../docs/framework/net-native/missingmetadataexception-class-net-native.md), [MissingInteropDataException](../../../docs/framework/net-native/missinginteropdataexception-class-net-native.md), and [MissingRuntimeArtifactException](../../../docs/framework/net-native/missingruntimeartifactexception-class-net-native.md) exceptions until you encounter no more exceptions. + > [!TIP] -> Specify the runtime directives at a high level to enable your app to be resilient to code changes. We recommend adding runtime directives at the namespace and type levels rather than the member level. Note that there may be a tradeoff between resiliency and larger binaries with longer compile times. - - When addressing a missing metadata exception, consider these issues: - -- What was the app trying to do before the exception? - - - For example, was it data binding, serializing or deserializing data, or directly using the reflection API? - -- Is this an isolated case, or do you believe you'll encounter the same issue for other types? - - - For example, a [MissingMetadataException](../../../docs/framework/net-native/missingmetadataexception-class-net-native.md) exception is thrown when serializing a type in the app’s object model. If you know other types that will be serialized, you can add runtime directives for those types (or for their containing namespaces, depending on how well the code is organized) at the same time. - -- Can you rewrite the code so it doesn’t use reflection? - - - For example, does the code use the `dynamic` keyword when you know what type to expect? - - - Does the code call a method that depends on reflection when some better alternative is available? - +> Specify the runtime directives at a high level to enable your app to be resilient to code changes. We recommend adding runtime directives at the namespace and type levels rather than the member level. Note that there may be a tradeoff between resiliency and larger binaries with longer compile times. + +When addressing a missing metadata exception, consider these issues: + +- What was the app trying to do before the exception? + + - For example, was it data binding, serializing or deserializing data, or directly using the reflection API? + +- Is this an isolated case, or do you believe you'll encounter the same issue for other types? + + - For example, a [MissingMetadataException](../../../docs/framework/net-native/missingmetadataexception-class-net-native.md) exception is thrown when serializing a type in the app’s object model. If you know other types that will be serialized, you can add runtime directives for those types (or for their containing namespaces, depending on how well the code is organized) at the same time. + +- Can you rewrite the code so it doesn’t use reflection? + + - For example, does the code use the `dynamic` keyword when you know what type to expect? + + - Does the code call a method that depends on reflection when some better alternative is available? + > [!NOTE] -> For additional information about handling problems that stem from differences in reflection and the availability of metadata in desktop apps and [!INCLUDE[net_native](../../../includes/net-native-md.md)], see [APIs That Rely on Reflection](../../../docs/framework/net-native/apis-that-rely-on-reflection.md). - - For some specific examples of handling exceptions and other issues that occur when testing your app, see: - -- [Example: Handling Exceptions When Binding Data](../../../docs/framework/net-native/example-handling-exceptions-when-binding-data.md) - -- [Example: Troubleshooting Dynamic Programming](../../../docs/framework/net-native/example-troubleshooting-dynamic-programming.md) - -- [Runtime Exceptions in .NET Native Apps](../../../docs/framework/net-native/runtime-exceptions-in-net-native-apps.md) - +> For additional information about handling problems that stem from differences in reflection and the availability of metadata in desktop apps and [!INCLUDE[net_native](../../../includes/net-native-md.md)], see [APIs That Rely on Reflection](../../../docs/framework/net-native/apis-that-rely-on-reflection.md). + +For some specific examples of handling exceptions and other issues that occur when testing your app, see: + +- [Example: Handling Exceptions When Binding Data](../../../docs/framework/net-native/example-handling-exceptions-when-binding-data.md) + +- [Example: Troubleshooting Dynamic Programming](../../../docs/framework/net-native/example-troubleshooting-dynamic-programming.md) + +- [Runtime Exceptions in .NET Native Apps](../../../docs/framework/net-native/runtime-exceptions-in-net-native-apps.md) + ## See also - [Runtime Directives (rd.xml) Configuration File Reference](../../../docs/framework/net-native/runtime-directives-rd-xml-configuration-file-reference.md)