How to detach entity from context when you no longer have a context reference

c# caching datacontext entity-framework entity-framework-6

Question

I am pre-loading product data on my website as I need this to be accessible fast and would rather this be loaded once on application start up rather than just when it's request. This is one way to make sure things load fast. I do this by eager loading my product entity alongside some other entities and store them in memory.

I then have something like the following to retrieve my data:

public override IEnumerable<Product> Get()
{
    var result = _cacheManager.Get(PreLoadCacheKey) as IEnumerable<Product>;
    if (result != null)
        return result;

    return base.Get();
}

The issue I am facing is that with me using dependency injection, I don't control the scope of my data context (other than setting it to InstancePerRequest() and leaving it be) so when I cache my entities they still have a reference to the original context.

I've tried various things but can't seem to get around the issue of:

 The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects. 

when trying to attach an entity retrieved from the cache to a new entity I am adding to the database.

Things I've tried:

  1. Retrieving the data using AsNoTracking()
  2. Looping through all the results before adding them to the cache and Detaching them from the current context then attaching them to the new context on retrieval from the cache.

Ideally, I'd like to be able to detach a context from an entity from the side of the entity so I could see if the entity is attached to the current context and if not, detach it from the old one and attach it to the new one. From what I've seen though, the only you can detach it though is by having a reference to the old context which I won't have.

Am I missing something obvious?

Edit

This is one example where I'd attach the entity to another context:

var orderLine = order.Lines.FirstOrDefault(ol => ol.Product.Id == product.Id) ?? new SalesOrderLine();

orderLine.Price = price.Price;
orderLine.Product = product; //This is my cache'd entity.
orderLine.ProductPriceType = price.ProductPriceType;
orderLine.Quantity += qty;

order.Customer = customer;
order.Lines.Add(orderLine);
order.Status = SalesOrderStatus.Current;

Update(order);
SaveChanges();

As it stands at the moment, I am forcibly loading an uncached version to get around this issue.

1
4
12/6/2014 8:11:17 PM

Popular Answer

Retrieving the cached data with AsNoTracking is the first step. But (apparently) the objects in the cache are created as proxies, so they are aware of having been created by another context.

So make sure that no proxies, but just POCO's are cached, which you do by disabling proxy creation in the context that fetches the objects to the cache:

db.Configuration.ProxyCreationEnabled = false;

(where db is the DbContext instance).

Then make sure you attach the object to a new context before you use it there. This is important, because if you Add() a new OrderLine, EF may try to add a new Product as well.

I'd like to add that this would all be so much easier if you'd exposed OrderLine.ProductId in your entity model: just setting the Id value would be enough.

1
12/6/2014 8:24:21 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow