我遇到了一个复杂的问题,但对它的解释更为复杂(我认为)。但无论如何我都会试一试,如果不清楚的话,请让我详细说明。
我有一张名为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
,但我不确定这可能会在短期和长期内发生什么。因为并不总是需要它。
答案 0 :(得分:0)
现在你有办法,Room
与UserService
实际上有一对一的关系,因为它们有一个外键到那个表。
您可以保持原样,并将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
。