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