帮助CoreData查询 [英] Help with CoreData Query

查看:108
本文介绍了帮助CoreData查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找在CoreData中编写一些基本查询的方法,文档中没有示例。以下是我的查询:


  1. 我有一个费用对象,它有一个开支字段。

  2. 费用可以链接到ExpenseCategory对象。

  3. 费用类别可以仅定义费用的类别(例如Food),也可以具有单位费率(例如里程)。如果它只是名称,则费用值是费用对象中的开支,或者是费用类别中的费用。* / $>
  4. 由于费用到类别链接是可选的,最终费用将基于

  5. $ b

    因此,用于计算总费用的SQL查询将是:

      select 
    TOTAL(e.amount * IFNULL(c.rate,1))
    来自EXPENSE e
    LEFT OUTER join CATEGORY c on
    e.category = c.id

    如何做在CoreData中?

    解决方案

    一个更简单的解决方案可能是在你的Expense类中实现另一个方法, / p>

    例如

       - (NSDecimalNumber *)calculatedExpenseAmount {

    NSDecimalNumber * actualAmount = self.expenseAmount;

    //伪代码开始
    if(self.expenseCategory!= nil){
    actualAmount = self.expenseAmount * self.expenseCategory.unitRate;
    }

    return actualAmount;
    }






    到我以前的答案。



    如果你想避免拉入每个managed对象,你可以使用NSDictionary-result查询来取出expenseAmount和expenseCategory.unitRate的值。

       - (NSDecimalNumber *)totalExpenses 
    {
    //获取任何相关类别的所有费用金额和单位费率。

    NSFetchRequest * request = ...;
    [request setManagedObjectContext:< ...>];
    [request setEntity:< ExpenseAccountDescription>];
    [request setResultType:NSDictionaryResultType];
    NSArray * props = [NSArray arrayWithObjects:@expenseAmount,@category.unitRate,nil];
    [request setPropertiesToFetch:props];

    NSArray * amount = [request executeRequest:...]
    // amount是一个字典数组,每个字段都包含所需的属性值。

    //循环并求和各个金额

    NSDecimal * total = [[NSDecimalNumber zero] decimalNumber];
    NSAutoreleasePool * pool = nil; // contains the mess

    NSCalculationError err = NSCalculationNoError;

    for(NSDictionary * result in quantities)
    {
    pool = [NSAutoreleasePool new];

    NSDecimal newTotal = [[NSDecimalNumber zero] decimalNumber];
    NSDecimalNumber * expenseAmount = [result valueForKeyPath:@expenseAmount];
    NSDecimalNumber * unitRate = [result valueForKeyPath:@category.unitRate];

    if(unitRate!= nil){
    //进行单位速率乘法并累加结果总和

    NSDecimal calculated = [[NSDecimalNumber zero] decimalNumber];
    err = NSDecimalMultiply(& calculated,[expenseAmount decimalNumber],[unitRate decimalNumber],NSRoundBankers);
    if(err == NSCalculationNoError){
    err = NSDecimalAdd(& newTotal,total,calculated,NSRoundBankers);
    }
    }
    else {
    //只是将结果累加到总计

    err = NSDecimalAdd(& newTotal,total,[expenseAmount decimalNumber ],NSRoundBankers);
    }

    //保留新的合计
    NSDecimalCopy(& total,newTotal);

    [pool drain];
    }

    return [NSDecimalNumber decimalNumberWithDecimal:total];
    }

    如果您有10000个费用条目,则此提取和计算可能需要少于1MB的RAM。仪器将是你的朋友测量。


    I am looking for ways to write some basic queries in CoreData and there are not examples in the documentation. Following is my query:

    1. I have an Expense object and it has an expenseAmount field.
    2. Expense can be linked to an ExpenseCategory object.
    3. ExpenseCategory may just define the category for the expense (for eg Food) or it may have a unit rate (for eg Mileage). If it is just name, the expense value is the expenseAmount in Expense object else it is expenseAmount * unitRate in ExpenseCategory.
    4. Since Expense to Category link is optional, the final expense would be based on presence/absence of Category and the unit rate.

    So a SQL query to calculate total expenses would be :

    select
        TOTAL(e.amount * IFNULL(c.rate, 1))
    from EXPENSE e
    LEFT OUTER join CATEGORY c on
        e.category = c.id
    

    How can this be done in CoreData?

    解决方案

    A simpler solution might be to implement another method on your Expense class that gives you the appropriately calculated amount.

    E.g.

    - (NSDecimalNumber *) calculatedExpenseAmount {
    
      NSDecimalNumber *actualAmount = self.expenseAmount;
    
      // Pseudo-code begins
      if (self.expenseCategory != nil) {
        actualAmount = self.expenseAmount * self.expenseCategory.unitRate;
      }
    
      return actualAmount;
    }
    


    I'm adding on to my previous answer.

    If you want to avoid pulling in every managed object, you could use the NSDictionary-result query to just pull out the expenseAmount and expenseCategory.unitRate values.

    - (NSDecimalNumber *) totalExpenses
    {
        // Fetch all of the expense amounts and unit rate of any related category.
    
        NSFetchRequest *request = ...;
        [request setManagedObjectContext:<...>];
        [request setEntity:<ExpenseAccountDescription>];
        [request setResultType:NSDictionaryResultType];
        NSArray *props = [NSArray arrayWithObjects:@"expenseAmount", @"category.unitRate", nil];
        [request setPropertiesToFetch:props];
    
        NSArray *amounts = [request executeRequest:...];
        // amounts is an array of dictionaries, each hold the desired property values.
    
        // Loop and sum the individual amounts
    
        NSDecimal *total = [[NSDecimalNumber zero] decimalNumber];
        NSAutoreleasePool *pool = nil; // contain the mess
    
        NSCalculationError err = NSCalculationNoError;
    
        for (NSDictionary *result in amounts) 
        {
            pool = [NSAutoreleasePool new];
    
            NSDecimal newTotal = [[NSDecimalNumber zero] decimalNumber];
            NSDecimalNumber *expenseAmount = [result valueForKeyPath:@"expenseAmount"];
            NSDecimalNumber *unitRate = [result valueForKeyPath:@"category.unitRate"];
    
            if (unitRate != nil) {
                // do the unit rate multiplication and accumulate the result in the total
    
                NSDecimal calculated = [[NSDecimalNumber zero] decimalNumber];
                err = NSDecimalMultiply (&calculated, [expenseAmount decimalNumber], [unitRate decimalNumber], NSRoundBankers);
                if (err == NSCalculationNoError) {
                    err = NSDecimalAdd (&newTotal, total, calculated, NSRoundBankers);
                }
            }
            else {
                // just accumulate the result in the total
    
                err = NSDecimalAdd (&newTotal, total, [expenseAmount decimalNumber], NSRoundBankers);
            }
    
            // Keep the new total
            NSDecimalCopy(&total, newTotal);
    
            [pool drain];
        }
    
        return [NSDecimalNumber decimalNumberWithDecimal:total];
    }
    

    If you have 10000 expense entries, this fetch and calculation might take less than 1MB of RAM. Instruments would be your friend in measuring that.

    这篇关于帮助CoreData查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆