Loading Full tree of New Object

9 posts, 0 answers
  1. devoas
    devoas avatar
    69 posts
    Member since:
    Dec 2009

    Posted 09 Dec 2011 Link to this post

    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.
  2. devoas
    devoas avatar
    69 posts
    Member since:
    Dec 2009

    Posted 13 Dec 2011 Link to this post

    Hi, 

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

    Thanks,
    devoas.
  3. DevCraft banner
  4. Ivailo
    Admin
    Ivailo avatar
    318 posts

    Posted 14 Dec 2011 Link to this post

    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!

  5. devoas
    devoas avatar
    69 posts
    Member since:
    Dec 2009

    Posted 14 Dec 2011 Link to this post

    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.

  6. TSE
    TSE avatar
    381 posts
    Member since:
    Sep 2008

    Posted 15 Dec 2011 Link to this post

    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


  7. devoas
    devoas avatar
    69 posts
    Member since:
    Dec 2009

    Posted 16 Dec 2011 Link to this post

    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.






  8. TSE
    TSE avatar
    381 posts
    Member since:
    Sep 2008

    Posted 16 Dec 2011 Link to this post

    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
  9. devoas
    devoas avatar
    69 posts
    Member since:
    Dec 2009

    Posted 16 Dec 2011 Link to this post

    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.
  10. TSE
    TSE avatar
    381 posts
    Member since:
    Sep 2008

    Posted 19 Dec 2011 Link to this post

    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
Back to Top
DevCraft banner