Skip to content

Commit

Permalink
Cleanup in related data page
Browse files Browse the repository at this point in the history
* Added note on Include producing JOINs in 3.0 and on the cartesian
  explosion problem.
* Remove warning for VS Intellisense issue which has been fixed
  (dotnet/roslyn#8237).
* Removed the ignored include section
* Removed some old "introduced in version" notes

Closes #1466
  • Loading branch information
roji committed Sep 27, 2019
1 parent 2971689 commit 83e7cad
Showing 1 changed file with 14 additions and 22 deletions.
36 changes: 14 additions & 22 deletions entity-framework/core/querying/related-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ You can use the `Include` method to specify related data to be included in query
> [!TIP]
> Entity Framework Core will automatically fix-up navigation properties to any other entities that were previously loaded into the context instance. So even if you don't explicitly include the data for a navigation property, the property may still be populated if some or all of the related entities were previously loaded.

You can include related data from multiple relationships in a single query.

[!code-csharp[Main](../../../samples/core/Querying/RelatedData/Sample.cs#MultipleIncludes)]
Expand All @@ -36,9 +35,6 @@ You can drill down through relationships to include multiple levels of related d

[!code-csharp[Main](../../../samples/core/Querying/RelatedData/Sample.cs#SingleThenInclude)]

> [!NOTE]
> Current versions of Visual Studio offer incorrect code completion options and can cause correct expressions to be flagged with syntax errors when using the `ThenInclude` method after a collection navigation property. This is a symptom of an IntelliSense bug tracked at https://github.com/dotnet/roslyn/issues/8237. It is safe to ignore these spurious syntax errors as long as the code is correct and can be compiled successfully.
You can chain multiple calls to `ThenInclude` to continue including further levels of related data.

[!code-csharp[Main](../../../samples/core/Querying/RelatedData/Sample.cs#MultipleThenIncludes)]
Expand All @@ -51,6 +47,9 @@ You may want to include multiple related entities for one of the entities that i

[!code-csharp[Main](../../../samples/core/Querying/RelatedData/Sample.cs#MultipleLeafIncludes)]

> [!CAUTION]
> Since version 3.0.0, each `Include` will cause an additional JOIN to be added to SQL queries produced by relational providers, whereas previous versions generated additional SQL queries. This can significantly change the performance of your queries, for better or worse. In particular, LINQ queries with an exceedingly high number of `Include` operators may need to be broken down into multiple separate LINQ queries in order to avoid the cartesian explosion problem.
### Include on derived types

You can include related data from navigations defined only on a derived type using `Include` and `ThenInclude`.
Expand Down Expand Up @@ -106,23 +105,8 @@ Contents of `School` navigation of all People who are Students can be eagerly lo
context.People.Include("School").ToList()
```

### Ignored includes

If you change the query so that it no longer returns instances of the entity type that the query began with, then the include operators are ignored.

In the following example, the include operators are based on the `Blog`, but then the `Select` operator is used to change the query to return an anonymous type. In this case, the include operators have no effect.

[!code-csharp[Main](../../../samples/core/Querying/RelatedData/Sample.cs#IgnoredInclude)]

By default, EF Core will log a warning when include operators are ignored. See [Logging](../miscellaneous/logging.md) for more information on viewing logging output. You can change the behavior when an include operator is ignored to either throw or do nothing. This is done when setting up the options for your context - typically in `DbContext.OnConfiguring`, or in `Startup.cs` if you are using ASP.NET Core.

[!code-csharp[Main](../../../samples/core/Querying/RelatedData/ThrowOnIgnoredInclude/BloggingContext.cs#OnConfiguring)]

## Explicit loading

> [!NOTE]
> This feature was introduced in EF Core 1.1.
You can explicitly load a navigation property via the `DbContext.Entry(...)` API.

[!code-csharp[Main](../../../samples/core/Querying/RelatedData/Sample.cs#Eager)]
Expand All @@ -143,23 +127,24 @@ You can also filter which related entities are loaded into memory.

## Lazy loading

> [!NOTE]
> This feature was introduced in EF Core 2.1.
The simplest way to use lazy-loading is by installing the [Microsoft.EntityFrameworkCore.Proxies](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Proxies/) package and enabling it with a call to `UseLazyLoadingProxies`. For example:

```csharp
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseLazyLoadingProxies()
.UseSqlServer(myConnectionString);
```
Or when using AddDbContext:

```csharp
.AddDbContext<BloggingContext>(
b => b.UseLazyLoadingProxies()
.UseSqlServer(myConnectionString));
```

EF Core will then enable lazy loading for any navigation property that can be overridden--that is, it must be `virtual` and on a class that can be inherited from. For example, in the following entities, the `Post.Blog` and `Blog.Posts` navigation properties will be lazy-loaded.

```csharp
public class Blog
{
Expand All @@ -178,9 +163,11 @@ public class Post
public virtual Blog Blog { get; set; }
}
```

### Lazy loading without proxies

Lazy-loading proxies work by injecting the `ILazyLoader` service into an entity, as described in [Entity Type Constructors](../modeling/constructors.md). For example:

```csharp
public class Blog
{
Expand Down Expand Up @@ -233,7 +220,9 @@ public class Post
}
}
```

This doesn't require entity types to be inherited from or navigation properties to be virtual, and allows entity instances created with `new` to lazy-load once attached to a context. However, it requires a reference to the `ILazyLoader` service, which is defined in the [Microsoft.EntityFrameworkCore.Abstractions](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Abstractions/) package. This package contains a minimal set of types so that there is very little impact in depending on it. However, to completely avoid depending on any EF Core packages in the entity types, it is possible to inject the `ILazyLoader.Load` method as a delegate. For example:

```csharp
public class Blog
{
Expand Down Expand Up @@ -286,7 +275,9 @@ public class Post
}
}
```

The code above uses a `Load` extension method to make using the delegate a bit cleaner:

```csharp
public static class PocoLoadingExtensions
{
Expand All @@ -303,6 +294,7 @@ public static class PocoLoadingExtensions
}
}
```

> [!NOTE]
> The constructor parameter for the lazy-loading delegate must be called "lazyLoader". Configuration to use a different name than this is planned for a future release.
Expand Down

0 comments on commit 83e7cad

Please sign in to comment.