Developer forum

Forum » Development » Command Timeout for LoadPricesOnProducts

Command Timeout for LoadPricesOnProducts

Tom Kamphuis
Reply

Hi guys,

For a customer we once build a webservice which imported all products to the DW CMS. This went all very well and there where no real issues importing the products. The database grew and grew and one day we started encountering timeout exceptions when importing the products. First it was a onetimer a week, nowadays it's everyday so I started investigating what caused the problems.

In our application we load all products in cache using this statement: Product.GetProductBySql("SELECT * FROM [dbo].[EcomProducts] WHERE ProductActive = 1", false); Somewhere in code DW calls the Load method on ProductCollection, which calls LoadPricesOnProducts on the Price class. At this point we have a big set of Product items (22000+) which DW uses to calculate the Prices for products. DW creates the following SQL query based on the products: SELECT EcomPrices.* FROM EcomPrices WHERE (PriceUserCustomerNumber='' OR PriceUserCustomerNumber IS NULL) AND PriceProductID IN(  [ALL 22000+ PRODUCT ID's as strings]  ) ORDER BY EcomPrices.PriceProductID

When running this query directly in SQL Management studio it takes around three minutes to finish. De DataReader object which is created by the LoadPricesOnProduct method uses a IDbCommand object with a default command timeout of 30 seconds, which is less than the 180 secounds I need. I can't change this timeout property myself because it's all DW code. In the end the application throws a Command Timeout error and fails to import the products. 

I understand that my initial query for products could be better, but if I have bigger sets of products this would always be a problem, right? Or is there a better way of retrieving Products and ProductCollections? This is the code from our application which is executed before the error occurs:

public override void BeforeExecute()
{
    _groupsCache = Group.GetAllGroups();
    _productCache = Product.GetProductBySql("SELECT * FROM [dbo].[EcomProducts]"false);
    _productsToSave = new ProductCollection();
}

Cheers,
Tom


Replies

 
Imar Spaanjaars Dynamicweb Employee
Imar Spaanjaars
Reply

What about paging? Loading 22,000 poducts seems like a lot to me. Batching this into sets of a few hundred or thousand seems like a better solution.

You could also look into the Data Intgeration Framework, although that would require a rewrite of your code.

Imar

 
Tom Kamphuis
Reply

Yeah well, this code is only there to import products. So I actually need the whole batch in order to be able to tell which products need to be active and which need to be inactive. I'll have to make a subselection and probably it would help to get a subselection or fill the collection over multiple calls to the database. Maybe selecting only the active products would help (6000 versus 22000) but that would be kind of a temporary fix.

The command timeout behaviour in this specific part of the code is expected behaviour? Or shouldn't we use this specific part of the API?

 
Nicolai Høeg Pedersen
Reply

Hi Tom

You can do something like this

col  = New productcollection
Using datareader(select * from ecomproducts)
do while datareader.read()
var p = new product
col.add(p.fill(datareader)
end while
end using

 

You must be logged in to post in the forum