This is a migrated thread and some comments may be shown as answers.

Loading Full tree of New Object

8 Answers 94 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
devoas
Top achievements
Rank 1
devoas asked on 09 Dec 2011, 04:35 PM
Hi,

Please advise if there is any way to retrieve the complete object tree of newly created object. It is very much required in validation in Business logic.  

Suppose I have an object SalesMaster having Child SalesDetail....   When creating new Invoice, we add different products sold under an document in SalesDetail. Now in validation phase we need to check if products added in collection are valid according to business logic or not. This requires to fetch product object each element under sales detail   from database base separately  because SalesDetail.Product reference object is still null. Is there any way that I can get all Products object filled under SalesDetail...

Thanks
devoas.

8 Answers, 1 is accepted

Sort by
0
devoas
Top achievements
Rank 1
answered on 13 Dec 2011, 06:26 PM
Hi, 

I will be really thankful if any telerik expert can reply my question...

Thanks,
devoas.
0
Ivailo
Telerik team
answered on 14 Dec 2011, 10:53 AM
Hello Devoas,

You can achieve what you want by using the Fetch Plans functionality OpenAccess ORM is offering. Find here the guide for defining the proper fetch plan for your needs. 

Do not hesitate to contact us if you need further assistance or you have other questions.


Kind regards,
Ivailo
the Telerik team

Q3’11 of Telerik OpenAccess ORM is available for download. Register for the What's New in Data Tools webinar to see what's new and get a chance to WIN A FREE LICENSE!

0
devoas
Top achievements
Rank 1
answered on 14 Dec 2011, 04:31 PM
Hi 

Thanks for your reply but seems that I could not explain my issue properly. Actualy I am creating New Records/objects using ORM Classic API. Please refer following code for the objects in transient state required reference property to be filled.

// Order Master Object Created ////////
Order newOrder = new Order();
newOrder.OrderDate = DateTime.Now;
 
OrderDetail newOrderDetail;
 
// Order Detail First Item  Object Created ////////
newOrderDetail = new OrderDetail();
newOrderDetail.ProductId = 1;
newOrderDetail.Qnty = 5;
 
newOrder.OrderDetails.Add(newOrderDetail);
 
// Order Detail Second Item  Object Created ////////
newOrderDetail = new OrderDetail();
newOrderDetail.ProductId = 2;
newOrderDetail.Qnty = 10;
 
newOrder.OrderDetails.Add(newOrderDetail);



We have Product as reference property  in  OrderDetail .....  and Product have property  BalanceStock . 
In our BO before saving, we need to verify all Orders Products are having Balance Stock...

Since this OrderDetail object is in transient state so we don't get Product Object filled under Orderdetail... this is null at this stage. so we cannot check Orderdetail.Product.BalanceStock > 1 rather we have to query Product table each time while iterating on Order.OrderDetails.

Is there any way I can get Order.OrderDetails .... (all child object's reference property Product) filled in one go/query within transient state.

Thanks,
Devoas.

0
IT-Als
Top achievements
Rank 1
answered on 15 Dec 2011, 07:41 AM
Hi Devoas,

Sorry for interfering your thread.

"Normally" when you work with ORMs you work with objects. So instead of assigning Ids, like the ProductId property (I guess it maps to the same table column as the Product property is mapped to), you load and assign the Product property only. Doing so you would have the Product instance at hand and would be able to check the stock at that time.

You choose another (or both ways).. having both the reference to Product and the Id of the Product instance in two different properties, which is perfectly legal. Out of curiosity: What are your motivation of doing so?

The only way I could think of to load all Product instances in one go is to construct a query (LINQ or OQL does not matter) that loads all Product instances referenced by the OrderDetail. For example (pseudo code):

// Collect all Ids of product references by OrderDetails
IList<int> productIds = new List<int>();
foreach (OrderDetail detail in order.OrderDetails)
  productIds.Add(detail.ProductId);

// Once collected construct a query to get all Product instances with Ids collected
IQuery query = .....

IList<Product> productsReferenced = query.Execute().ToList();

// Iterate the productsReferenced list to check/validate the stock
foreach (Product product in productsReferenced)
{
   // Code to check the stock, eventually throw a ValidationException if we are out of stock
   if (....)
      throw ValidationException("Product: " + product.Id + " is out of stock");
}

Alternatively: I guess you should update the stock count once an order is placed. So while doing so you load the object with the property representing the stock count (for example the Product.StockCount property). So you actually can check against the stock count at update time (of the stock count) instead, because you will need to load the object under all circumstances at that time to do the update. Do you get the idea?
All the above is written with the minimal knowledge I have of your model. So, if the structure of your model, doesn't allow to do stuff like the above... I am sorry, bear with me.

Regards

Henrik


0
devoas
Top achievements
Rank 1
answered on 16 Dec 2011, 12:34 PM
Dear Henrik,

Thanks alot for your time and detail reply. According to my give scenario, we have ProductId field in OrderDetail Table.   When we create classes through reverse mapping it create two properties in OrderDetail Class:  ProductId  (table - column of orderdetail) and Product (reference field of product Table which represent Product object).  Normally while creating new records, we select Products in Form->Grid and while selecting products, we store productId in Grid. On Save, we create OrderMaster and OrderDetail Object, filled from  grid and we  set the OrderDetail.ProductId from grid column.  So in this way my OrderMaster & OrderDetail Object get ready for Saving. Normally at this stage we does not require Product (reference object) data. Except for the case when it is required for Validation in BO...  Our product table already have ClosingStock field which is updated thru trigger on saving of OrderDetails. But before saving, I need validation to check if ClosingStock > CurrentOrderQnty to allow saving.

One Ordermaster (Order) record can  have 10-15 Orderdetail (lineitmes) objects. So I was trying to figure out if I can iterate on OrderDetail object and get Product Object filled in transient state to have same logic for Add/Edit in BO.... because  when I edit any record - load from database, and change some quantity, I can easily get orderdetail.Product.ClosingStock...  

Now another situation, when any orderdetail(lineitem) added in  Record Edit Mode in existing salesmaster object.... so I have to handle it differently.....    Is there any better way that ORM can fill the orderdetail -> Product Object of all Orderdetails(LineItems) under OrderMaster irrespective if any record is in persistent state or transient state....  so that I can easy iterate 

foreach (OrderDetail detail in order.OrderDetails)
detail.Product.ClosingStock  ...... (checking)


Hope I explained my issue clearly so that experts like you can guide and advise appropriate way to handle this...

thanks,
devoas.






0
IT-Als
Top achievements
Rank 1
answered on 16 Dec 2011, 01:14 PM
Hi Devoas,

Yeah I understand you perfectly. You want the Product property to be resolved in transient state by the ProductId property you set. So when you navigate the orderDetail.Product property OA will go and get the correct Product instance.
Problem is.. this is the way it works when the object is retrieved from the database again (once stored). Also called lazy loading. But in effect you want lazy loading to work on transient instances, too... I am almost sure this is not possible, with doing some code that actually loads the missing instances based on their Id.
No matter how you do it or where you place it, you will end up doing the same stuff - namely getting the Product instance by its registered (ProductId property) id.

So you could do it this way:

ResolveReferencesForValidation(Order order)

This method will take your instance.... for example the Order iterate the orderDetails instances and load the Product reference by its Id.
After that you would call me Validate(Order order) method that actually does the validation. Another option could be to clash those two methods into one.

/Henrik
0
devoas
Top achievements
Rank 1
answered on 16 Dec 2011, 03:28 PM
Hi Henrik,

Thanks again for your quick reply.  As you suggested to create some method ResolveReferencesForValidation(Order order) 
and it will query several time to database in this method to fetch Product Object and set against each of  detail.Product  which we are already doing. 

Sometime  there are 100 products then it will have 100 round trips to the server. Where as lazy load that ORM do is some smart way which reduce the round trip....  

Please advise if you think there can be any better way...

Thanks
devoas.
0
IT-Als
Top achievements
Rank 1
answered on 19 Dec 2011, 08:54 AM
Hi Devoas,

The only other way I can think is to contruct some kind of query (LINQ, SQL or OQL) that takes the full list of Ids to find product instances for, so you will only hit the database once.

In SQL it could be achieved by using a "where product.id in (n1, n2, n3, n4....nx)

Not very efficient as this will probably resolve to multiple ORs in the database query engine, but you will only hit the database once.

Regards

Henrik
Tags
General Discussions
Asked by
devoas
Top achievements
Rank 1
Answers by
devoas
Top achievements
Rank 1
Ivailo
Telerik team
IT-Als
Top achievements
Rank 1
Share this question
or