[MultiIndex] Resolving foreign keys

Hi there, beware I'm a new to Multiindex and haven't digested the whole capabilities of the library, yet. In my example I have two entities that are connected via a foreign key. In this case the key is type of an int. When retrieving the objects from a database I end up having two containers containing those objects. In the code below there are a customer_row and a order_row class. There is a one-to_many relationship between them. One customer can have several order but one order is can only one customer. So, my goal is to find an way to create order objects that are pointing to the correct row objects. So far, I don't really see how the MultiIndex lib can be of help for me. I have looked at the example six which I think came pretty close to my goal. So, taken this example, is it possible to use an key type instead of the car_manufacturer pointer? Please consider the following code: using namespace std; using namespace boost; using namespace boost::multi_index; struct primary {}; struct foreign {}; struct customer_row { int _id; string _name; customer_row( int id, const string& name ) : _id( id ), _name( name ) {} friend ostream& operator<<( ostream& os, const customer_row& c ) { os << c._id << " " << c._name << endl; return os; } }; typedef multi_index_container< customer_row, indexed_by< ordered_unique< tag< primary >, BOOST_MULTI_INDEX_MEMBER(customer_row,int,_id) >
customer_table;
struct order_row { int _id; int _customer_id; string _article; order_row( int id, int customer_id, const string& article ) : _id( id ), _customer_id( customer_id ), _article( article ) {} friend ostream& operator<<( ostream& os, const order_row& o ) { os << o._id << " " << o._customer_id << " " << o._article << endl; return os; } }; typedef multi_index_container< order_row, indexed_by< ordered_unique< tag< primary >, BOOST_MULTI_INDEX_MEMBER(order_row,int,_id) >, ordered_non_unique< tag< foreign >, BOOST_MULTI_INDEX_MEMBER(order_row,int,_customer_id) >
order_table;
struct order { const order_row* _order_row; const customer_row* _customer_row; }; int main() { customer_table ct; ct.insert( customer_row( 97, "Bon Jovi" )); ct.insert( customer_row( 98, "Billy Joel" )); ct.insert( customer_row( 99, "Morgan Freeman" )); order_table ot; ot.insert( order_row( 0, 97, "Book" )); ot.insert( order_row( 1, 97, "Car" )); ot.insert( order_row( 2, 97, "Dish Washer" )); order_table::iterator it = ot.get<primary>().begin(); order_table::iterator end = ot.get<primary>().end(); vector<order> orders; while( it != end ) { // find customer typedef customer_table::index<primary>::type customer_table_by_primary; customer_table_by_primary::iterator ic = ct.get<primary>().find( it->_customer_id ); order o; o._order_row = &( *it ); o._customer_row = &*ct.get<primary>().find( it->_customer_id ); orders.push_back( o ); ++it; } return 0; } Is there a more advanced way using the MultiIndex lib of combining two related objects so I can created my orders array? Or in different words can I structure my code more efficiently? Since this is a very simplified version it should be extensible to more entities with more than one foreign keys. Thanks ahead, Christian

----- Mensaje original -----
De: Christian Henning
Hi there, beware I'm a new to Multiindex and haven't digested the whole capabilities of the library, yet.
In my example I have two entities that are connected via a foreign key. In this case the key is type of an int. When retrieving the objects from a database I end up having two containers containing those objects. In the code below there are a customer_row and a order_row class. There is a one-to_many relationship between them. One customer can have several order but one order is can only one customer. So, my goal is to find an way to create order objects that are pointing to the correct row objects.
So far, I don't really see how the MultiIndex lib can be of help for me. I have looked at the example six which I think came pretty close to my goal. So, taken this example, is it possible to use an key type instead of the car_manufacturer pointer?
Your design looks basically correct, but you can have a tighter relationship between order_rows and their associated customer_rows as follows: struct order_row { int _id; customer_table::iterator _customer_it; string _article; int customer_id() const { return _customer_it->_id; } order_row( int id, customer_table::iterator customer_it, const string& article ) : _id( id ), _customer_it( customer_it ), _article( article ) {} friend ostream& operator<<( ostream& os, const order_row& o ) { os << o._id << " " << o.customer_id() << " " << o._article << endl; return os; } }; ... typedef multi_index_container< order_row, indexed_by< ordered_unique< tag< primary >, BOOST_MULTI_INDEX_MEMBER(order_row,int,_id) >, ordered_non_unique< tag< foreign >, BOOST_MULTI_INDEX_CONST_MEM_FUN(order_row,int,customer_id) > >
order_table;
... order_table ot; ot.insert( order_row( 0, ct.find(97), "Book" )); ot.insert( order_row( 1, ct.find(97), "Car" )); ot.insert( order_row( 2, ct.find(97), "Dish Washer" )); Having things arranged this way allows to go from a given order_row to the associated customer info faster (constant time) than in your original design (logarithmic lookup on _customer_id). Depending on your usage scenarios this can be worthwile. [...]
Is there a more advanced way using the MultiIndex lib of combining two related objects so I can created my orders array? Or in different words can I structure my code more efficiently?
With the design I propose, looks to me like there is no compelling need to define an order object and populate the orders vector: you can work directly with order_table just as easily, and as efficiently. Does this sound good to you, or is there some additional aspect I'm missing? Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

Thanks JOAQUIN, for your quick answer. Please see below my comments.
Your design looks basically correct, but you can have a tighter relationship between order_rows and their associated customer_rows as follows:
I don't think I can do that. All my row objects are coming from an ORM. Storing and retrieving an interator to/from a database table, of course, doesn't work. This way I still need the two containers. What I'm looking for is a way to combine the two containers into one of type "order". I don't know if this is possible, at all. What's your opinion? Thanks again, Christian

----- Mensaje original -----
De: Christian Henning
Thanks JOAQUIN, for your quick answer.
Oh, I happened to be in front of the computer, just like now :)
Please see below my comments.
Your design looks basically correct, but you can have a tighter relationship between order_rows and their associated customer_rows as follows:
I don't think I can do that. All my row objects are coming from an ORM. Storing and retrieving an interator to/from a database table, of course, doesn't work.
I don't know how much customization your ORM engine allows for, but can't you save/load order_rows using the _customer_id key and then internally convert to customer_rows (or any other class based on it) using customer_table::iterators?
This way I still need the two containers. What I'm looking for is a way to combine the two containers into one of type "order". I don't know if this is possible, at all. What's your opinion?
I don't see a way to store both the customer and order objects in one table, to begin with because they are different objects... Why do you need an order container, I mean, which modes of use do you envision that are not realizable witht wo containers, one for customers and the other for orders?
Thanks again, Christian
Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

----- Mensaje original -----
De: "JOAQUIN LOPEZ MU?Z"
----- Mensaje original ----- De: Christian Henning
Fecha: Miércoles, Abril 4, 2007 8:42 pm Asunto: Re: [Boost-users] [MultiIndex] Resolving foreign keys Para: boost-users@lists.boost.org Thanks JOAQUIN, for your quick answer.
Oh, I happened to be in front of the computer, just like now :)
Please see below my comments.
Your design looks basically correct, but you can have a tighter relationship between order_rows and their associated
customer_rows
as follows:
I don't think I can do that. All my row objects are coming from an ORM. Storing and retrieving an interator to/from a database table, of course, doesn't work.
I don't know how much customization your ORM engine allows for, but can't you save/load order_rows using the _customer_id key and then internally convert to customer_rows...
I meant "order_rows" here. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

Thanks Joaquin, for your help. Seems that I need more time for designing my project. I think I have basic understanding now when to use MultiIndex and when not to. Either way the lib rocks. Christian
participants (2)
-
"JOAQUIN LOPEZ MU?Z"
-
Christian Henning