Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
f7e82d9
Update cs5001.md (#27080)
machielvisser Nov 15, 2021
3c93530
Remove redundant nullable operator (#27023)
ArtyProf Nov 15, 2021
8eb1b6e
VS 2022 'preview' removed (#27070)
jakubkozera Nov 15, 2021
55abc21
Fixed Typo (#27072)
mohamed-azhar Nov 15, 2021
f9adfd1
Update package index with latest published versions (#27083)
azure-sdk Nov 15, 2021
3ce349f
Update ExampleAsyncDisposable.cs (#27074)
wuyuansushen Nov 15, 2021
b7920dd
Details overloading `==` and `!=` operators on the `ValueObject` type…
IEvangelist Nov 15, 2021
64a2471
Fix text element count not starting at 1 (#27010)
enchant97 Nov 15, 2021
241be5d
Update code analysis props for .NET 6 (#26880)
gewarren Nov 16, 2021
210a70e
Update package index with latest published versions (#27095)
azure-sdk Nov 16, 2021
f83657c
Add link to Fedora .NET 6 tracking bug (#27091)
adegeo Nov 16, 2021
a537ee6
Retitle Fact 1 (#27102)
radrow Nov 16, 2021
00e6cae
Add the HTTP keyword to the expected list of available slug completio…
IEvangelist Nov 16, 2021
a9e82f4
Address concerns about inconsistent code style and formatting (#27089)
IEvangelist Nov 16, 2021
b174580
Code block fix (#27103)
kendaleiv Nov 16, 2021
49323a3
Update package index with latest published versions (#27105)
azure-sdk Nov 16, 2021
cde9a3b
Fix NETSDK error number (#27106)
tdykstra Nov 16, 2021
889bf91
Add more info to recommended actions (#27093)
gewarren Nov 16, 2021
6a46344
Add note about .NET Framework (#27107)
gewarren Nov 16, 2021
39b3aab
Update package index with latest published versions (#27108)
azure-sdk Nov 16, 2021
d520d37
fix build suggestions (#27109)
gewarren Nov 16, 2021
93caa7f
Add note about FTP (#27094)
gewarren Nov 16, 2021
550b183
Add with-expressions to anonymous types (#27111)
BillWagner Nov 16, 2021
bd5ba5f
Bump Humanizer (#27124)
dependabot[bot] Nov 17, 2021
feeacb3
Fix Dispose(bool) method overload in ConjunctiveDisposable pattern (#…
wuyuansushen Nov 17, 2021
8ec5808
Add documentation for CA2255 (new in .NET 6) (#27096)
jeffhandley Nov 17, 2021
62cd837
Remove backticks from page metadata (#27114)
jeffhandley Nov 17, 2021
9255bb4
Update package index with latest published versions (#27115)
azure-sdk Nov 17, 2021
22eb48f
acrolinx (#27117)
gewarren Nov 17, 2021
5e211a8
update front matter for .net 6
ardalis Nov 17, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"F#",
"HashiCorp Configuration Language (HCL)",
"HTML",
"HTTP",
"Ini",
"JavaScript",
"JSON",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ This section describes the *inner-loop* development workflow for Docker containe

An application is composed of your own services plus additional libraries (dependencies). The following are the basic steps you usually take when building a Docker application, as illustrated in Figure 5-1.

:::image type="complex" source="./media/docker-app-development-workflow/life-cycle-containerized-apps-docker-cli.png" alt-text="Diagram showing the 7 steps it takes to create a containerized app.":::
:::image type="complex" source="./media/docker-app-development-workflow/life-cycle-containerized-apps-docker-cli.png" alt-text="Diagram showing the seven steps it takes to create a containerized app.":::
The development process for Docker apps: 1 - Code your App, 2 - Write Dockerfile/s, 3 - Create images defined at Dockerfile/s, 4 - (optional) Compose services in the docker-compose.yml file, 5 - Run container or docker-compose app, 6 - Test your app or microservices, 7 - Push to repo and repeat.
:::image-end:::

Expand Down Expand Up @@ -407,7 +407,7 @@ Besides adding a Dockerfile to a project, as we mentioned before, Visual Studio

When you add container orchestrator support, as shown in Figure 5-7, for the first time, Visual Studio creates the Dockerfile for the project and creates a new (service section) project in your solution with several global `docker-compose*.yml` files, and then adds the project to those files. You can then open the docker-compose.yml files and update them with additional features.

You have to repeat this operation for every project you want to include in the docker-compose.yml file.
Repeat this operation for every project you want to include in the docker-compose.yml file.

At the time of this writing, Visual Studio supports **Docker Compose** and **Kubernetes/Helm** orchestrators.

Expand Down Expand Up @@ -508,7 +508,7 @@ This step will vary depending on what your application is doing. In a simple .NE

If localhost is not pointing to the Docker host IP (by default, when using Docker CE, it should), to navigate to your service, use the IP address of your machine's network card.

Note that this URL in the browser uses port 80 for the particular container example being discussed. However, internally the requests are being redirected to port 5000, because that was how it was deployed with the docker run command, as explained in a previous step.
This URL in the browser uses port 80 for the particular container example being discussed. However, internally the requests are being redirected to port 5000, because that was how it was deployed with the docker run command, as explained in a previous step.

You can also test the application using curl from the terminal, as shown in Figure 5-14. In a Docker installation on Windows, the default Docker Host IP is always 10.0.75.1 in addition to your machine's actual IP address.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Implementing value objects
description: .NET Microservices Architecture for Containerized .NET Applications | Get into the details and options to implement value objects using new Entity Framework features.
ms.date: 08/21/2020
ms.date: 11/11/2021
---

# Implement value objects
Expand All @@ -16,7 +16,7 @@ Figure 7-13 shows the Address value object within the Order aggregate.

**Figure 7-13**. Address value object within the Order aggregate

As shown in Figure 7-13, an entity is usually composed of multiple attributes. For example, the `Order` entity can be modeled as an entity with an identity and composed internally of a set of attributes such as OrderId, OrderDate, OrderItems, etc. But the address, which is simply a complex-value composed of country/region, street, city, etc. and has no identity in this domain, must be modeled and treated as a value object.
As shown in Figure 7-13, an entity is usually composed of multiple attributes. For example, the `Order` entity can be modeled as an entity with an identity and composed internally of a set of attributes such as OrderId, OrderDate, OrderItems, etc. But the address, which is simply a complex-value composed of country/region, street, city, etc., and has no identity in this domain, must be modeled and treated as a value object.

## Important characteristics of value objects

Expand Down Expand Up @@ -75,7 +75,23 @@ public abstract class ValueObject
}
```

You can use this class when implementing your actual value object, as with the Address value object shown in the following example:
<a id="equal-op-overload"></a>

The `ValueObject` is an `abstract class` type, but in this example, it doesn't overload the `==` and `!=` operators. You could choose to do so, making comparisons delegate to the `Equals` override. For example, consider the following operator overloads to the `ValueObject` type:

```csharp
public static bool operator ==(ValueObject one, ValueObject two)
{
return one?.Equals(two) ?? false;
}

public static bool operator !=(ValueObject one, ValueObject two)
{
return !(one?.Equals(two) ?? false);
}
```

You can use this class when implementing your actual value object, as with the `Address` value object shown in the following example:

```csharp
public class Address : ValueObject
Expand Down Expand Up @@ -109,12 +125,28 @@ public class Address : ValueObject
}
```

You can see how this value object implementation of Address has no identity and therefore, no ID field, neither at the Address class not even at the ValueObject class.
This value object implementation of `Address` has no identity, and therefore no ID field is defined for it, either in the `Address` class definition or the `ValueObject` class definition.

Having no ID field in a class to be used by Entity Framework (EF) was not possible until EF Core 2.0, which greatly helps to implement better value objects with no ID. That is precisely the explanation of the next section.

It could be argued that value objects, being immutable, should be read-only (that is, have get-only properties), and that's indeed true. However, value objects are usually serialized and deserialized to go through message queues, and being read-only stops the deserializer from assigning values, so you just leave them as `private set`, which is read-only enough to be practical.

### Value object comparison semantics

Two instances of the `Address` type can be compared using all the following methods:

```csharp
var one = new Address("1 Microsoft Way", "Redmond", "WA", "US", "98052");
var two = new Address("1 Microsoft Way", "Redmond", "WA", "US", "98052");

Console.WriteLine(EqualityComparer<Address>.Default.Equals(one, two)); // True
Console.WriteLine(object.Equals(one, two)); // True
Console.WriteLine(one.Equals(two)); // True
Console.WriteLine(one == two); // True
```

When all the values are the same, the comparisons are correctly evaluated as `true`. If you didn't choose to overload the `==` and `!=` operators, then the last comparison of `one == two` would evaluate as `false`. For more information, see [Overload ValueObject equality operators](#equal-op-overload).

## How to persist value objects in the database with EF Core 2.0 and later

You just saw how to define a value object in your domain model. But how can you actually persist it into the database using Entity Framework Core since it usually targets entities with identity?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ no-loc: [Blazor, WebAssembly]
>
> Tim Berners-Lee

Data access is an important part of almost any software application. ASP.NET Core supports a variety of data access options, including Entity Framework Core (and Entity Framework 6 as well), and can work with any .NET data access framework. The choice of which data access framework to use depends on the application's needs. Abstracting these choices from the ApplicationCore and UI projects, and encapsulating implementation details in Infrastructure, helps to produce loosely coupled, testable software.
Data access is an important part of almost any software application. ASP.NET Core supports various data access options, including Entity Framework Core (and Entity Framework 6 as well), and can work with any .NET data access framework. The choice of which data access framework to use depends on the application's needs. Abstracting these choices from the ApplicationCore and UI projects, and encapsulating implementation details in Infrastructure, helps to produce loosely coupled, testable software.

## Entity Framework Core (for relational databases)

Expand Down Expand Up @@ -186,7 +186,7 @@ private void ConfigureBasket(EntityTypeBuilder<Basket> builder)
}
```

Another way in which you can improve your domain model is through the use of value objects for types that lack identity and are only distinguished by their properties. Using such types as properties of your entities can help keep logic specific to the value object where it belongs, and can avoid duplicate logic between multiple entities that use the same concept. In Entity Framework Core, you can persist value objects in the same table as their owning entity by configuring the type as an owned entity, like so:
Another way in which you can improve your domain model is by using value objects for types that lack identity and are only distinguished by their properties. Using such types as properties of your entities can help keep logic specific to the value object where it belongs, and can avoid duplicate logic between multiple entities that use the same concept. In Entity Framework Core, you can persist value objects in the same table as their owning entity by configuring the type as an owned entity, like so:

```csharp
private void ConfigureOrder(EntityTypeBuilder<Order> builder)
Expand Down Expand Up @@ -277,7 +277,7 @@ The first DbContext is the \_catalogContext and the second DbContext is within t

While EF Core is a great choice for managing persistence, and for the most part encapsulates database details from application developers, it isn't the only choice. Another popular open-source alternative is [Dapper](https://github.com/StackExchange/Dapper), a so-called micro-ORM. A micro-ORM is a lightweight, less full-featured tool for mapping objects to data structures. In the case of Dapper, its design goals focus on performance, rather than fully encapsulating the underlying queries it uses to retrieve and update data. Because it doesn't abstract SQL from the developer, Dapper is "closer to the metal" and lets developers write the exact queries they want to use for a given data access operation.

EF Core has two significant features it provides which separate it from Dapper but also add to its performance overhead. The first is the translation from LINQ expressions into SQL. These translations are cached, but even so there is overhead in performing them the first time. The second is change tracking on entities (so that efficient update statements can be generated). This behavior can be turned off for specific queries by using the <xref:System.Data.Entity.DbExtensions.AsNoTracking%2A> extension. EF Core also generates SQL queries that usually are very efficient and in any case perfectly acceptable from a performance standpoint, but if you need fine control over the precise query to be executed, you can pass in custom SQL (or execute a stored procedure) using EF Core, too. In this case, Dapper still outperforms EF Core, but only slightly. Julie Lerman presents some performance data in her May 2016 MSDN article [Dapper, Entity Framework, and Hybrid Apps](/archive/msdn-magazine/2016/may/data-points-dapper-entity-framework-and-hybrid-apps). Additional performance benchmark data for a variety of data access methods can be found on [the Dapper site](https://github.com/StackExchange/Dapper).
EF Core has two significant features it provides which separate it from Dapper but also add to its performance overhead. The first is the translation from LINQ expressions into SQL. These translations are cached, but even so there is overhead in performing them the first time. The second is change tracking on entities (so that efficient update statements can be generated). This behavior can be turned off for specific queries by using the <xref:System.Data.Entity.DbExtensions.AsNoTracking%2A> extension. EF Core also generates SQL queries that usually are very efficient and in any case perfectly acceptable from a performance standpoint, but if you need fine control over the precise query to be executed, you can pass in custom SQL (or execute a stored procedure) using EF Core, too. In this case, Dapper still outperforms EF Core, but only slightly. Julie Lerman presents some performance data in her May 2016 MSDN article [Dapper, Entity Framework, and Hybrid Apps](/archive/msdn-magazine/2016/may/data-points-dapper-entity-framework-and-hybrid-apps). Additional performance benchmark data for various data access methods can be found on [the Dapper site](https://github.com/StackExchange/Dapper).

To see how the syntax for Dapper varies from EF Core, consider these two versions of the same method for retrieving a list of items:

Expand All @@ -297,7 +297,7 @@ public async Task<IEnumerable<CatalogType>> GetCatalogTypesWithDapper()
}
```

If you need to build more complex object graphs with Dapper, you need to write the associated queries yourself (as opposed to adding an Include as you would in EF Core). This functionality is supported through a variety of syntaxes, including a feature called Multi Mapping that lets you map individual rows to multiple mapped objects. For example, given a class Post with a property Owner of type User, the following SQL would return all of the necessary data:
If you need to build more complex object graphs with Dapper, you need to write the associated queries yourself (as opposed to adding an Include as you would in EF Core). This functionality is supported through various syntaxes, including a feature called Multi Mapping that lets you map individual rows to multiple mapped objects. For example, given a class Post with a property Owner of type User, the following SQL would return all of the necessary data:

```sql
select * from #Posts p
Expand Down Expand Up @@ -354,7 +354,7 @@ The Azure Cosmos DB query language is a simple yet powerful interface for queryi

## Other persistence options

In addition to relational and NoSQL storage options, ASP.NET Core applications can use Azure Storage to store a variety of data formats and files in a cloud-based, scalable fashion. Azure Storage is massively scalable, so you can start out storing small amounts of data and scale up to storing hundreds or terabytes if your application requires it. Azure Storage supports four kinds of data:
In addition to relational and NoSQL storage options, ASP.NET Core applications can use Azure Storage to store various data formats and files in a cloud-based, scalable fashion. Azure Storage is massively scalable, so you can start out storing small amounts of data and scale up to storing hundreds or terabytes if your application requires it. Azure Storage supports four kinds of data:

- Blob Storage for unstructured text or binary storage, also referred to as object storage.

Expand Down
6 changes: 3 additions & 3 deletions docs/architecture/modernize-desktop/whats-new-dotnet.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ Starting with .NET Core 3.0, besides the existing support for web and cloud, the
.NET 5 is the next step forward with .NET Core. .NET 5 aims to improve .NET in a few key ways:

- Produce a single .NET runtime and framework that can be used everywhere and that has uniform runtime behaviors and developer experiences.
- Expand the capabilities of .NET by taking the best of .NET Core, .NET Framework, Xamarin and Mono.
- Expand the capabilities of .NET by taking the best of .NET Core, .NET Framework, Xamarin, and Mono.
- Build that product out of a single code-base that developers (Microsoft and the community) can work on and expand together and that improves all scenarios.

This new release and direction are a game-changer for .NET. With .NET 5, your code and project files will look and feel the same no matter which type of app you're building. You’ll have access to the same runtime, APIs, and language capabilities with each app. This includes new [performance improvements](https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-5/) that get committed to the runtime, practically daily. For more details refer [What's new in .NET 5](../../core/whats-new/dotnet-5.md).
This new release and direction are a game-changer for .NET. With .NET 5, your code and project files will look and feel the same no matter which type of app you're building. You’ll have access to the same runtime, APIs, and language capabilities with each app. This includes new [performance improvements](https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-5/) that get committed to the runtime, practically daily. For more details, see [What's new in .NET 5](../../core/whats-new/dotnet-5.md).

![All domains of .NET 5](./media/whats-new-dotnet-core/all-domains-of-dotnet5.png)

Expand Down Expand Up @@ -125,7 +125,7 @@ To make it easier to create XAML Islands for Windows Forms and WPF developers, t

### Access to all Windows 10 APIs

Windows 10 has a great amount of API available for developers to work with. These APIs give access to a wide variety of functionality like Authentication, Bluetooth, Appointments, and Contacts. Now these APIs are exposed through .NET Core and give Windows developers the chance to create powerful desktops apps leveraging the capabilities present on Windows 10.
Windows 10 has a great amount of API available for developers to work with. These APIs give access to a wide variety of functionality like Authentication, Bluetooth, Appointments, and Contacts. Now these APIs are exposed through .NET Core and give Windows developers the chance to create powerful desktops apps using the capabilities present on Windows 10.

### Side-by-side support and self-contained EXEs

Expand Down
Loading