62

在我关于模拟 DbContext.Set的另一个问题之后,我还有另一个关于模拟 EF Code First 的问题。

我现在有一个更新方法,如下所示:

if (entity == null)
    throw new ArgumentNullException("entity");

Context.GetIDbSet<T>().Attach(entity);
Context.Entry(entity).State = EntityState.Modified;
Context.CommitChanges();

return entity;

Context是我自己的DbContext的一个接口。

我遇到的问题是,我该如何处理

Context.Entry(entity).State.

我已经逐步完成了这段代码,当我有一个真实的 DbContext 作为我的 Context 接口的实现时,它就可以工作。但是当我把我的假上下文放在那里时,我不知道如何处理它。

DbEntityEntry 类没有构造函数,所以我不能只在我的假上下文中创建一个新的。

有没有人在您的 CodeFirst 解决方案中模拟或伪造 DbEntityEntry 取得任何成功?

还是有更好的方法来处理状态变化?

4

2 回答 2

99

就像其他情况一样,您需要添加一个额外的间接级别:

interface ISalesContext
{
    IDbSet<T> GetIDbSet<T>();
    void SetModified(object entity)
}

class SalesContext : DbContext, ISalesContext
{
    public IDbSet<T> GetIDbSet<T>()
    {
        return Set<T>();
    }

    public void SetModified(object entity)
    {
        Entry(entity).State = EntityState.Modified;
    }
}

因此,您只需调用SetModified.

于 2011-02-18T00:19:32.507 回答
4

当我需要用 进行单元测试时发现这个问题Moq,不需要你自己的界面。我想将特定字段设置为不修改,但该方法SetModified也可以与对象一起使用。

数据库上下文:

public class AppDbContext : DbContext
{   
    ...
    public virtual void SetModified(GuidEntityBase entity)
    {
        Entry(entity).State = EntityState.Modified;
        Entry(entity).Property(x => x.CreatedDate).IsModified = false;
        Entry(entity).Property(x => x.CreatedBy).IsModified = false;
    }
    ...
}

测试:

var mockContext = new Mock<AppDbContext>();
mockContext.Setup(c => c.MyDbSet).Returns(mockMyDbSet.Object);
mockContext.Setup(c => c.SetModified(It.IsAny<GuidEntityBase>()));
于 2019-01-03T14:15:07.100 回答