在SaveChanges之前的AddObject之后查询对象?

时间:2011-08-09 01:54:52

标签: entity-framework entity-framework-4

在EntityFramework中,可以在调用SaveChanges方法之前查询刚刚使用AddObject添加到上下文中的对象吗?

由于

3 个答案:

答案 0 :(得分:27)

要保留实体,通常会在上下文中将其添加到DbSet

例如

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

令人惊讶的是,查询context.Bars,无法找到刚刚添加的实体

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

context.SaveChanges()之后,同一行会产生1

DbSet似乎没有意识到要更改,直到它们持续存在于db。

幸运的是,每个DbSet都有Local属性,其作用类似于DbSet本身,但它反映了所有内存中的操作

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

您还可以使用Local添加实体

context.Bars.Local.Add(bar);

并摆脱Entity Framework的奇怪行为。

答案 1 :(得分:10)

你可以查询这样的对象,

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

这将查询处于添加状态的对象。如果你也想要其他状态,你可以将所有其他状态传递给GetObjectStateEntries这样的方法。

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

答案 2 :(得分:1)

在休眠中,瞬态实例已经附加到上下文中。偶然发现了这个EF限制。

我没有设法将ObjectSet与其瞬态实体ObjectSet.Local相交/联合,但对于我们的用例,下面的find方法就足够了。

在我们的例子中,我们根据迭代期间的唯一标准创建一些实体惰性

查找方法

如果您使用的是存储库模式,则可以创建一个方法:

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;
    }
}