Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to include locally cached items in query of DBSet?

I'm just getting my feet wet with Entity Framework, but I'm a bit baffled by some of the behavior of the DBSet Object. When I invoke the Find() method, it seems to be aware of my collection of recently-added (but not yet saved) items, but when I try to query the DBSet, it seems to only include items that have been there all along. Is there an easy way to work around this? I'm including some code that I've done to try to work around this, but when it starts to iterate through the items from my "Added" change set, I get this error:

"Unable to create a constant value of type EntityType. Only primitive types ('such as Int32, String, and Guid') are supported in this context."

internal DbContext Context  { get; set; }
protected DbSet<T> DBSet    { get; set; }

public virtual IEnumerable<T> Get(
    Expression<Func<T, bool>> filter = null,
    Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null,
    bool ignoreCachedChanges = false)
{
    IQueryable<T> oReturn = DBSet;

    // This block is intended to adjust the queryable source to account for changes
    if (!ignoreCachedChanges)
    {
        oReturn = oReturn.Except(Context.ChangeTracker.Entries<T>().Where(x => x.State == System.Data.EntityState.Deleted).Select(x => x.Entity));
        oReturn = oReturn.Union(Context.ChangeTracker.Entries<T>().Where(x => x.State == System.Data.EntityState.Added).Select(x => x.Entity));
    }
    if (filter != null)
        oReturn = oReturn.Where(filter);

    if (orderBy != null)
        return orderBy(oReturn).ToList();
    else
        return oReturn.ToList();
}

// NOTE: Get By ID uses Find which considers the queued-but-not-yet-applied changes
public virtual T GetByID(object id)
{
    return DBSet.Find(id);
}

(In case context helps, I'm doing this because I want to set up a unit test where I populate my (local) context with items that cater to my particular testing environment...I'd just as soon not have to apply those changes since they're really only applicable for that particular test, but I can if need be...In doing that, I was surprised to see that the repository was not including changed items in its queried results -- unless I was doing the FindByID -- so I'm also hoping I can either resolve that apparent inconsistency, or get a better undersanding of why that's not doable...or not a good idea? :) )

like image 391
Steven Avatar asked Nov 05 '22 16:11

Steven


1 Answers

The exception says it: You cannot send a list of entity types (of your generic type T) to the server to execute Except and Union in SQL with these collections of "constant" objects. Basically you must apply Except and Union in memory with LINQ to Objects, which means: after the filtered result from the server has been materialized (so, somewhere after .ToList()). You have to apply the filter a second time to the list of objects in the context which are in Added state.

like image 143
Slauma Avatar answered Nov 15 '22 05:11

Slauma