PredicateBuilder,使用EF在2个表上构建谓词

时间:2014-03-05 23:15:28

标签: c# entity-framework ef-code-first predicatebuilder

我遇到了一个复杂的问题,但对它的解释更为复杂(我认为)。但无论如何我都会试一试,如果不清楚的话,请让我详细说明。

我有一张名为UserService的表格。服务是用户提供的任何服务,例如在咖啡馆中播放的乐队。另一个是DJ和房间。这是表格的样子:

[Table("UserService")]
public class UserService
{
    public int Id { get; set; }
    public string UserId { get; set; }
    public string Name { get; set; }
    public string Information { get; set; }
    public Type Type { get; set; }

    [ForeignKey("UserId")]
    public virtual ApplicationUser User { get; set; }
}

Type是所有可能服务的enum

房间是一种特殊情况,因为它需要一些并非总是需要/需要的其他字段,例如地址和地理位置。出于这些原因,我为它创建了一个单独的表:

public class Room
{
    public int Id { get; set; }
    public int UserServiceId { get; set; }
    public string Street { get; set; }
    public string ZipCode { get; set; }
    public int HouseNumber { get; set; }
    public string City { get; set; }
    public DbGeography GeoLocation { get; set; }

    [ForeignKey("UserServiceId")]
    public virtual UserService UserService { get; set; }
}

过滤用户服务(可能是所有组合)时,我使用PredicateBuilder构建。

假设用户选择了Band和Room,但是当选择了房间时,用户还应该传递城市或邮政编码(或任何其他来获取地理位置)和距离以英里寻找房间。如何在2个表中构建谓词?

如果我这样做:

var userServices = PredicateBuilder.Create<UserService>(x => lstTypes.Contains(x.Type));

我不能对Room表中的GeoLocation字段做任何事情,因为UserService没有它。所以这不起作用:

userServices = userServices.And(x => x.GeoLocation.Distance(geo) < distance);

另外,由于我使用的Orderby().Skip().Take(),我需要将这些用户服务组合在一起。因此,如果我将它们分开并因此而两次进入数据库,这将会搞砸。

我正在考虑向Room添加导航属性UserService,但我不确定这可能会在短期和长期内发生什么。因为并不总是需要它。

1 个答案:

答案 0 :(得分:0)

现在你有办法,RoomUserService实际上有一对一的关系,因为它们有一个外键到那个表。

您可以保持原样,并将Rooms属性添加到UserService,在这种情况下,您必须查看是否x => x.Rooms.Any(r => r.GeoLocation.Distance(geo) < distance)。如果没有与服务相关联的空间,则.Any()显然会返回false。

但是,你让它听起来就像一个Room只是UserService之外的可选属性,在这种情况下你可能想让UserServiceId 成为其主键及其主键外键。那么你的谓词就是x => x.Room.GeoLocation.Distance(geo) < distance。奇怪的是,虽然C#会从此代码中抛出异常,但生成的SQL最终会传播空值,因此如果false结果为空,它应该有效x.Room