Symfony2 and Doctrine: how to make an atomic operation? - symfony

Imagine this scenario:
I have an array of ids for some entities that have to be deleted from database (i.e. a couple of externals keys that identifies a record into a third table) and an array of ids for some entities that have to be updated/inserted (based on some criteria that, in this moment, doesn't matters).
What can I do for delete those entities ?
Load them from db (repository way)
Call delete() on the obtained objects
Call flush() onto my entity manager
In that scenario I can make all my operation atomical as I can update/insert other records before call flush().
But why have I to load from db some records just for delete them? So I wrote my personal DQL query (into repo) and call it.
The problem is that if I call that function into my repo, this operation is done immediatly and so my "atomicity" can't be guaranteed.
So, how can I "jump" over this obstacle by following the second "delete-option" ?

By using flush() you're making Doctrine to start transactions implicitly. It is also possible to use transactions explicitly and that approach should solve your problem.

Related

How to update single property of multiple entities in specific kind of datastore?

I want to update one property of each entity present in one particular kind of my datastore. In traditional sql, we do something like this as -
update <tablename> set <property> = <value>; {where clause is optional}
Now, how can I do same thing for datastore using golang code?
In Datastore you can't perform an update like that without retrieving the entities. You have to pull all entities in that kind, update the property on each, and re-upsert the now updated entities (preferably in a batch).
Go Datastore Queries: https://cloud.google.com/datastore/docs/concepts/queries#datastore-datastore-basic-query-go
Go Update Entities: https://cloud.google.com/datastore/docs/concepts/entities#datastore-datastore-update-go
Go Batch Upsert: https://cloud.google.com/datastore/docs/concepts/entities#datastore-datastore-batch-upsert-go

Doctrine migrations and data transformation

I use Doctrine's Migrations in my symfony 2 project to safely migrate my database. Most of the times it's all about adding columns, but sometimes I split columns (because of normalization) or I change releationships (one to one -> one to many).
The creation itself is simple. But deleting or renaming the old column/property is not. This can and may only happen if the data is transformed from the old format to the new one.
Example:
Current situation: Task entity with one tag
Future situation: Task entity with one to many Tags
I tried the preUp/postUp functions in the migration script.
Pseudo-code:
Fetch Tasks
Foreach Tasks as Task
$tag = new Tag();
$tag->setName($task->getTag());
persist
$task->setNewtag($tag);
persist
flush
In the second migration script I can safely delete the old Tag column and rename Newtag to Tag.
Problem:
When I --dry-run the script, the SQL commands are not executed (ofcourse) but the 'transformation' scripts are, whith an error as result because the columns does not exist.
How can I overcome this error? Can I intercept the result of the SQL-script and only execute the transformation if SQL result = true?

Updating multiple rows from a list in entity framework

I fetch a list of rows (Id,field1,f2...) and do some computation and store the result in a IList.
I want to now update all the values in this list to a table T. I am using entity framework and this needs to be a transaction.
Will it be fine if I open a transactionscope and update using a stored proc or is thr a efficient way to push multiple updates once ?
SaveChanges method of ObjectContext is a gateway to persist all changes made to entities to the database. When you call ObjectContext.SaveChanges(), it performs insert, update or delete operation on the database based on EntityState of the entities.
ObjectContext.SaveChanges();
Hope this may help you.

Efficient way to load lists of objects from database to instantiate a single object

My situation
I have a c# object which contains some lists. One of these lists are for example a list of tags, which is a list of c# "SystemTag"-objects. I want to instantiate this object the most efficient way.
In my database structure, I have the following tables:
dbObject - the table which contains some basic information about my c# object
dbTags - a list of all available tabs
dbTagConnections - a list which has 2 fields: TagID and ObjectID (to make sure an object can have several tags)
(I have several other similar types of data)
This is how I do it now...
Retrieve my object from the DB using an ID
Send the DB object to a "Object factory" pattern, which then realise we have to get the tags (and other lists). Then it sends a call to the DAL layer using the ID of our C# object
The DAL layer retrieves the data from the DB
These data are send to a "TagFactory" pattern which converts to tags
We are back to the Object Factory
This is really inefficient and we have many calls to the database. This especially gives problems as I have 4+ types of lists.
What have I tried?
I am not really good at SQL, but I've tried the following query:
SELECT * FROM dbObject p
LEFT JOIN dbTagConnection c on p.Id= c.PointId
LEFT JOIN dbTags t on c.TagId = t.dbTagId
WHERE ....
However, this retreives as many objects as there are tagconnections - so I don't see joins as a good way to do this.
Other info...
Using .NET Framework 4.0
Using LINQ to SQL (BLL and DAL layer with Factory patterns in the BLL to convert from DAL objects)
...
So - how do I solve this as efficient as possible? :-) Thanks!
At first sight I don't see your current way of work as "inefficient" (with the information provided). I would replace the code:
SELECT * FROM dbObject p
LEFT JOIN dbTagConnection c on p.Id= c.PointId
LEFT JOIN dbTags t on c.TagId = t.dbTagId
WHERE ...
by two calls to the DALs methods, first to retrieve the object main data (1) and one after that to get, only, the data of the tags related (2) so that your factory can fill-up the object's tags list:
(1)
SELECT * FROM dbObject WHERE Id=#objectId
(2)
SELECT t.* FROM dbTags t
INNER JOIN dbTag Connection c ON c.TagId = t.dbTagId
INNER JOIN dbObject p ON p.Id = c.PointId
WHERE p.Id=#objectId
If you have many objects and the amount of data is just a few (meaning that your are not going to manage big volumes) then I would look for a ORM based solution as the Entity Framework.
I (still) feel comfortable writing SQL queries in the DAOs to have under control all queries being sent to the DB server, but finally it is because in our situation is a need. I don't see any inconvenience on having to query the database to recover, first, the object data (SELECT * FROM dbObject WHERE ID=#myId) and fill the object instance, and then query again the DB to recover all satellite data that you may need (the Tags in your case).
You have be more concise about your scenario so that we can provide valuable recommendations for your particular scenario. Hope this is useful you you anyway.
We used stored procedures that returned multiple resultsets, in a similar situation in a previous project using Java/MSSQL server/Plain JDBC.
The stored procedure takes the ID corresponding to the object to be retrieved, return the row to build the primary object, followed by multiple records of each one-to-many relationship with the primary object. This allowed us to build the object in its entirety in a single database interaction.
Have you thought about using the entity framework? You would then interact with your database in the same way as you would interact with any other type of class in your application.
It's really simple to set up and you would create the relationships between your database tables in the entity designer - this will give you all the foreign keys you need to call related objects. If you have all your keys set up in the database then the entity designer will use these instead - creating all the objects is as simple as selecting 'Create model from database' and when you make changes to your database you simply right-click in your designer and choose 'update model from database'
The framework takes care of all the SQL for you - so you don't need to worry about that; in most cases..
A great starting place to get up and running with this would be here, and here
Once you have it all set up you can use LINQ to easily query the database.
You will find this a lot more efficient than going down the table adapter route (assuming that's what you're doing at the moment?)
Sorry if i missed something and you're already using this.. :)
As far I guess, your database exists already and you are familiar enough with SQL.
You might want to use a Micro ORM, like petapoco.
To use it, you have to write classes that matches the tables you have in the database (there are T4 generator to do this automatically with Visual Studio 2010), then you can write wrappers to create richer business objects (you can use the ValueInjecter to do it, it is the simpler I ever used), or you can use them as they are.
Petapoco handles insert / update operations, and it retrieves generated IDs automatically.
Because Petapoco handles multiple relationships too, it seems to fit your requirements.

SQL Delete taking too long

We have a table(say T1) that is referenced by about 16 other tables with foreign keys in our SQL Server database. The data is accessed through an ASP.NET application with LINQToSQL. When the user tried to delete a record from T1 the statement would time out. So we decided to first delete the records from the tables that reference T1 and only then delete the record in T1. The problem is that deletion from T1 does not work as fast as expected.
My question is: is it normal that deletion from a table referenced by many other tables to be so time-consuming even if the record itself does not have any 'children' records?
EDIT: Apparently the cause for the timeout was not the delete itself but another query that retrieved data from the same DataContext. Thank you for your suggestions, I have marked as answer the suggestion to add indexes for all foreign keys because it improved our script's execution plan.
I suspect that you may need to look into the indexing on your child tables.
It sounds as if you FKs are set to Cascade Deletes, so I would suspect that some of your tables do not have an index that includes the key to the parent as the first in the index.
In this way your delete will be full scanning the child tables - even if you've already deleted the child records it will still check as you've still got the Cascade set.
When you define a relationship in DB, you can set the Delete rule as Cascade in SQL server. In this way, when you delete the record from the parent table, it will be automatically deleted from the child tables.
Please see the image below:
If it taking long time, you may have set other constraint that will slow
down the process of deletion.
Linq does not do bulk deletes if you're having it operate directly on the record set -- instead, it is probably deleting one record at a time.
To improve performance, use a stored procedure instead for any bulk insert, update or delete operations.

Resources