c# - DbSet<>.Local 是否需要特别小心使用?

标签 c# entity-framework dbcontext dbset

几天来,我一直在努力从存储库 (DbContext) 中检索我的实体。

我正在尝试将所有实体保存在一个原子操作中。因此,不同的实体一起代表对我有值(value)的东西。如果所有实体都是“有效”的,那么我可以将它们全部保存到数据库中。实体“a”已存储在我的存储库中,需要检索以“验证”实体“b”。

这就是问题所在。我的存储库依赖于 DbSet<TEntity>与 Linq2Sql 一起工作的类(Include() 导航属性,例如)。但是,DbSet<TEntity>不包含处于“已添加”状态的实体。

所以我(据我所知)有两个选择:

  • 使用ChangeTracker查看哪些实体可用并根据其 EntityState 将它们查询到一个集合中.
  • 使用DbSet<TEntity>.Local属性(property)。

ChangeTracker似乎需要一些额外的努力才能让它以某种方式工作,这样我就可以使用 Linq2Sql 来 Include()导航属性,例如

DbSet<TEntity>.Local我觉得有点奇怪。这可能只是名字。我刚刚读到一些它表现不佳的东西(比 DbSet<> 本身慢)。不确定这是否是错误的陈述。

有 EntityFramework 丰富经验的人能对此有所启发吗?什么是“明智”的道路?还是我看到了鬼魂,我是否应该始终使用 .Local属性(property)?

更新代码示例:


错误示例

    public void AddAndRetrieveUncommittedTenant()
    {
        _tenantRepository = new TenantRepository(new TenantApplicationTestContext());

        const string tenantName = "testtenant";

        // Create the tenant, but not call `SaveChanges` yet until all entities are validated 
        _tenantRepository.Create(tenantName);

        //
        // Some other code
        //

        var tenant = _tenantRepository.GetTenants().FirstOrDefault(entity => entity.Name.Equals(tenantName));

        // The tenant will be null, because I did not call save changes yet,
        // and the implementation of the Repository uses a DbSet<TEntity>
        // instead of the DbSet<TEntity>.Local.
        Assert.IsNotNull(tenant);

        // Can I safely use DbSet<TEntity>.Local ? Or should I play 
        // around with DbContext.ChangeTracker instead?
    }

我想如何使用我的 Repository 的示例

在我的 Repository我有这个方法:

    public IQueryable<TEntity> GetAll()
    {
        return Context.Set<TEntity>().AsQueryable();
    }

我以这种方式在业务代码中使用:

    public List<Case> GetCasesForUser(User user)
    {
        return _repository.GetAll().
            Where(@case => @case.Owner.EmailAddress.Equals(user.EmailAddress)).
            Include(@case => @case.Type).
            Include(@case => @case.Owner).
            ToList();
    }

这主要是我更喜欢坚持 DbSet 的原因像变量。我需要灵 active Include导航属性。如果我使用 ChangeTracker我在 List 中检索实体,这不允许我在以后的某个时间延迟加载相关实体。

如果这接近于难以理解的废话*t,那么请告诉我,以便我改进问题。我迫切需要一个答案。

提前致谢!

最佳答案

如果您希望能够“轻松地”对 DbSet 发出查询并让它找到新创建的项目,那么您需要在创建每个实体后调用 SaveChanges()。如果您使用“工作单元”风格的方法来处理持久实体,这实际上没有问题,因为您可以让工作单元将 UoW 中的所有操作包装为 DB 事务(即,在 UoW 时创建一个新的 TransactionScope被创建,并在 UoW 完成时对其调用 Commit())。使用此结构,更改将发送到数据库,并且对 DbSet 可见,但对其他 UoW 不可见(模数您使用的任何隔离级别)。

如果您不想要这样的开销,那么您需要修改代码以在适当的时候使用 Local(这可能涉及查看 Local,然后如果您不希望使用 Local,则对 DbSet 发出查询找到你要找的东西)。 DbSet 上的 Find() 方法在这些情况下也非常有用。它将通过主键在本地或数据库中找到一个实体。所以如果你只需要通过主键定位项目,这非常方便(并且具有性能优势)。

关于c# - DbSet<>.Local 是否需要特别小心使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15094903/

相关文章:

C# App.Config - 未获取类(class)集合的值

c# - 从外部函数 C++ DLL 调用静态函数

c# - 为什么这个 LINQ 抛出 "FormatException was unhandled"?

c# - 在 Entity Framework 6.1 中添加存储过程的问题

c# - 从具体化 'System.DateTime' 类型到 'System.String' 类型的指定转换无效

c# - 在 Entity Framework 中使用 DbContext 运行异步调用

c# - 从托管代码获取安装日期

c# - 如何重用 where 条件

entity-framework-4 - 如何在多个 DbContext 类中强制只进行一项事务?

asp.net-mvc - 如何在 MVC 4 中使用我自己的 User 表而不是默认的 UserProfile?