几天来,我一直在努力从存储库中检索实体(DbContext)。
我试图在原子行动中拯救所有的实体。因此,不同的实体一起代表了对我有价值的东西。如果所有实体都是“有效的”,那么我可以将它们全部保存到数据库中。实体“a”已存储在我的存储库中,需要检索以“验证”实体“b”。
这就是问题所在。我的存储库依赖于DbSet<TEntity>类,该类非常适合linq2sql(Include()导航属性)。但是,DbSet<TEntity>不包含处于“添加”状态的实体。
所以(据我所知)我有两个选择:
使用ChangeTracker查看哪些实体可用,并根据它们的EntityState将它们查询到一个集合中。
使用DbSet<TEntity>.Local属性。
ChangeTracker似乎需要一些额外的努力才能使它工作,这样我就可以使用linq2sql来Include()导航属性,例如。
我觉得这个有点怪。可能只是名字。我刚刚读到了一些性能不太好的东西(比dbset本身慢)。不确定这是不是一个错误的陈述。
有重要实体框架经验的人能对此有所启发吗?“明智”的道路是什么?或者我看到鬼魂了,我应该一直使用DbSet<TEntity>.Local属性吗?
用代码示例更新:
出问题的例子

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

如何使用.Local的示例
在我的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();
    }

这就是我喜欢使用Repository类变量的主要原因。我需要灵活性来DbSet导航属性。如果我使用Include检索ChangeTracker中的实体,这不允许我在以后的时间点延迟加载相关实体。
如果这是接近不可理解的牛市,那么请让我知道,以便我可以改善这个问题。我迫切需要一个答案。
提前很多!

最佳答案

如果希望能够“轻松”对dbset发出查询并让它找到新创建的项,那么需要在创建每个实体后调用saveChanges()。如果使用“工作单元”样式的方法处理持久实体,这实际上没有问题,因为您可以让工作单元将UOW中的所有操作包装为DB事务(即,在创建UOW时创建新的TransactionScope,并在创建UOW时调用commit()对其执行操作UOW已完成)。使用这种结构,更改将被发送到数据库,dbset将看到这些更改,但其他uows将看不到这些更改(模块化您使用的隔离级别)。
如果您不需要这样的开销,那么您需要修改代码,以便在适当的时候使用local(这可能涉及查看local,然后在找不到所需内容时对dbset发出查询)。dbset上的find()方法在这些情况下也非常有用。它将按主键在本地或数据库中查找实体。因此,如果只需要按主键定位项,那么这非常方便(而且还具有性能优势)。

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

10-12 13:30