Wednesday, September 11, 2019

Entity Framework - When an object is returned with a NoTracking merge option, Load can only be called when the EntityCollection or EntityReference does not contain objects.

I recently encountered the below Entity Framework error message while mapping to entity data to domain object.

System.InvalidOperationException: When an object is returned with a NoTracking merge option, Load can only be called when the EntityCollection or EntityReference does not contain objects

Here is Entity Framework Model (edmx) diagram and repository method GetOrder() which is  used to get order information on based on order number.

Entity Framework Model (edmx) diagram:


Domain Class:

    public class OrderData
    {
        public int OrderID { getset; }
        public int OrderNumber { getset; }
        public int? StatusID { getset; }
        public string  OrderStatusCode { getset; }
    }


Repository Class:
           
    public OrderData GetOrder(int orderNumber)
        {
           Order orderEntity =  _dbContext.Orders.AsNoTracking().FirstOrDefault(x => x.OrderNumber == orderNumber);

            return orderEntity != null ? new OrderData
            {
                OrderID = orderEntity.OrderID,
                OrderNumber = orderEntity.OrderNumber,
                OrderStatusCode = orderEntity.OrderStatu.StatusCode
            }: null;
        }


In above EF query, AsNoTracking() option is used for Orders entity, it means EF will not track the instantiated Order value and Order entity ‘s navigation properties also will be OFF.

In above Edmx diagram, we can see the Order has a navigation property ‘OrderStatu’ but due to asNoTracking option, all navigation properties of Order entity will be OFF and when we will try to access any navigation property value and It will be throw entity framework  exception

Order orderEntity = _dbContext.Orders.AsNoTracking().FirstOrDefault(x => x.OrderNumber == orderNumber);

So in this scenario, we need to explicitly include navigation property OrderStatu’ by using Include () function

Order orderEntity = _dbContext.Orders.Include(x => x.OrderStatu).AsNoTracking().FirstOrDefault(x => x.OrderNumber == orderNumber);

In other way

Order orderEntity =  _dbContext.Orders.Include("OrderStatu").AsNoTracking().FirstOrDefault(x => x.OrderNumber == orderNumber);

No comments:

SQL Server - Identify unused indexes

 In this blog, we learn about the index usage information (SYS.DM_DB_INDEX_USAGE_STATS) and analyze the index usage data (USER_SEEKS, USER_S...