2

I am having an issue with entity framework including all of the nested entities that are redundant and those entities including the entities that are already loaded and then those entities load the same nested entities etc.

Situation: I have a list of clients with a lot of includes that also have lists of clients.

Question: How do I prevent the Clients properties' from pulling their list of Clients? Currently I have all of the entities set with the Virtual keyword but they're still being included.

public IEnumerable<Property> GetProperties()
    {
        return _context.Property.AsQueryable()
            .Include(x => x.PropertyType).AsNoTracking()
            .Include(x => x.PropertyStatus).AsNoTracking()
            .Include(x => x.EngagementType).AsNoTracking()
            .Include(x => x.IntInvestorClient).AsNoTracking()
            .Include(x => x.PropertySizeType).AsNoTracking()
            .Include(x => x.Division).AsNoTracking()
            .Include(x => x.LocalMarketArea).AsNoTracking()
            .Include(x => x.Country).AsNoTracking();
    }

var all = _repo.GetProperties();

        var result = returnAll ? all.ToList() : all.Skip(offset).Take(limit).ToList();
Rami
  • 490
  • 7
  • 22
  • 2
    You don't tell *why* this is an issue for you, but I guess it's related to [this](https://stackoverflow.com/q/19467673/861716). If so, consider this a duplicate. – Gert Arnold Sep 25 '17 at 20:30
  • I just posted the code and this is producing the issue. I am using postgresql not ms sql if that matters – Rami Sep 25 '17 at 20:57
  • 1
    Again, *why* is this a problem? The entities are interconnected. So what? – Gert Arnold Sep 25 '17 at 21:01
  • I guess its a circular reference is what I am finding, I may just remove a property on another entity to solve this issue. – Rami Sep 25 '17 at 21:07
  • 2
    Well, did you to look at my first comment and the link in it? – Gert Arnold Sep 25 '17 at 21:09
  • @GertArnold your link solved the problem, how do I mark it as the correct answer? – Rami Sep 26 '17 at 14:21

1 Answers1

0

Turn off Change Tracking.

See

Tracking behavior controls whether or not Entity Framework Core will keep information about an entity instance in its change tracker. If an entity is tracked, any changes detected in the entity will be persisted to the database during SaveChanges(). Entity Framework Core will also fix-up navigation properties between entities that are obtained from a tracking query and entities that were previously loaded into the DbContext instance.

https://learn.microsoft.com/en-us/ef/core/querying/tracking

EG

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;

namespace EFCore2Test
{

    public class Note
    {
        public int Id { get; set; }
        public string Value { get; set; }
    }

    public class Item
    {
        public int Id { get; set; }

        public string Name { get; set; }
    }
    public class Part
    {
        public int Id { get; set; }
        public ICollection<Part> ChildParts { get; } = new HashSet<Part>();

        public ICollection<Note> Notes { get; } = new HashSet<Note>();

        public int? ItemId { get; set; }
        public Item Item { get; set; }
    }

    public class Db : DbContext
    {
        public DbSet<Part> Parts { get; set; }
        public DbSet<Item> Items { get; set; }
        public DbSet<Note> Notes { get; set; }


        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {

            base.OnModelCreating(modelBuilder);
        }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer("Server=(local);Database=EfCoreTest;Trusted_Connection=True;MultipleActiveResultSets=true");
            base.OnConfiguring(optionsBuilder);
        }
    }




    class Program
    {


        static void Main(string[] args)
        {

            int partid;
            using (var db = new Db())
            {
                db.Database.EnsureDeleted();
                db.Database.EnsureCreated();

                var item = new Item();
                db.Items.Add(item);

                var p = new Part();
                p.Item = item;

                for (int i = 0; i < 10; i++)
                {
                    var cp = new Part();
                    p.ChildParts.Add(cp);
                    db.Parts.Add(cp);

                }

                for (int i = 0; i < 4; i++)
                {
                    p.Notes.Add(new Note() { Value = "Note" });
                }

                db.Parts.Add(p);

                db.SaveChanges();
                partid = p.Id;
            }


            using (var db = new Db())
            {
                Console.WriteLine("With Change Tracking");

                var q = from p in db.Parts
                                    .Include(p => p.Notes)
                                    .Include(p => p.Item)
                        orderby p.Id == partid?0:1, p.Id
                        select p;

                var parts = q.Take(5).ToList();

                foreach (var p in parts)
                {
                    Console.WriteLine($"Part {p.Id}, Child Parts {p.ChildParts.Count}");

                }
                Console.WriteLine();
            }


            using (var db = new Db())
            {
                Console.WriteLine("Without Change Tracking");

                var q = from p in db.Parts.AsNoTracking()
                                     .Include(p => p.Notes)
                                     .Include(p => p.Item)
                        orderby p.Id == partid ? 0 : 1, p.Id
                        select p;

                var parts = q.Take(5).ToList();

                foreach (var p in parts)
                {
                    Console.WriteLine($"Part {p.Id}, Child Parts {p.ChildParts.Count}");

                }
            }
            Console.WriteLine("Hit any key to exit");
            Console.ReadKey();
        }
    }
}

outputs

With Change Tracking
Part 1, Child Parts 4
Part 2, Child Parts 0
Part 3, Child Parts 0
Part 4, Child Parts 0
Part 5, Child Parts 0

Without Change Tracking
Part 1, Child Parts 0
Part 2, Child Parts 0
Part 3, Child Parts 0
Part 4, Child Parts 0
Part 5, Child Parts 0
Hit any key to exit
David Browne - Microsoft
  • 80,331
  • 6
  • 39
  • 67
  • 1
    Your test is essentially different from OP's code. Try the same thing with `Include` and you get other results. – Gert Arnold Sep 25 '17 at 21:23