views:

49

answers:

0

I have a problem in EF4 where a query that I have returns the data that I want into an anonymous type, but when I try to move the data into a "real" type (I'm creating new instances of my EF objects) some data that the code has already pulled down from the database gets lazily loaded and for the lazy load it's using the key from the previous object in the array.

Example:

I'm pulling out inventory items. The query returns Inventory items with IDs: 1,2,3,4. I am using the following syntax to pull the data from the database:

var inventory = query.ToList();

If I hover over inventory after this line executes I can explore the returned data and all looks good at this point. If I explore into the data from the third item in the inventory list (ID 3) I see it has a list of images associated with that inventory item.

A few lines later I instantiate some objects from the EF 4 that were created for my table and populate them with the retrieved data in a foreach loop that looks like this:

foreach (var current in inventory)
{
}

When "current" becomes the third item in the inventory list (ID 3) and I attempt to explore the data in "current" I see a hit go out to the database to pull back the images associated with that inventory item. This it does even though I know the data was already in memory. It only seems to do this with certain lines in the inventory table however. But that's not the worst of it. Once the lazy load is complete and I can see the data in the debugger I see that it has loaded the images for ID 2 (the previous item in the inventory list). To be clear in the debugger I see InventoryId 3, and it has images attached to it that belong to InventoryId 2. If I look at the SQL it sent to the server during the lazy load sure enough in my trace it shows that it queried for images that belong to inventory with ID 2.

Further exploration shows that Inventory with ID 4 does not experience this problem. And if I query the data such that it excludes Inventory with ID 2 from the resultset instead of populating the object representing Inventory ID 3 with images belonging to Inventory with ID 2, it pulls images belonging to Inventory with ID 1, the previous index in the list. Somehow EF is grabbing the previous index's key when it does a lazy load from the db. Again, before my foreach loop I can explore the data belonging to Inventory with ID 3 and no lazy load occurs and the images attached are those that belong to Inventory with ID 3.

I have no idea how to address this issue. Can someone offer some suggestions?

Thanks

-=Edit, here is some more related code=-

The query (I have removed a lot of the query body because it is so big. I have tried to keep in the relevant pieces):

var query = (from a in productRepository.ObjectSet
                select new 
                {
                    ProductId = a.ProductId
                    , CategoryAttachmentAssociations = (from d in ((StrictInventoryModelEntities)productRepository.ObjectContext).AttachmentAssociations
                                                        join da in a.ProductToCategories on d.AttachmentKeyId equals da.CategoryId
                                                        where d.AttachmentType.Name.ToLower().Contains("category") &&
                                                        ((string.IsNullOrEmpty(filter.LanguageCodeIetf)) || (d.Language.AlternateCode.Equals(filter.LanguageCodeIetf, StringComparison.CurrentCultureIgnoreCase)))
                                                        select new { AttachmentAssociation = d, d.Attachment, d.AttachmentType })});

Here's the rest of the code. I marked the locations where the data is correct, and the location where the data gets lazy loaded from the wrong key.

var anonymousResult = query.ToList();

// I stop execution here and view the anonymousResult object. The
// data is correct and no lazy loading occurs
List<Product> result = new List<Product>();

foreach (var current in anonymousResult)
{
    Product newProduct = new Product
    {
        ProductId = current.ProductId
    };

    foreach (var currentAssociation in current.CategoryAttachmentAssociations)
    {
        // I put a breakpoint here, when I try to view the data a SQL query
        // is captured by my trace showing it attempting a lazy load. The query
        // is requesting the wrong data.
        AttachmentAssociation newAssociation = currentAssociation.AttachmentAssociation;
        newAssociation.IsCategoryTable = true;
        newAssociation.UniqueItemId = currentAssociation.AttachmentAssociation.AttachmentKeyId;

        newProduct.AttachmentAssociations.Add(newAssociation);
    }

One thing of note here is that there is no relationship at the schema level between ProductToCategory and AttachmentAssociation, however the join is still sound. I also didn't create an association between the ProductToCategory and AttachmentAssociation tables in the edmx designer. I would but I cannot because CategoryId is not a key field on ProductToCategory.