开发者

Querying objects after AddObject before SaveChanges?

In EntityFramework, is that possible to query the objects that have just been added to the context using AddObject but before calling the SaveChanges method?

开发者_运维技巧Thanks


To persist an entity you usually add it to it's DbSet in the context.

For example

var bar = new Bar();
bar.Name = "foo";
var context = new Context();
context.Bars.Add(bar);

Surprisingly, querying context.Bars, the just added entity cannot be found

var howMany = context.Bars.Count(b => b.Name == "foo");
// howMany == 0

After context.SaveChanges() the same line will result 1

The DbSet seems unaware to changes until they're persisted on db.

Fortunately, each DbSet has a Local property that acts like the DbSet itself, but it reflect all in-memory operations

var howMany = context.Bars.Local.Count(b => b.Name == "foo");
// howMany == 1

You can also use Local to add entities

context.Bars.Local.Add(bar);

and get rid of the weird behavior of Entity Framework.


you can query objects like this,

context.ObjectStateManager.GetObjectStateEntries(EntityState.Added).Select(obj => obj.Entity).OfType<TheEntityType>()

this will query the objects which are in added state. If you want other states too you can pass all other states to GetObjectStateEntries method like this.

GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Unchanged)


In hibernate transient instances are already attached to context. Just stumbled upon this EF restriction.

I did not managed to intersect/union the ObjectSet with its transient entities ObjectSet.Local but for our usecase the below find method is sufficient.

In our cases we create some entities lazy depending on unique criteria during an iteration

Find method

If you are using an repository pattern you can create a method like:

public interface IRepository<T> where T : class, IEntity
{
    /// <summary>
    /// Finds the unique Entity with the given predicate.
    /// Depending on implementation also checks transient / local (unsaved) Entities.
    /// </summary>
    /// <param name="predicate"></param>
    /// <returns></returns>
    IQueryable<T> FindAll(Expression<Func<T, bool>> predicate);
}

public class EfRepository<T> : IRepository<T> where T : class, IEntity
{
    protected readonly ObjectContext context;
    protected readonly ObjectSet<T> objectSet;

    /// <summary>
    /// Creates a new repository of the given context.
    /// </summary>
    /// <param name="context"></param>
    public EfRepository(ObjectContext context)
    {
        if (context == null)
            throw new ArgumentException("Context must not be null.");
        this.context = context;
        this.objectSet = context.CreateObjectSet<T>();
    }

    /// <summary>
    /// Also takes local context into consideration for unsaved changes
    /// </summary>
    /// <param name="predicate"></param>
    /// <returns></returns>
    public T Find(Expression<Func<T, bool>> predicate)
    {
        T result = this.objectSet.Where(predicate).FirstOrDefault();
        if (result == null)
            result = this.objectSet.Local().Where(predicate).FirstOrDefault();
        return result;
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜