C# 实体框架6.1.3:投影-直接加载子对象的子对象
我的目标是只访问数据库一次,并通过筛选的子集合获取订单 为了实现这一点,我使用了一个投影:C# 实体框架6.1.3:投影-直接加载子对象的子对象,c#,entity-framework,linq,projection,anonymous-types,C#,Entity Framework,Linq,Projection,Anonymous Types,我的目标是只访问数据库一次,并通过筛选的子集合获取订单 为了实现这一点,我使用了一个投影: using (var db = new context()) { var query = from o in db.Orders select new {
using (var db = new context())
{
var query = from o in db.Orders
select
new
{
Order = o,
Events = o.Events.Where(
e => e.SomeBool
&& e.SomeBool2
),
EventsGroups = o.Events.Where(
e => e.SomeBool
&& e.SomeBool2
).Select(e => e.Groups),
};
}
var query = from o in db.Orders
select new
{
Order = o,
Events = (from e in o.Events
where e.SomeBool && e.SomeBool2
select new
{
Event = e,
Groups = e.Groups,
}),
};
这里的问题是没有加载子集合“事件组”。为了解决这个问题,我将其作为查询中的另一个属性“EventsGroups”加载,然后将其与事件一起放在一起
我的问题:是否有办法将子“组”直接加载到“事件”中,这样我就不必将它们作为另一个属性了
沿着
Events = o.Events.Where(
e => e.SomeBool
&& e.SomeBool2
).Include(e => e.Groups), //this cannot be done this way
为什么我使用投影而不是快速加载: 基础类:
public class Order
{
public Order()
{
Events = new HashSet<Event>();
}
public int Id { get; set; }
public virtual ICollection<Event> Events { get; set; }
}
public class Event
{
public Event()
{
Groups = new HashSet<Group>();
}
public int Id { get; set; }
public bool SomeBool { get; set; }
public bool SomeBool2 { get; set; }
public virtual ICollection<Group> Groups { get; set; }
}
public class Group
{
public Group()
{
Events = new HashSet<Event>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Event> Events { get; set; }
}
公共类秩序
{
公共秩序()
{
Events=newhashset();
}
公共int Id{get;set;}
公共虚拟ICollection事件{get;set;}
}
公开课活动
{
公共活动()
{
Groups=newhashset();
}
公共int Id{get;set;}
公共bool SomeBool{get;set;}
公共bool SomeBool2{get;set;}
公共虚拟ICollection组{get;set;}
}
公共课组
{
公共组()
{
Events=newhashset();
}
公共int Id{get;set;}
公共字符串名称{get;set;}
公共虚拟ICollection事件{get;set;}
}
由于包含
不能与匿名投影相结合,您需要以投影顺序事件的相同方式投影事件组
,即使用另一种匿名类型投影:
using (var db = new context())
{
var query = from o in db.Orders
select
new
{
Order = o,
Events = o.Events.Where(
e => e.SomeBool
&& e.SomeBool2
),
EventsGroups = o.Events.Where(
e => e.SomeBool
&& e.SomeBool2
).Select(e => e.Groups),
};
}
var query = from o in db.Orders
select new
{
Order = o,
Events = (from e in o.Events
where e.SomeBool && e.SomeBool2
select new
{
Event = e,
Groups = e.Groups,
}),
};
您可以通过设置Configuration.LazyLoadingEnabled=true来加载所有内容代码>,不需要任何包含,当然。。。必须牢记业绩。。视情况而定
public MyDatabaseContext(string databaseName)
: base(databaseName)
{
Configuration.LazyLoadingEnabled = true;
}
我相信这应该对你有用:
using (var db = new context())
{
var query = db.Orders
.Include(o=>o.Events)
.Include(o=>o.Events.Select(e=>e.Groups))
.Select(o=>new
{
Order = o,
Events = o.Events.Where(e => e.SomeBool && e.SomeBool2)
});
}
如果没有,这将:
using (var db = new context())
{
var query = db.Orders
.Include(o=>o.Events)
.Include(o=>o.Events.Select(e=>e.Groups))
.Select(o=>new Order
{
Id=o.Id,
Events = o.Events.Where(e => e.SomeBool && e.SomeBool2).ToList()
});
}
你能试试o.Events.include(e=>e.Groups)吗(…
?你的意思是在投影内部吗?我不认为存在包含。对不起,你是对的。我认为@Ivans下面的答案应该有效。这打破了我只访问一次数据库的目标。这比我的方式更美好,更容易组合。我怀疑这是我可以避免循环的一个接近点从任意对象构造DTO对象。如果您确实有DTO对象,则可以直接投影到它们,而不是匿名类型-EF支持这一点。这在测试时不起作用。未加载组。获取命令和筛选的事件起作用,但事件上的组只有一个空列表。包含不起作用似乎在做任何事情,不管有没有它们,结果都是一样的。嗯。很有趣。一个简单的修复方法是在Include和Select之间添加.ToList()
。这肯定会起作用,但是,您将检索所有事件记录,而不仅仅是那些符合.Where
条件的记录。