Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在EF6中重新加载导航属性_C#_Linq_Entity Framework 6_Dbcontext - Fatal编程技术网

C# 在EF6中重新加载导航属性

C# 在EF6中重新加载导航属性,c#,linq,entity-framework-6,dbcontext,C#,Linq,Entity Framework 6,Dbcontext,关于使用Context.Entry(entity).Collection(p=>p.property).Load()重新加载导航属性,我已经读过很多关于stackoverflow的问题,但在我的例子中,它没有给出数据库中更新的值 LazyLoading和ProxyCreation选项被设置为它们的默认值,我已经读到它们默认是打开的 我有一个实体测试的对象,我使用下面的方法从数据库中获取该对象,该对象包含所有相关属性: var test = Repository.GetById(testId, n

关于使用
Context.Entry(entity).Collection(p=>p.property).Load()
重新加载导航属性,我已经读过很多关于stackoverflow的问题,但在我的例子中,它没有给出数据库中更新的值

LazyLoading和ProxyCreation选项被设置为它们的默认值,我已经读到它们默认是打开的

我有一个实体测试的对象,我使用下面的方法从数据库中获取该对象,该对象包含所有相关属性:

var test = Repository.GetById(testId, null, true, new Expression<Func<Test,object>>[] {
    bt=>bt.Baselining,
    ct=>ct.Baselining.BaselineTestCase,
    dt=>dt.Baselining.BaselineTestCase.Baseline,
    ft=>ft.Baselining.Transaction,
    gt=>gt.Baselining.Transaction>Select(x=>x.Fields)
}); 

public virtual T GetById<T>(int id, Func<T,bool> where = null, bool trackChanges = false, params Expression<Func<T,object>>[] includeProps) 
{
    T item = null;
    IQuerable<T> dbQuery = Context.Set<T>();

    if(includeProps != null)
        foreach(Expression<Func<T,object>> navProp in includeProps)
            dbQuery = dbQuery.Include<T,object>(navProp);

    if(where == null)
    {    
        if(!trackChanges) item = dbQuery.AsNoTracking().FirstOrDefault(t=>t.Id == id);
        else item = dbQuery.FirstOrDefault(t=>t.Id == id);
    }
    else
    {
        if(!trackChanges) item = dbQuery.AsNoTracking().Where(where).FirstOrDefault(t=>t.Id == id);
        else item = dbQuery.Where(where).FirstOrDefault(t=>t.Id == id);
    }
    return item;
}
存储库方法类似于:

public virtual void ReloadNavigationProperties(TEntity,TElement>(TEntity entity, Expression<Func<TEntity,ICollection<TElement>>> navProp) where TEntity : class where TElement : class
{
    Context.Entry(entity).Collection(navProp).Load();
}

public virtual T Reload<T>(T entity) where T : class {
    Context.Entry(entity).Reload();
    return entity;
}
因为我有大约100个TransactionQueryFields用于每个TransactionQuery,这个嵌套的foreach需要100次来重新加载每个字段,它的速度非常慢,应该很慢

这里是实体

public class Test 
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int id {get;set;}
    public virtual Baselining Baselining {get;set;}
    public virtual ICollection<TestExecutionResult> TestCaseResults {get;set;} = new List<TestExecutionResult>();
}

public class Baselining 
{
    public Baselining() {}
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int id {get;set;}
    public DateTime BaseliningDate {get;set;}
    public virtual BaselineTestCase BaselineTestCase {get;set;}
    public virtual ICollection<TransactionQuery> Transaction {get;set;} = new List<TransactionQuery>();
}

public class BaselineTestCase 
{
    public BaselineTestCase() {}
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int id {get;set;}
    public virtual Baseline Baseline {get;set;}
    public virtual ICollection<Baselining> Baselinings {get;set;} = new List<Baselining>();
    public Baselining LastBaselining {
        get {return Baselinings.OrderBy(x=>x.BaseliningDate).LastOrDefault(); }
    }
}

public class TransactionQuery : TransactionItem 
{
    public TransactionQuery() {}
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public override int id {get;set;}
    public virtual Baselining Baselining {get;set;}
    public virtual ICollection<TransactionQueryField> Transaction {get;set;} = new List<TransactionQueryField>();
}

public class TransactionQueryField : TransactionItem 
{
    public TransactionQueryField() {}
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public override int id {get;set;}
    public bool Compare {get;set;}
    public bool Critical {get;set;}
}

public abstract class TransactionItem : BaseEntity<int> {
    public string TestResultCode {get;set;}
}

public abstract class BaseEntity<T> {
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public virtual T Id {get;set;}
}
公共类测试
{
[Key,DatabaseGenerated(DatabaseGeneratedOption.None)]
公共int id{get;set;}
公共虚拟基线{get;set;}
公共虚拟ICollection TestCaseResults{get;set;}=new List();
}
公共类基线
{
公共基线()
[Key,DatabaseGenerated(DatabaseGeneratedOption.None)]
公共int id{get;set;}
公共日期时间基线日期{get;set;}
公共虚拟BaselineTestCase BaselineTestCase{get;set;}
公共虚拟ICollection事务{get;set;}=new List();
}
公共类BaselineTestCase
{
公共BaselineTestCase(){}
[Key,DatabaseGenerated(DatabaseGeneratedOption.None)]
公共int id{get;set;}
公共虚拟基线{get;set;}
公共虚拟ICollection基线{get;set;}=new List();
公共基线{
获取{return Baselinings.OrderBy(x=>x.BaseliningDate).LastOrDefault();}
}
}
公共类TransactionQuery:TransactionItem
{
公共事务查询(){}
[Key,DatabaseGenerated(DatabaseGeneratedOption.None)]
公共重写int-id{get;set;}
公共虚拟基线{get;set;}
公共虚拟ICollection事务{get;set;}=new List();
}
公共类TransactionQueryField:TransactionItem
{
公共事务查询字段(){}
[Key,DatabaseGenerated(DatabaseGeneratedOption.None)]
公共重写int-id{get;set;}
公共布尔比较{get;set;}
公共布尔临界{get;set;}
}
公共抽象类TransactionItem:BaseEntity{
公共字符串TestResultCode{get;set;}
}
公共抽象类BaseEntity{
[Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)]
公共虚拟T Id{get;set;}
}
我想了解为什么使用导航属性加载时不加载更新的数据。因为根据我的理解,若我想要加载任何东西,它应该往返于数据库并获取更新的数据。但是,即使是通过重新加载进行快速加载,它也不会给我更新的值


如果我没有正确解释,我很抱歉,尽管我将非常感谢任何关于如何更快地加载我的字段的帮助,可能只需要一个db往返。

这只是一个假设,但我认为没有重新加载导航属性的原因是被跟踪的。 我已经经历过类似的事情,关于
Load
方法,它说:

从数据库加载实体集合。请注意,实体 上下文中已经存在的值不会被中的值覆盖 数据库。

调用
GetById
时,将参数
trackChanges
设置为true。从现在起,将跟踪所有急切加载的实体。
正如我所说的,我不确定这是否是问题所在,但您可以尝试将所有跟踪实体的状态设置为
EntityState.Distached

我已经读过这篇文章,但关键是如果我不跟踪更改,那么我将无法注入实体挂钩,这是我在OnSave和OnLoad期间配置的。因此,我必须跟踪真实的变化。虽然我已经尝试过Object context.Refresh,它正在工作,但我很想知道如何正确处理导航属性的这种情况。我从未使用过EntityHooks包,但是文档在
Load
方法上非常清晰,除了使用
EntityState
DbCollectionEntry
上的属性之外,我想不出其他方法来克服这种情况。
foreach(var tq in test.Baselining.Transaction)
    foreach(var tqfs in tq.Fields) 
        Repository.Reload(tqfs);
public class Test 
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int id {get;set;}
    public virtual Baselining Baselining {get;set;}
    public virtual ICollection<TestExecutionResult> TestCaseResults {get;set;} = new List<TestExecutionResult>();
}

public class Baselining 
{
    public Baselining() {}
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int id {get;set;}
    public DateTime BaseliningDate {get;set;}
    public virtual BaselineTestCase BaselineTestCase {get;set;}
    public virtual ICollection<TransactionQuery> Transaction {get;set;} = new List<TransactionQuery>();
}

public class BaselineTestCase 
{
    public BaselineTestCase() {}
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int id {get;set;}
    public virtual Baseline Baseline {get;set;}
    public virtual ICollection<Baselining> Baselinings {get;set;} = new List<Baselining>();
    public Baselining LastBaselining {
        get {return Baselinings.OrderBy(x=>x.BaseliningDate).LastOrDefault(); }
    }
}

public class TransactionQuery : TransactionItem 
{
    public TransactionQuery() {}
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public override int id {get;set;}
    public virtual Baselining Baselining {get;set;}
    public virtual ICollection<TransactionQueryField> Transaction {get;set;} = new List<TransactionQueryField>();
}

public class TransactionQueryField : TransactionItem 
{
    public TransactionQueryField() {}
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public override int id {get;set;}
    public bool Compare {get;set;}
    public bool Critical {get;set;}
}

public abstract class TransactionItem : BaseEntity<int> {
    public string TestResultCode {get;set;}
}

public abstract class BaseEntity<T> {
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public virtual T Id {get;set;}
}