在没有FK /导航属性的模型上运行查询

时间:2015-09-12 08:42:57

标签: c# .net entity-framework linq

假设我的网站中有2个模型/实体,User和Ticket。 用户和票证具有一对多关联(一个用户可以拥有多个票证)。

class User {
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Ticket> Tickets { get; set; }
}

class Ticket {
    public int Id { get; set; }
    public string Type { get; set; }
}

如您所见,故障单模型不包含对用户模型的任何引用。

我的问题是如何过滤属于特定用户的故障单? 如果Ticket模型引用了User模型,我可以这样做:

IEnumerable<Ticket> tickets = context.Tickets.Where(t => t.User.Id == userId);

但是在Ticket模型中没有User对象,它是不可能的。 我意识到我可以加载我想要的用户然后从其模型中访问其票证,但这将花费我不必要地加载用户,我不想加载用户,我只是想加载它票。

谢谢

更新

让我们说每张票可以有多张子票:

class Ticket {
    public int Id { get; set; }
    public string Type { get; set; }
    public virtual ICollection<Ticket> Children { get; set; }
}

根据用户ID,我想获得属于该用户的所有门票,但不是子门票(没有父门票)。

如果票证模型中没有Parent属性,我怎么能这样做?

即使我在Ticket模型中有一个Parent属性并运行此查询:

var tickets = context.Where(u => u.Id == userId).SelectMany(u => u.Tickets).Where(t => t.Parent == null);

但是根据我的理解,由于延迟加载,Parent属性可以通过在数据库本身实际为null或者仅仅因为它尚未加载而为null ...

2 个答案:

答案 0 :(得分:3)

如果你想要的只是特定用户的门票:

var tickets = context.Users
    .Where(u => u.Id == userID)
    .SelectMany(u => u.Tickets);

假设您的模型是数据库支持的,这将导致单个查询只返回Ticket记录列表。

对于&#34的额外测试;不是其他门票的附加测试&#34;你会添加另一个子句,如下所示:

var tickets = context.Users
    .Where(u => u.Id == userID)
    .SelectMany(u => u.Tickets)
    .Where(t => !context.Tickets.Any(t1 => t1.Children.Contains(t)));

请注意,AnyAll相似,我只是认为Any更适合这一点。

答案 1 :(得分:1)

根据更新修改@Corey答案(尝试一下,我只是在没有测试的情况下编写它):

var tickets = context.Users
    .Where(u => u.Id == userID)
    .SelectMany(u => u.Tickets)
    .Where(t => context.Tickets.All(t1 => !t1.Children.Contains(t)));