LINQ to SQL:如何创建条件包含之类的东西?
LINQ to SQL: How to create something like conditional include?
我想创建一个包含 User
的查询,其实体有 Event
和 type == 1
。我还想将 Event
条目加载到 EventsCollection
中。我的代码类似于 .Include(u => u.EventsCollection)
,但这只会加载所有 Event
条目 - 我只想加载类型 == 1.
我有这样的简单模型:
public class User
{
public int UserId { get; set; }
public ICollection<Event> EventsCollection { get; set; }
}
public class Event
{
public int EventId { get; set; }
public int UserId { get; set; }
public int Type { get; set; }
public User User {get; set; }
}
有什么想法吗?
编辑:
我终于找到了解决方案:
我们需要新的 DataContext 对象,之前没有加载任何事件实体。
然后我们需要像这样过滤事件:
var filteredEventsCollection = db.Events
.Where(ev => ev.Type == 1)
.ToList(); //Materialize query here
现在我们应该这样查询用户:
var usersWithFilteredEvents = db.Users
.Where(u => u.EventsCollection.Any(ev => ev.Type == 1))
.ToList();
仅此而已! EF 将自己用第一个查询中的数据替换 EventsCollection。
如果您只想获取 userID ==1 的事件,您可以使用以下方法。这将只为您提供您需要的用户事件集合中的事件。
User u = new User()
{
UserId = 60
};
Event e1 = new Event() { EventId = 1, UserId = 2, Type = 3, User = u };
Event e2 = new Event() { EventId = 2, UserId = 3, Type = 4, User = u };
Event e3 = new Event() { EventId = 3, UserId = 4, Type = 5, User = u };
Event e_Test = new Event() { EventId = 7, UserId = 1, Type = 5, User = u };
u.EventsCollection = new List<Event>();
u.EventsCollection.Add(e1);
u.EventsCollection.Add(e2);
u.EventsCollection.Add(e3);
u.EventsCollection.Add(e_Test);
var h = from use in u.EventsCollection where use.UserId == 1 select use;
这将为您提供所需的信息:
void Main(){
List<User> users = new List<User>{
new User{ UserId=1},
new User{ UserId=2}
};
List<Event> events = new List<Event>{
new Event{ EventId=1, UserId=2, Type=0},
new Event{ EventId=2, UserId=2, Type=1},
new Event{ EventId=4, UserId=2, Type=1},
new Event{ EventId=5, UserId=2, Type=0},
new Event{ EventId=1, UserId=1, Type=1},
new Event{ EventId=2, UserId=1, Type=0},
new Event{ EventId=4, UserId=1, Type=0},
new Event{ EventId=5, UserId=1, Type=1},
};
var result = users.GroupJoin(events.Where (e =>e.Type==1 ),
u => u.UserId,
e => e.UserId,
(a, b) => new {a.UserId,b});
//result.Dump();
}
// Define other methods and classes here
public class User
{
public int UserId { get; set; }
public ICollection<Event> EventsCollection { get; set; }
}
public class Event
{
public int EventId { get; set; }
public int UserId { get; set; }
public int Type { get; set; }
public User User {get; set; }
}
您不能使用 Include
并过滤哪些实体是急切加载(或延迟加载)的,但您可以使用投影来伪造它:
var result = (from u in db.Users
where u.EventsCollection.Any(ev => ev.Type == 1)
select new {
User = u,
Events = u.EventsCollection.Where(ev => ev.Type == 1),
}).ToList() // materialize query here!
.Select(uev => uev.User)
.ToList();
- 这应该 return 一个 IEnumerable,其中包含您在
EventCollection
中想要的事件
- 如果先前已将其他
Event
个实体加载到上下文中,这将不起作用!
- 还必须为
User.EventsCollection
禁用延迟加载,方法是删除 virtual
(您已经完成)或在整个上下文中禁用它。
- 见this link
无论如何,我可能会直接使用投影,因为这样更安全。
我想创建一个包含 User
的查询,其实体有 Event
和 type == 1
。我还想将 Event
条目加载到 EventsCollection
中。我的代码类似于 .Include(u => u.EventsCollection)
,但这只会加载所有 Event
条目 - 我只想加载类型 == 1.
我有这样的简单模型:
public class User
{
public int UserId { get; set; }
public ICollection<Event> EventsCollection { get; set; }
}
public class Event
{
public int EventId { get; set; }
public int UserId { get; set; }
public int Type { get; set; }
public User User {get; set; }
}
有什么想法吗?
编辑:
我终于找到了解决方案: 我们需要新的 DataContext 对象,之前没有加载任何事件实体。
然后我们需要像这样过滤事件:
var filteredEventsCollection = db.Events
.Where(ev => ev.Type == 1)
.ToList(); //Materialize query here
现在我们应该这样查询用户:
var usersWithFilteredEvents = db.Users
.Where(u => u.EventsCollection.Any(ev => ev.Type == 1))
.ToList();
仅此而已! EF 将自己用第一个查询中的数据替换 EventsCollection。
如果您只想获取 userID ==1 的事件,您可以使用以下方法。这将只为您提供您需要的用户事件集合中的事件。
User u = new User()
{
UserId = 60
};
Event e1 = new Event() { EventId = 1, UserId = 2, Type = 3, User = u };
Event e2 = new Event() { EventId = 2, UserId = 3, Type = 4, User = u };
Event e3 = new Event() { EventId = 3, UserId = 4, Type = 5, User = u };
Event e_Test = new Event() { EventId = 7, UserId = 1, Type = 5, User = u };
u.EventsCollection = new List<Event>();
u.EventsCollection.Add(e1);
u.EventsCollection.Add(e2);
u.EventsCollection.Add(e3);
u.EventsCollection.Add(e_Test);
var h = from use in u.EventsCollection where use.UserId == 1 select use;
这将为您提供所需的信息:
void Main(){
List<User> users = new List<User>{
new User{ UserId=1},
new User{ UserId=2}
};
List<Event> events = new List<Event>{
new Event{ EventId=1, UserId=2, Type=0},
new Event{ EventId=2, UserId=2, Type=1},
new Event{ EventId=4, UserId=2, Type=1},
new Event{ EventId=5, UserId=2, Type=0},
new Event{ EventId=1, UserId=1, Type=1},
new Event{ EventId=2, UserId=1, Type=0},
new Event{ EventId=4, UserId=1, Type=0},
new Event{ EventId=5, UserId=1, Type=1},
};
var result = users.GroupJoin(events.Where (e =>e.Type==1 ),
u => u.UserId,
e => e.UserId,
(a, b) => new {a.UserId,b});
//result.Dump();
}
// Define other methods and classes here
public class User
{
public int UserId { get; set; }
public ICollection<Event> EventsCollection { get; set; }
}
public class Event
{
public int EventId { get; set; }
public int UserId { get; set; }
public int Type { get; set; }
public User User {get; set; }
}
您不能使用 Include
并过滤哪些实体是急切加载(或延迟加载)的,但您可以使用投影来伪造它:
var result = (from u in db.Users
where u.EventsCollection.Any(ev => ev.Type == 1)
select new {
User = u,
Events = u.EventsCollection.Where(ev => ev.Type == 1),
}).ToList() // materialize query here!
.Select(uev => uev.User)
.ToList();
- 这应该 return 一个 IEnumerable,其中包含您在
EventCollection
中想要的事件
- 如果先前已将其他
Event
个实体加载到上下文中,这将不起作用! - 还必须为
User.EventsCollection
禁用延迟加载,方法是删除virtual
(您已经完成)或在整个上下文中禁用它。 - 见this link
无论如何,我可能会直接使用投影,因为这样更安全。