核心数据 - 遵循Keypaths

时间:2010-07-07 00:59:44

标签: cocoa core-data

我是Core Data的新手,并且正在寻找设置查询的正确方法。

我的托管对象模型包括类Apartment,Lease,以及我称之为ApartmentLease的连接表。这看起来像:

/-----------------\      /-----------------\      /-----------------\
| Apartment       |      | ApartmentLease  |      | Lease           |
|-----------------|      |-----------------|      |-----------------|
| number          |      | startOn         |      | occupantName    |
|-----------------|      | endOn           |      | monthlyRate     |
| apartmentLeases |-\    |-----------------|      | occupantPhone   |
\-----------------/  \->>| apartment       |      |-----------------|
                         | lease           |<<----|apartmentLeases  |
                         \-----------------/      \-----------------/

所以我试图建模的是租约可以有很多公寓,租约中的每套公寓都有自己的开始和结束日期。

所以我的问题是:考虑到一系列日期,我如何查询公寓对象并获取在该日期范围内占用公寓的所有租约的数组?

感谢和抱歉我可怕的ASCII艺术!

伯特

2 个答案:

答案 0 :(得分:0)

不是查询Apartment实体,而是查询您的ApartmentLease实体。

[NSPredicate predicateWithFormat:@"startOn <= %@ && endOn >= %@", referenceDate, referenceDate];

然后,一旦拥有了ApartmentLease实体数组,您就可以通过以下方式检索公寓实体:

NSArray *apartments = [apartmentLeaseArray valueForKeyPath:@"@distinctUnionOfObjects.apartment"];

现在您有一系列符合搜索条件的公寓实体。

更新

如果您已经参考了公寓,那么只需获得一套公寓租约,并根据包含相关日期的租约过滤。如果您已经拥有公寓,则没有理由通过NSFetchRequest。将Core Data视为对象图,而不是数据库。所有关系都已预先填充,您无需获取它们,只需遍历对象图。

答案 1 :(得分:0)

Marcus S. Zarra对您的实际问题的回答是正确的,但您可能想重新考虑您的数据模型。你肯定不想试图用关系数据库来思考核心数据。

在良好的数据模型中,每个实体都应该模拟真实世界的对象,事件或条件。在这种情况下,您的ApartmentLease实体实际上并不代表任何真实的东西,它只是让代码工作。那是一面红旗。

您真的只需要公寓和租赁实体。租赁实体应准确地模拟真实的租赁协议。由于实际租约具有自己的开始和结束日期,因此该数据应存储在租赁实体的属性中,而不是存储在另一个实体的属性中。

你真的只需要:

Apartment {
    number:int;
    leases<--(optional,cascade)-->>lease.apartment
} 

Lease{
    startOn:date;
    endOn:date;
    occupantName:string;
    monthlyRate:float;
    occupantPhone:string
    apartment<<--(required,nullify)->Apartment.leases
}

然后您只需使用Marcus的谓词并将其应用于Apartment.leases以查找日期范围内的租约。

NSManageObject *anApartment= // which every apartment whose leases you want to examine
NSPredicate *rangePred=[NSPredicate predicateWithFormat:@"startOn <= %@ && endOn >= %@", startReferenceDate, endReferenceDate];
NSSet *leases=[anAparment valueForkey:@"leases"];
NSSet *leasesInDateRange=[leases filteredSetUsingPredicate:rangePred];

请记住,这些实体在运行时实际上是对象,因此如果您创建客户NSManagedObject子类,则可以在其中嵌入逻辑。例如,您可以为租用实体创建瞬态bool属性:inForce,expired。然后有这样的自定义getter:

-(BOOL) inForce{
    BOOL isInForce;
    NSDate *today=[NSDate now];
    if (self.starOn<today<self.endOn){
        isInForce=YES;
    }else{
        isInForce=NO;
    }
    return isInForce;
}

然后,您可以使用谓词来获取所有租约,这些租约是在forForce,expired或pending,或者您可以获取所有租约属于其中一种状态的公寓。