Reputation: 6384
I'm trying to write my first Cocoa app, and Core Data is making it difficult to model my data objects. I have two entities that I want to manipulate: Account
and Transaction
. Account
has a human-readable name and that's about it. Transaction
stores a monetary value, and references to two accounts called debitAccount
and creditAccount
(I'm working on a double-book accounting app).
I want to be able to find all the Transactions
for a given Account
, whether they use debitAccount
or creditAccount
. How can I do this? Is there a way to do it that will work easily with Cocoa UI binding?
Upvotes: 3
Views: 2935
Reputation: 6384
The solution that worked best (and made the most sense) to me was to create a subclass of NSManagedObject
to use as my Account
entity:
@interface Account : NSManagedObject {
}
-(NSArray*)getTransactions;
@end
I have the actual lookup logic inside -getTransactions
, which wasn't too hard to do by hand. This is working out well so far, especially because the method name conforms to KVO.
To make Core Data return Account
s instead of NSManagedObject
s, I had to change the entity's "Class" property in Xcode's data modeling tool.
Upvotes: 0
Reputation: 26859
If I understand you correctly, you want Transaction to be related to Account via two relationships: debitAccount
and creditAccount
, yes? And you're wondering about creating inverse relationships.
In short, a relationship can only be the inverse of one other relationship. So you won't be able to create a relationship called, say, transactions
that is the inverse of both debitAccount
and creditAccount
. Instead, you'll have to create two relationships, like debitTransactions
and creditTransactions
(I'm sure you'll think of more appropriate names for these...)
Now, since relationships are modeled as sets (specifically, NSSet
s), you can union the creditTransactions
and debitTransactions
relationships for a particular Account to get all transactions that account is involved with.
A (possibly better) alternative would be to introduce an intermediate entity, with a name like TransactionAccount
that has a to-one relationship to both Account
and Transaction
as well as an attribute, like accountRole
that identifies the account as being the debit or credit account relative to that particular transaction. You'd create inverse to-many relationships on both Transaction
and Account
with a name like transactionAccounts
. That way, you could write something like this:
[account valueForKeyPath:@"transactionAccounts.transaction"]
to get all the transactions for a particular account. You could use an NSPredicate
to filter the set to only transactions where the account was the debit/credit account.
Upvotes: 4