Trwa ładowanie powiązanych danychLoading Related Data

Program Entity Framework Core umożliwia przy użyciu właściwości nawigacji w modelu załadować powiązanych jednostek.Entity Framework Core allows you to use the navigation properties in your model to load related entities. Istnieją trzy typowe wzorce O/RM używana do załadowania powiązanych danych.There are three common O/RM patterns used to load related data.

  • Ładowanie wczesny oznacza, że powiązane dane są ładowane z bazy danych w ramach początkowego zapytania.Eager loading means that the related data is loaded from the database as part of the initial query.
  • Ładowanie jawne oznacza, że powiązane jest jawnie załadować danych z bazy danych w późniejszym czasie.Explicit loading means that the related data is explicitly loaded from the database at a later time.
  • Powolne ładowanie oznacza, że pokrewne niewidocznie załadowaniu danych z bazy danych podczas uzyskiwania dostępu do właściwości nawigacji.Lazy loading means that the related data is transparently loaded from the database when the navigation property is accessed. Powolne ładowanie nie jest jeszcze możliwe EF podstawowych.Lazy loading is not yet possible with EF Core.

Porada

Można wyświetlić w tym artykule próbki w witrynie GitHub.You can view this article's sample on GitHub.

Ładowanie wczesnyEager loading

Można użyć Include metodę, aby określić powiązane dane mają zostać uwzględnione w wynikach zapytania.You can use the Include method to specify related data to be included in query results. W poniższym przykładzie, blogów, z którego są zwracane w wynikach będzie miał ich Posts właściwości wypełniane przy użyciu powiązanych wpisów.In the following example, the blogs that are returned in the results will have their Posts property populated with the related posts.

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .Include(blog => blog.Posts)
        .ToList();
}

Porada

Entity Framework Core będzie automatycznie konfigurowania właściwości nawigacji z innymi obiektami, które wcześniej zostały załadowane do wystąpienia kontekstu.Entity Framework Core will automatically fix-up navigation properties to any other entities that were previously loaded into the context instance. Dlatego nawet wtedy, gdy wyraźnie nie zawierają danych dla właściwości nawigacji, właściwość nadal może być wypełniana w przypadku niektórych lub wszystkich powiązanych jednostek wcześniej załadowane.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.

Powiązane dane z wielu relacji można uwzględnić w jednym zapytaniu.You can include related data from multiple relationships in a single query.

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .Include(blog => blog.Posts)
        .Include(blog => blog.Owner)
        .ToList();
}

W tym wiele poziomówIncluding multiple levels

Można przejść do relacji z obejmują wiele poziomów powiązanych danych przy użyciu ThenInclude metody.You can drill down thru relationships to include multiple levels of related data using the ThenInclude method. Poniższy przykład ładuje wszystkie blogi, ich powiązane ogłoszeń i autor każdego post.The following example loads all blogs, their related posts, and the author of each post.

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .Include(blog => blog.Posts)
            .ThenInclude(post => post.Author)
        .ToList();
}

Tworzenia łańcucha wielu wywołań ThenInclude aby kontynuować, tym więcej poziomy powiązanych danych.You can chain multiple calls to ThenInclude to continue including further levels of related data.

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .Include(blog => blog.Posts)
            .ThenInclude(post => post.Author)
                .ThenInclude(author => author.Photo)
        .ToList();
}

Możesz łączyć wszystko to zostać uwzględnione w jednym zapytaniu powiązane dane z różnych poziomach i wielu elementów głównych.You can combine all of this to include related data from multiple levels and multiple roots in the same query.

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .Include(blog => blog.Posts)
            .ThenInclude(post => post.Author)
            .ThenInclude(author => author.Photo)
        .Include(blog => blog.Owner)
            .ThenInclude(owner => owner.Photo)
        .ToList();
}

Można dołączyć wielu powiązanych jednostek dla jednego z jednostkami, które ma być.You may want to include multiple related entities for one of the entities that is being included. Na przykład podczas wykonywania zapytania Blogs, obejmują Posts , a następnie chcesz dołączyć zarówno Author i Tags z Posts.For example, when querying Blogs, you include Posts and then want to include both the Author and Tags of the Posts. Aby to zrobić, należy określić każdy obejmować ścieżki od katalogu głównego.To do this, you need to specify each include path starting at the root. Na przykład Blog -> Posts -> Author i Blog -> Posts -> Tags.For example, Blog -> Posts -> Author and Blog -> Posts -> Tags. Oznacza to, że otrzymasz nadmiarowe sprzężeń, w większości przypadków będzie skonsolidować EF sprzężeń podczas generowania SQL.This does not mean you will get redundant joins, in most cases EF will consolidate the joins when generating SQL.

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .Include(blog => blog.Posts)
            .ThenInclude(post => post.Author)
        .Include(blog => blog.Posts)
            .ThenInclude(post => post.Tags)
        .ToList();
}

Ignorowane obejmujeIgnored includes

Jeśli zmienisz zapytanie tak, aby nie będzie już zwracać wystąpień typów jednostek, które rozpoczął się zapytanie, operatorów include są ignorowane.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.

W poniższym przykładzie operatory dołączania są oparte na Blog, ale następnie Select operator służy do zmiany zwracanego typu anonimowego przez zapytanie.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. W takim przypadku operatory include nie obowiązują.In this case, the include operators have no effect.

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .Include(blog => blog.Posts)
        .Select(blog => new
        {
            Id = blog.BlogId,
            Url = blog.Url
        })
        .ToList();
}

Domyślnie EF Core będzie rejestrować ostrzeżenie podczas obejmują operatory są ignorowane.By default, EF Core will log a warning when include operators are ignored. Zobacz rejestrowanie Aby uzyskać więcej informacji o wyświetlaniu dane wyjściowe rejestrowania.See Logging for more information on viewing logging output. Można zmienić to zachowanie, gdy operator include jest ignorowana, aby zgłosić lub nie rób.You can change the behavior when an include operator is ignored to either throw or do nothing. Odbywa się podczas konfigurowania opcji kontekstu — zwykle w DbContext.OnConfiguring, lub Startup.cs Jeśli używasz platformy ASP.NET Core.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.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFQuerying;Trusted_Connection=True;ConnectRetryCount=0")
        .ConfigureWarnings(warnings => warnings.Throw(CoreEventId.IncludeIgnoredWarning));
}

Ładowanie jawneExplicit loading

Uwaga

Ta funkcja została wprowadzona w EF Core 1.1.This feature was introduced in EF Core 1.1.

Można w sposób jawny załadować właściwości nawigacji za pośrednictwem DbContext.Entry(...) interfejsu API.You can explicitly load a navigation property via the DbContext.Entry(...) API.

using (var context = new BloggingContext())
{
    var blog = context.Blogs
        .Single(b => b.BlogId == 1);

    context.Entry(blog)
        .Collection(b => b.Posts)
        .Load();

    context.Entry(blog)
        .Reference(b => b.Owner)
        .Load();
}

Można również jawnie załadować właściwość nawigacji, wykonując oddzielne zapytania, które zwraca powiązanych jednostek.You can also explicitly load a navigation property by executing a seperate query that returns the related entities. Jeśli jest włączone śledzenie zmian, podczas ładowania jednostki, EF Core zostanie automatycznie Ustaw właściwości nawigacji entitiy nowo załadowanych do odwoływania się do żadnych jednostek już załadowany, a następnie ustaw właściwości nawigacji jednostki już załadowany do odwoływania się do nowo załadowanych jednostki.If change tracking is enabled, then when loading an entity, EF Core will automatically set the navigation properties of the newly-loaded entitiy to refer to any entities already loaded, and set the navigation properties of the already-loaded entities to refer to the newly-loaded entity.

Można również uzyskać kwerendy LINQ, która reprezentuje zawartość właściwości nawigacji.You can also get a LINQ query that represents the contents of a navigation property.

Pozwala na wykonywanie czynności, takie jak uruchomienie operatora agregacji za pośrednictwem powiązanych jednostek bez ładowania ich do pamięci.This allows you to do things such as running an aggregate operator over the related entities without loading them into memory.

using (var context = new BloggingContext())
{
    var blog = context.Blogs
        .Single(b => b.BlogId == 1);

    var postCount = context.Entry(blog)
        .Collection(b => b.Posts)
        .Query()
        .Count();
}

Można również filtrować, które powiązanych jednostek są ładowane do pamięci.You can also filter which related entities are loaded into memory.

using (var context = new BloggingContext())
{
    var blog = context.Blogs
        .Single(b => b.BlogId == 1);

    var goodPosts = context.Entry(blog)
        .Collection(b => b.Posts)
        .Query()
        .Where(p => p.Rating > 3)
        .ToList();
}

powolne ładowanieLazy loading

Powolne ładowanie nie jest jeszcze obsługiwany przez EF rdzeń.Lazy loading is not yet supported by EF Core. Możesz wyświetlić elementu opóźnionego ładowania na naszych zaległości do śledzenia tej funkcji.You can view the lazy loading item on our backlog to track this feature.

Ponieważ właściwości nawigacji automatycznie konfigurowania będzie EF Core, można na końcu cykli na wykresie obiektu.Because EF Core will automatically fix-up navigation properties, you can end up with cycles in your object graph. Na przykład ładowanie blogu i powiązanych spowoduje wpisów w obiekcie blog, który odwołuje się do kolekcji wpisów.For example, Loading a blog and it's related posts will result in a blog object that references a collection of posts. Każdy z tych stanowisk ma odwołanie do blogu.Each of those posts will have a reference back to the blog.

Niektórych struktur serializacji nie zezwalają na takie cykle.Some serialization frameworks do not allow such cycles. Na przykład struktury Json.NET zgłosi następujący wyjątek, jeśli encoutered cyklu.For example, Json.NET will throw the following exception if a cycle is encoutered.

Newtonsoft.Json.JsonSerializationException: Self odwołujące się do pętli wykryto dla właściwości "Blog" z typem "MyApplication.Models.Blog".Newtonsoft.Json.JsonSerializationException: Self referencing loop detected for property 'Blog' with type 'MyApplication.Models.Blog'.

Jeśli używasz platformy ASP.NET Core, można skonfigurować struktury Json.NET do ignorowania cykle znalezionych w grafie obiektu.If you are using ASP.NET Core, you can configure Json.NET to ignore cycles that it finds in the object graph. Jest to wykonywane w ConfigureServices(...) metoda Startup.cs.This is done in the ConfigureServices(...) method in Startup.cs.

public void ConfigureServices(IServiceCollection services)
{
    ...

    services.AddMvc()
        .AddJsonOptions(
            options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
        );

    ...
}