LINQ to SQL:如何创建条件包含之类的东西?

LINQ to SQL: How to create something like conditional include?

我想创建一个包含 User 的查询,其实体有 Eventtype == 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

无论如何,我可能会直接使用投影,因为这样更安全。