我有一个名为Filter的对象,它具有以下属性:
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Type> Types{ get; set; }
public virtual ICollection<Step> Steps { get; set; }
public virtual ICollection<Flow> Flows { get; set; }
public virtual ICollection<Room> Rooms { get; set; }
当我从数据库中选择过滤器列表时,我不知道如何包括集合(类型,步骤,流程,房间)。我的代码如下:
var filters = (
from filter in dbContext.DbSet<Filter>()
let rooms = (
from r in dbContext.DbSet<Room>()
select r
)
let eventTypes = (
from t in dbContext.DbSet<Type>()
select t
)
let processFlows = (
from f in dbContext.DbSet<Flow>()
select f
)
let processFlowSteps = (
from s in dbContext.DbSet<Step>()
select s
)
select filter
).ToList();
返回了我的Filter集合,但是里面的集合为空。您能告诉我如何实现吗?
Ps:由于性能问题,我不想使用Include,我不喜欢Entity Framework如何生成查询,并且我想这样做。
答案 0 :(得分:1)
您需要使用Include
扩展方法:
var filters=dbContext.DbSet<Filter>()
.Include(f=>f.Types)
.Include(f=>f.Steps)
.Include(f=>f.Flows)
.Include(f=>f.Rooms)
.ToList()
@MrSilent,Include
扩展方法是专门为加载相关实体而设计的,我认为您拥有的另一种选择是执行raw sql,但是您做的方式却并非如此要进行一次,您有四个往返数据库的往返时间,而您需要使用join来获取相关实体,Include
会为您生成这些连接,而这只是一次往返。
例如,这是我想您可以使用的另一种方式,但是再次违反了使用EF的目的,模型的思想还在于表示表之间的关系,而不仅仅是表示它们之间的关系。
var query= from f in context.DbSet<Filter>()
from s in f.Steps
from r in f.Rooms
from t in f.Types
from fl in f.Flows
select new {f, s, r, t, fl};
答案 1 :(得分:1)
您的方法有效,您只是在做错了。
要包括导航属性,您要做的只是一个子选择(使用linq),例如:
var filters = (from filter in dbContext.DbSet<Filter>()
select new Filter
{
filter.Id,
filter.Name,
Rooms = (from r in dbContext.DbSet<Room>()
where r.FilterId == filter.Id
select r).ToList()
}).ToList();
请记住,直到您调用返回方法(ToList,Any,FirstOrDefault等),EF才会执行查询。这样,它不会执行不希望通过不使用Include()避免的丑陋查询,而只会触发两个查询并在所需对象中正确分配值。
答案 2 :(得分:0)
您可以使用延迟加载,方法如下:
您首先需要获取Include属性,使其成为虚拟属性,然后获取一个受保护的访问类型的空构造函数以很好地完成工作。
public virtual ICollection<Type> Types{ get; set; }
public virtual ICollection<Step> Steps { get; set; }
public virtual ICollection<Flow> Flows { get; set; }
public virtual ICollection<Room> Rooms { get; set; }
还有
//FOR EF !
protected Filter() { }
我认为此解决方案可以解决您的问题。