{"action":"created","issue":{"url":"https://api.github.com/repos/aspnet/EntityFrameworkCore/issues/11664","repository_url":"https://api.github.com/repos/aspnet/EntityFrameworkCore","labels_url":"https://api.github.com/repos/aspnet/EntityFrameworkCore/issues/11664/labels{/name}","comments_url":"https://api.github.com/repos/aspnet/EntityFrameworkCore/issues/11664/comments","events_url":"https://api.github.com/repos/aspnet/EntityFrameworkCore/issues/11664/events","html_url":"https://github.com/aspnet/EntityFrameworkCore/issues/11664","id":313990331,"number":11664,"title":"Include on readonly context object changed in EF Core 2.1 preview 2","user":{"login":"EdwinArends","id":38310814,"avatar_url":"https://avatars3.githubusercontent.com/u/38310814?v=4","gravatar_id":"","url":"https://api.github.com/users/EdwinArends","html_url":"https://github.com/EdwinArends","followers_url":"https://api.github.com/users/EdwinArends/followers","following_url":"https://api.github.com/users/EdwinArends/following{/other_user}","gists_url":"https://api.github.com/users/EdwinArends/gists{/gist_id}","starred_url":"https://api.github.com/users/EdwinArends/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EdwinArends/subscriptions","organizations_url":"https://api.github.com/users/EdwinArends/orgs","repos_url":"https://api.github.com/users/EdwinArends/repos","events_url":"https://api.github.com/users/EdwinArends/events{/privacy}","received_events_url":"https://api.github.com/users/EdwinArends/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-04-13T07:01:19Z","updated_at":"2018-04-13T17:00:39Z","closed_at":null,"author_association":"NONE","body":"In our project we are using EF Core 2.1 preview 2, in the preview 1 version we used to use a lot of Include / ThenInclude methods. In the return methods we use AutoMapper to map the database objects to a return object. We use a UnitOfWork/Repository design pattern for our backend. \r\n\r\nWe explicitly use the AsNoTracking feature for performance/memory reasons. This worked fine in preview 1, but in preview 2 we get the following exception.\r\n\r\n```\r\nException message:\r\nNavigation property 'DocumentType' on entity of type 'Document' cannot be loaded because the entity is not being tracked. Navigation properties can only be loaded for tracked entities.\r\nStack trace:\r\nSystem.InvalidOperationException\r\n  HResult=0x80131509\r\n  Message=Navigation property 'DocumentType' on entity of type 'Document' cannot be loaded because the entity is not being tracked. Navigation properties can only be loaded for tracked entities.\r\n  Source=Microsoft.EntityFrameworkCore\r\n  StackTrace:\r\n   at Microsoft.EntityFrameworkCore.Internal.EntityFinder`1.Load(INavigation navigation, InternalEntityEntry entry)\r\n   at Microsoft.EntityFrameworkCore.Internal.LazyLoader.Load(Object entity, String navigationName)\r\n   at Microsoft.EntityFrameworkCore.Proxies.Internal.LazyLoadingInterceptor.Intercept(IInvocation invocation)\r\n   at Castle.DynamicProxy.AbstractInvocation.Proceed()\r\n   at Castle.Proxies.DocumentProxy.get_DocumentType()\r\n   at Service.Atlas.DocumentService.GetDocument(Guid id) in D:\\dev\\Atlas\\Service.Atlas\\DocumentService.cs:line 80\r\n   at Atlas.Controllers.DocumentController.GetDocumentHeader(Guid id) in D:\\dev\\Atlas\\Atlas.Controllers\\DocumentController.cs:line 107\r\n   at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()\r\n```\r\n\r\n### Steps to reproduce\r\nWe generate a simple Document class from the SQL Server database using Scaffold-DbContext:\r\n```c#\r\n    public partial class Document\r\n    {\r\n        public Document()\r\n        {\r\n        }\r\n\r\n        public Guid Id { get; set; }\r\n        public int DocumentNumber { get; set; }\r\n        public string Description { get; set; }\r\n        public DocumentStatus Status { get; set; }\r\n        public string CreatedBy { get; set; }\r\n        public DateTime CreatedDate { get; set; }\r\n        public string ModifiedBy { get; set; }\r\n        public DateTime? ModifiedDate { get; set; }\r\n        public byte[] RowVersion { get; set; }\r\n\r\n        public virtual ICollection<AuditTrail> AuditTrail { get; set; } = new HashSet<AuditTrail>();\r\n        public virtual ICollection<DocumentAttributeValue> DocumentAttributeValue { get; set; } = new HashSet<DocumentAttributeValue>();\r\n        public virtual ICollection<DocumentType> DocumentType { get; set; } = new HashSet<DocumentType>();\r\n        public virtual ICollection<Revision> Revision { get; set; } = new HashSet<Revision>();\r\n    }\r\n```\r\n\r\nWe use a Repository interface so the service layer can access the database:\r\n```c#\r\n    public class Repository<TEntity> : IRepository<TEntity> where TEntity : class\r\n    {\r\n        private readonly UnitOfWork _unitOfWork;\r\n        private readonly IApplicationLogger _applicationLogger;\r\n\r\n        public Repository(IUnitOfWork unitOfWork, IApplicationLogger applicationLogger)\r\n        {\r\n            _applicationLogger = applicationLogger;\r\n            _unitOfWork = (UnitOfWork) unitOfWork;\r\n        }\r\n\r\n        protected DbSet<TEntity> DbSet => _unitOfWork.DataContext.Set<TEntity>();\r\n\r\n        public virtual IQueryable<TEntity> Get()\r\n        {\r\n            return DbSet;\r\n        }\r\n\r\n        public virtual IQueryable<TEntity> Query()\r\n        {\r\n            return DbSet.AsNoTracking();\r\n        }\r\n\r\n        public virtual IQueryable<TEntity> Get(Expression<Func<TEntity, bool>> where)\r\n        {\r\n            return DbSet.Where(where);\r\n        }\r\n\r\n        public virtual TEntity GetById(object id)\r\n        {\r\n            return DbSet.Find(id);\r\n        }\r\n\r\n        public virtual void Add(TEntity entity)\r\n        {\r\n            _applicationLogger.Info<TEntity>(\"Added entity to database.\");\r\n            DbSet.Add(entity);\r\n        }\r\n\r\n        public virtual void Delete(TEntity entity)\r\n        {\r\n            _applicationLogger.Info<TEntity>($\"Deleting entity.\");\r\n            _unitOfWork.DataContext.Entry(entity).State = EntityState.Deleted;\r\n        }\r\n\r\n        public virtual void Delete(Expression<Func<TEntity, bool>> where)\r\n        {\r\n            var objects = DbSet.Where(where).AsEnumerable();\r\n            foreach (var obj in objects)\r\n            {\r\n                DbSet.Remove(obj);\r\n            }\r\n        }\r\n    }\r\n```\r\n\r\nWe inject the repository in the Startup class:\r\n```c#\r\nservices.AddScoped<IRepository<Document>, Repository<Document>>();\r\n```\r\n\r\nIn our document service class the repository is injected:\r\n\r\n```c#\r\n   public class DocumentService : IDocumentService\r\n    {\r\n        private readonly IRepository<Document> _documentRepository;\r\n        private readonly IRepository<Type> _typeRepository;\r\n        private readonly IRepository<DocumentType> _documentTypeRespository;\r\n        private readonly IRepository<DocumentAttributeValue> _documentAttributeValueRepository;\r\n        private readonly IRepository<Revision> _revisionRepository;\r\n        private readonly IRepository<Attribute> _attributeRepository;\r\n        private readonly IRepository<AttributeValue> _attributeValueRepository;\r\n        private readonly IRepository<AttributeMultiValue> _attributeMultiValueRepository;\r\n        private readonly IRepository<MultiValueAttributeValue> _multiValueAttributeValueRepository;\r\n        private readonly IFileService _fileService;\r\n        private readonly IUnitOfWork _unitOfWork;\r\n\r\n        private readonly IAuditService _audit;\r\n        private readonly IApplicationLogger _logger;\r\n        private readonly IAttributeQuery _attributeQuery;\r\n        private readonly ITypeQuery _typeQuery;\r\n        private readonly IRevisionQuery _revisionQuery;\r\n\r\n        public DocumentService(IRepository<Document> documentRepository, IUnitOfWork unitOfWork,\r\n            IRepository<Revision> revisionRepository, IRepository<Attribute> attributeRepository,\r\n            IFileService fileService,\r\n            IRepository<DocumentType> documentTypeRespository,\r\n            IRepository<DocumentAttributeValue> documentAttributeValueRepository,\r\n            IRepository<AttributeValue> attributeValueRepository,\r\n            IRepository<AttributeMultiValue> attributeMultiValueRepository,\r\n            IRepository<MultiValueAttributeValue> multiValueAttributeValueRepository,\r\n            IRepository<Type> typeRepository,\r\n            IAuditService audit, IApplicationLogger logger, IAttributeQuery attributeQuery, ITypeQuery typeQuery, IRevisionQuery revisionQuery)\r\n        {\r\n            _documentRepository = documentRepository;\r\n            _unitOfWork = unitOfWork;\r\n            _revisionRepository = revisionRepository;\r\n            _attributeRepository = attributeRepository;\r\n            _fileService = fileService;\r\n            _documentTypeRespository = documentTypeRespository;\r\n            _documentAttributeValueRepository = documentAttributeValueRepository;\r\n            _attributeValueRepository = attributeValueRepository;\r\n            _attributeMultiValueRepository = attributeMultiValueRepository;\r\n            _multiValueAttributeValueRepository = multiValueAttributeValueRepository;\r\n            _typeRepository = typeRepository;\r\n            _audit = audit;\r\n            _logger = logger;\r\n            _attributeQuery = attributeQuery;\r\n            _typeQuery = typeQuery;\r\n            _revisionQuery = revisionQuery;\r\n        }\r\n\r\n        public DocumentResponse GetDocument(Guid id)\r\n        {\r\n            var document = _documentRepository.Query()\r\n                .Include(x => x.DocumentType)\r\n                .ThenInclude(x => x.Type)\r\n                .FirstOrDefault(x => x.Id == id);\r\n\r\n            if (document == null) return null;\r\n\r\n            var documentResponse = Mapper.Map(document, new DocumentResponse());\r\n//ERROR OCCURS BELOW\r\n            documentResponse.DocumentTypes = document.DocumentType.Select(documentType => Mapper.Map(documentType.Type, new TypeResponse()));\r\n            return documentResponse;\r\n          \r\n        }\r\n   }\r\n```\r\n\r\nThis error occurs in EF Core 2.1 preview 2, in EF Core 2.1 preview 1 this code was accepted and ran perfectly well.\r\nMy question is. Is this by design and do we need to change our code? Or has this accidentally gotten broken in the preview 2 version?\r\n\r\nKind regards,\r\nEdwin\r\n\r\n### Further technical details\r\nEF Core version: EF Core 2.1 preview 2\r\nDatabase Provider: Microsoft.EntityFrameworkCore.SqlServer\r\nOperating system: Windows 10 professional\r\nIDE: Visual Studio 2017 15.4\r\n"},"comment":{"url":"https://api.github.com/repos/aspnet/EntityFrameworkCore/issues/comments/381198849","html_url":"https://github.com/aspnet/EntityFrameworkCore/issues/11664#issuecomment-381198849","issue_url":"https://api.github.com/repos/aspnet/EntityFrameworkCore/issues/11664","id":381198849,"user":{"login":"ajcvickers","id":1430078,"avatar_url":"https://avatars1.githubusercontent.com/u/1430078?v=4","gravatar_id":"","url":"https://api.github.com/users/ajcvickers","html_url":"https://github.com/ajcvickers","followers_url":"https://api.github.com/users/ajcvickers/followers","following_url":"https://api.github.com/users/ajcvickers/following{/other_user}","gists_url":"https://api.github.com/users/ajcvickers/gists{/gist_id}","starred_url":"https://api.github.com/users/ajcvickers/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ajcvickers/subscriptions","organizations_url":"https://api.github.com/users/ajcvickers/orgs","repos_url":"https://api.github.com/users/ajcvickers/repos","events_url":"https://api.github.com/users/ajcvickers/events{/privacy}","received_events_url":"https://api.github.com/users/ajcvickers/received_events","type":"User","site_admin":false},"created_at":"2018-04-13T17:00:39Z","updated_at":"2018-04-13T17:00:39Z","author_association":"MEMBER","body":"@EdwinArends The error is coming from lazy-loading. I believe in preview1, attempting to lazy-load when the entity is not tracked was silently ignored. In preview2, it started throwing to let you know that lazy-loading wasn't happening. Couple of questions:\r\n* Is lazy-loading enabled intentionally?\r\n* Are you intentionally using the assumption that lazy-loading will be a no-op for no-tracking queries?\r\n"}}
{"actor":{"display_login":"ajcvickers"}}