【问题标题】:EF Core entity refreshEF Core 实体刷新
【发布时间】:2020-01-30 16:30:54
【问题描述】:

我想在插入后将对象层次结构添加到缓存中后,是否有办法触发对象层次结构的延迟加载。

如果我插入一个只为其提供外键 ID 的对象并尝试在之后立即请求它,则不会检索到这些属性/集合。

例子:

            _dbContext.Set<MYTYPE>().Add(myObject);
            await _dbContext.SaveChangesAsync(ct);
            _dbContext.Entry(myObject).Collection(c => c.SomeCollection).Load();
            _dbContext.Entry(myObject).Reference(c => c.Property1).Load();
            _dbContext.Entry(myObject.Property1).Reference(c => c.NestedProperty).Load();
            _dbContext.Entry(myObject).Reference(c => c.Property2).Load();
            _dbContext.Entry(myObject).Collection(c => c.SomeCollection2).Load();
            _dbContext.Entry(myObject).Reference(c => c.Property3).Load();
            _dbContext.Entry(myObject).Reference(c => c.Property4).Load();
            _dbContext.Entry(myObject.Property4).Reference(c => c.SomeOtherNestedProperty).Load();
            _dbContext.Entry(myObject).Reference(c => c.Property5).Load();
            _dbContext.Entry(myObject).Reference(c => c.Property6).Load();

            return _dbContext.Set<MYTYPE>().Where(x => x.Id == myObject.Id); 

除非我执行所有 Load()(有时必须嵌套到多个层中......),否则我无法正确延迟加载任何子属性。

注意:做

_dbContext.Entry(myObject).Reload()

_dbContext.Entry(myObject).State = EntityState.Detached;

没用。

有什么想法吗?因为我有几个这样的案例,使用 HEAVY 对象嵌套,不得不手动完成所有负载感觉真的很糟糕。

谢谢。

【问题讨论】:

  • 那为什么不尝试不延迟加载呢?急切加载不是一种选择?
  • 问题是它有我在缓存中添加的实体,所以无论我做什么它都不会在没有显式加载的情况下加载其他属性。这没有任何意义,即使我使实体无效......
  • 等等,这一切都是因为您在插入和保存之前将外键作为整数而不是链接整个对象,明白吗?我会发布一个答案来解释。
  • 另外,我建议你看看这个问题的答案stackoverflow.com/questions/40729137/…

标签: entity-framework .net-core


【解决方案1】:

问题是,如果您尝试添加一些仅使用整数作为外键的行,如下所示:

db.tablename.Add(new tablename{

            name = "hello",
            FK_IdofanotherTable = 5
            });
db.SaveChanges();

那么实体不关心立即链接对象,您将无法将链接对象作为属性访问。

这是在现代实体框架中实际完成的方式:

var TheActualCompleteObject = db.AnotherTable.First(t => t.id == 5);

db.tablename.Add(new tablename{

            name = "hello",
            AnotherTable = TheActualCompleteObject
            });
db.SaveChanges();

所以...基本上,无论如何你都会加载对象,它不会让任何东西更快,但它会更加一致。您将能够浏览外键属性。

如果这是不可能的,那么您将不得不在SaveChanges 之后进行查询以检索您的对象并有权访问外部属性(当然是急切地加载它们,否则这是同样的灾难)

示例:

       _dbContext.Configuration.LazyLoadingEnabled = false;
       _dbContext.Set<MYTYPE>().Add(myObject);
       await _dbContext.SaveChangesAsync(ct);
       var v = _dbContext.First(t => t.id == myObject.id);
       var fk_prop = v.Property1;

【讨论】:

  • 确实,对于那些没有被检索到的人,这就是我所做的。但这对 EF 来说很奇怪,当我在 Reload 或 Detached 之后执行新查询时不检索设置了 ID 的属性但不检索实际对象......这完全适得其反。
  • 我在答案中添加了最后一段,也是一个例子
  • 等等,想一想,您需要的只是急切地加载,因为您确实在 return 语句中进行了查询。
  • 是的,延迟加载有时会适得其反,我只使用它来加快某些特定查询...
【解决方案2】:

我也没有找到简单的解决方法。 以下可能会使它更简单...

public static void Reset(this DbContext context)
    {
        var entries = context.ChangeTracker
                            .Entries()
                            .Where(e => e.State != EntityState.Unchanged)
                            .ToArray();
        foreach (var entry in entries) 
        { 
            switch (entry.State) 
            { 
                case EntityState.Modified: 
                    entry.State = EntityState.Unchanged; 
                    break; 
                case EntityState.Added: 
                    entry.State = EntityState.Detached; 
                    break; 
                case EntityState.Deleted: 
                    entry.Reload(); 
                    break; 
            } 
        }
    }

希望这会有所帮助!

JS

【讨论】:

  • 似乎不起作用。尝试重新延迟加载时我仍然遇到问题。
猜你喜欢
  • 1970-01-01
  • 2022-10-18
  • 2020-09-04
  • 1970-01-01
  • 2014-09-06
  • 1970-01-01
  • 1970-01-01
  • 2022-11-30
  • 2021-04-14
相关资源
最近更新 更多