I will use the standard example of Invoice and invoiceLineItems. So I have a single repository for the invoices because the invoice is the aggregate root. Creating a whole invoice and deleting an invoice is pretty easy. What about updating an invoice?
Maybe I shouldn't be thinking so "low level" but I can't imagine a nice way to handle this. Here is my pseudo code for this operation
public void Update(Invoice inv)
{
var dbVersion = GetInvoice(id);
foreach(var lineItem in inv.LineItems)
{
if (lineItem not in dbVersion)
{
InsertLineItem(lineItem);
}
else
{
UpdateLineItem(lineItem);
}
}
foreach(var lineItem in dbVersion)
{
if (lineItem not in inv)
{
DeleteLineItem(lineItem);
}
}
}
I am imagining the queries this thing needs to produce and it seems very inefficient.
Select statements to re materialize the whole invoice.
Update statement for the whole invoice (regardless if anything on the invoice changed)
Insert statement for each line item that is new
Update statement for each line item that is already there (regardless if anything changed)
Delete statement for each line item that is missing
Of course you wouldn't have to generate an update statement for the whole invoice and for the InvoiceLineItem but that would require you to check all the properties in each.
If you however went the IvoiceLineItemRepo you would only update when a user performed an action that would necessitate the update. So if the user updated just a line then there would only be a single update and for that line item and you wouldn't have to check for changes you could assume that it had changed.
Is there a nicer way of handling the updates?
You can first delete LineItem collection and then insert new collection like all-delete-orphan in hibernate.
deleteAllLineItemsByInvoiceId(Long id);
insertAllLineItems(List<LineItem> lineItems);
Related
I've been adding records to a dynamic module via the API and in the process during my experimentation I added a bunch of records that weren't associated correctly with any valid parent record.
I've checked and so far I can see that Sitefinity stores data about these records in a number of tables:
mydynamiccontenttype_table
sf_dynamic_content
sf_dynmc_cntnt_sf_lnguage_data
sf_dynmc_cntent_sf_permissions
I would like to clean up the database by deleting these records but I want to make sure I don't create more problems in the process.
Anyone know if there are more references to these dynamic content type records or a process to safely delete them?
There are probably other tables, so your safest option would be to delete the items using the Sitefinity API.
Just get the masterId of the item and use a code like this:
public static void DeleteDataItemOfType(this DynamicModuleManager manager, string type, Guid Id)
{
Type resolvedType = TypeResolutionService.ResolveType(type);
using (var region = new ElevatedModeRegion(manager))
{
manager.DeleteDataItem(resolvedType, Id);
manager.SaveChanges();
}
}
I'm developing a simple module that hooks to actionUpdateQuantity hook. So, every time the stock of a product is updated I must update the stock of other products.
But, to update the stock I call stockAvailable object, which trigger the actionUpdateQuantity hook. So, I have a endless loop.
Then I tried to manually update the stock directly on the database using SQL, but this have the problem that other modules don't "see" the stock updates. So, modules like MailAlert, ebay or Amazon don't update stock correctly.
I'm a bit stuck here.
How can I update the stock without enter a loop ?
Thanks!
I had similar issue before and think this is not best way but worked for me. Idea is to add class variable in your module:
protected $isSaved = false;
then in hookActionProductUpdate function first check that variable and later after you done saving data change its value
public function hookActionProductUpdate($params)
{
if ($this->isSaved)
return null;
...
$this->isSaved = true;
}
Another way to do this is, in your module when you submit new quantity make sure you also submit product id and attribute id. Then in your hook you can do a check.
public function hookActionUpdateQuantity($params)
{
if ((int)Tools::getValue('id_product') != $params['id_product']
|| (int)Tools::getValue('id_attribute') != $params['id_product_attribute']) {
return false;
}
// do your stuff
}
Everytime the hook actionUpdateQuantity triggers you have a $params array of product whose quantity is being updated.
$params['id_product'] // id of a product being updated
$params['id_product_attribute'] // id of product combination being updated
$params['quantity'] // quantity being set to product
This way your hook will run only once when you are updating quantity of a product from your module (form?). As you update other products quantity they will also trigger this hook but since the data in $params array is different than your POST'ed data, the hook method will return false.
I have an entity with a sequence attribute, which is an integer from 1-N for N members of the list. They are polyline points.
I want to be able to insert into the list at a given sequence point, and increment all the items at that point or beyond in the sequence to make room for the new item, and likewise if I delete then decrement everything above so we still have nice sequence ordering with no missing numbers.
There is a REST interface in this of course, but I dont want to hack about with that, I just want sequelize to magically manage this sequence number.
I am assuming I need to get hold of some "before insert" and "after delete" hooks in sequelize and issue some SQL to make this happen. Is that assumption correct or is there some cooler way of doing it.
I havent tested this, but this appears to be the solution, which is barely worth comment.
I know the modelName, and name==the attribute name,
options.hooks={
beforeInsert: function(record, options) {
return self.models[modelName].incrementAfter(name,record[name]);
},
afterDelete: function(record, options) {
return self.models[modelName].decrementAfter(name,record[name]);
}
}
and then added to my extended model prototype I have
incrementAfter:function(field,position){
return this.sequelize.query("UPDATE "+this.tableName+" SET "+field+" = "+field+"+1 WHERE "+field +" >= "+position);
},
decrementAfter:function(field,position){
return this.sequelize.query("UPDATE "+this.tableName+" SET "+field+" = "+field+"-1 WHERE "+field +" >= "+position);
},
I want to add property to existing document (using clues form http://ravendb.net/docs/client-api/partial-document-updates). But before adding want to check if that property already exists in my database.
Is any "special,proper ravendB way" to achieve that?
Or just load document and check if this property is null or not?
You can do this using a set based database update. You carry it out using JavaScript, which fortunately is similar enough to C# to make it a pretty painless process for anybody. Here's an example of an update I just ran.
Note: You have to be very careful doing this because errors in your script may have undesired results. For example, in my code CustomId contains something like '1234-1'. In my first iteration of writing the script, I had:
product.Order = parseInt(product.CustomId.split('-'));
Notice I forgot the indexer after split. The result? An error, right? Nope. Order had the value of 12341! It is supposed to be 1. So be careful and be sure to test it thoroughly.
Example:
Job has a Products property (a collection) and I'm adding the new Order property to existing Products.
ravenSession.Advanced.DocumentStore.DatabaseCommands.UpdateByIndex(
"Raven/DocumentsByEntityName",
new IndexQuery { Query = "Tag:Jobs" },
new ScriptedPatchRequest { Script =
#"
this.Products.Map(function(product) {
if(product.Order == undefined)
{
product.Order = parseInt(product.CustomId.split('-')[1]);
}
return product;
});"
}
);
I referenced these pages to build it:
set based ops
partial document updates (in particular the Map section)
How does one make Zend Db cascade delete multiple levels of the hierarchy? For example:
dealers -> products -> attributes
deleting one dealer should go all the way down to attributes, and now it doesn't :(
Any thoughts?
On row of the Zend_Table_Abstract within the function _cascadeDelete a row is constructed like this:
$rowsAffected += $this->delete($where);
It should instead be constructed as something like this:
$toDelete = $this->fetchAll($where);
foreach($toDelete as $row) {
$rowsAffected += $row->delete();
}
More info here.
It's worked for me in one cause but need to test more.