Symfony2/Doctrine2 caching stuff to avoid queries - symfony

Background: I have a fairly big table (2000 rows, 10 columns) full of small int (0,1,2 only).
Given an entity and a field of that entity, depending on the values of the 10 columns I get the information if I want to display and or make required that field of that entity when I render the form.
Instead of querying the DB for each field, every time I have my ->add in the form builder, I'd like to cache the whole table "somewhere" in server's memory.
How can I do that? Is it necessary that each user "loads" the table, or can it be done once for all of the users and each user simply reads server's RAM?
That table almost never changes. Still I need to be able to upload an updated version of it every once in a while (veeery seldom).
Thank you!
SN

All you need to do is use useResultCache method.
Doctrine uses cache driver set in Symfony configuration, so when you write queryBuilder which is fetching data from your table just tell Doctrine you want result to be cached (for how long and under what key is optional):
class YourEntityRepository extends EntityRepository
{
public function getAllRowsCached()
{
$cachedResult = $this->createQueryBuilder('e')
->getQuery()
->useResultCache(true, 3600, 'cache_key')
->getArrayResult();
return $cachedResult;
}
}
Cache is common for all users so first user will query DB, second will use data from cache. Also note, that by default in dev environment cache is disabled.
Check this blog entry for more detailed info

Related

In symfony what event can I use to add parameter to every database query?

I can’t find a solid answer for this, I’ve thought about using event listeners but I can’t seem to find a doctrine event to do what I want.
So the system we are building has different user accounts where each user is able to create a record, let’s say they can create a task using a Task entity and they can create a calendar event using a CalendarEvent entity.
Both entities have $createdBy mapped to the User entity.
When we pull data from the database, say a list of tasks, we only want the tasks for the current user but this would mean for every single entity in the system we would have to make sure the user is passed in the database query which easily becomes a mess.
What I want to do is automatically fill the $createdBy during persist and automatically add it as a where parameter during retrieval.
So instead in every repo function we write doing this for example:
$this->findBy([‘createdBy’=>$user]);
The createdBy part should be added automatically ; perhaps with some doctrine event?

AddOrUpdate() throws error: Modifying a column with the 'Identity' pattern - how should I be handling this?

I've been working through Adrian Hall's book on integrating Xamarin and Azure Mobile Apps. In Chapter 3 he adds a User table to facilitate "Friends" data. In his implementation, the client authenticates the user and then makes a request to a custom endpoint that either adds the user to the database or updates their record. Here's an abridged version of the method in the custom controller:
[HttpGet]
public async Task<IHttpActionResult> Get()
{
// ...Obtain user info
User user = new User()
{
Id = sid,
Name = name,
EmailAddress = email
};
dbContext.Users.AddOrUpdate(user);
dbContext.SaveChanges();
// ...
}
The trouble is, the 2nd time the same user logs in to the app, this code throws an exception saying
Modifying a column with the 'Identity' pattern is not supported. Column: 'CreatedAt'. Table: 'CodeFirstDatabaseSchema.User'.
This StackOverflow Answer explains that this is because the AddOrUpdate() method nulls out any properties not set on the entity, including CreatedAt, which is an identity column. This leaves me with a couple of questions:
What is the right way to Add or Update an entity if the CreatedAt value cannot be edited? The same SO thread suggests a helper method to look up the existing CreatedAt and apply it to the entity before trying to save it. This seems cumbersome.
Why is this implemented as a custom auth controller that returns a new Auth token when it only needs to add or update a User in a database? Why not use a normal entity controller to add/update the new user and allow the client to continue using the Auth token it already has?
For the CustomAuthController.cs code, see here.
When you focus on what you are trying to do from SQL perspective it would be like:
update dbo.some_table set some_primary_key = new_primary_key where some_primary_key = ...
which would result in cannot update identity column some_primary_key which makes sense.
But if you do have a reason to update the PK you still can do it if you set the identity insert
SET IDENTITY_INSERT dbo.some_table ON;
Then after you made an insert you set it off using similar syntax.
But this is rather exceptional scenario.
Usually there is no need to manually insert PKs.
Now going back to EF.
The error you are getting is telling you that you cannot modify a column with PK, most likely user_id and/or some other columns if you have composite PK.
So, first time round a new user gets created. Second time round, because you are suing GetOrUpdate a user gets udpated but because you are passing PK it breaks.
Solution?
AddOrUpdate was meant to help with seeding the migrations only.
Given its destructive nature I would not recommend using GetOrUpdate anywhere near production.
You can replace GetOrUpdate with two operations Get and Update
Fetch user and then
if not exists then create a new one
or if it does exist then update it

How do I save the "Many" side of a Many to One if I only have the id of the "One" side?

Let's say I have two entities with a one to many relationship. Call them EntityOne and EntityMany.
I want to save an EntityMany to the database.
I don't have an instance of EntityOne but I know the required entity_one_id.
Is there a way to save EntityMany without retrieving an instance of EntityOne from the db?
I don't want to do anything with the saved EntityMany. I just want to save it.
The only way I've been able to save EntityMany in this situation is to retrieve the EntityOne from the db, do a $entity_many->setEntityOne($entity_one) and then persist EntityMany.
That works but it seems like an unnecessary query for EntityOne when all the db needs is the id.
I tried simply instantiating a new EntityOne() and setting the id (I had to add a setter for the auto-generated integer id) and then using that unsaved instance but Doctrine was not happy with several errors.
EntityManager has a method "getReference" - you can use it to achieve your goal. It should look something like that:
$entityRef = $em->getReference('EntityOne', $entityOneId);
$entityMany->setEntityOne($entityRef);
// ...
Look here:
http://docs.doctrine-project.org/en/latest/reference/configuration.html#proxy-objects

LINQ to SQL - updating records

Using asp.net 4 though C#.
In my data access layer I have methods for saving and updating records. Saving is easy enough but the updating is tedious.
I previously used SubSonic which was great as it had active record and knew that if I loaded a record, changed a few entries and then saved it again, it recognised it as an update and didn't try to save a new entry in the DB.
I don't know how to do the same thing in LINQ. As a result my workflow is like this:
Web page grabs 'Record A' from the DB
Some values in it are changed by the user.
'Record A' is passed back to the data access layer
I now need to load Record A again, calling it 'SavedRecord A', update all values in this object with the values from the passed 'Record A' and then update/ save 'SavedRecord A'!
If I just save 'Record A' I end up with a new entry in the DB.
Obviously it would be nicer to just pass Record A and do something like:
RecordA.Update();
I'm presuming there's something I'm missing here but I can't find a straightforward answer on-line.
You can accomplish what you want using the Attach method on the Table instance, and committing via the SubmitChanges() method on the DataContext.
This process may not be as straight-forward as we would like, but you can read David DeWinter's LINQ to SQL: Updating Entities for a more in depth explanation/tutorial.
let's say you have a product class OR DB, then you will have to do this.
DbContext _db = new DbContext();
var _product = ( from p in _db.Products
where p.Id == 1 // suppose you getting the first product
select p).First(); // this will fetch the first record.
_product.ProductName = "New Product";
_db.SaveChanges();
// this is for EF LINQ to Objects
_db.Entry(_product).State = EntityState.Modified;
_db.SaveChanges();
-------------------------------------------------------------------------------------
this is another example using Attach
-------------------------------------------------------------------------------------
public static void Update(IEnumerable<Sample> samples , DataClassesDataContext db)
{
db.Samples.AttachAll(samples);
db.Refresh(RefreshMode.KeepCurrentValues, samples)
db.SubmitChanges();
}
If you attach your entities to the context and then Refresh (with KeepCurrentValues selected), Linq to SQL will get those entities from the server, compare them, and mark updated those that are different
When LINQ-to-SQL updates a record in the database, it needs to know exactly what fields were changed in order to only update those. You basically have three options:
When the updated data is posted back to the web server, load the existing data from the database, assign all properties to the loaded object and call SubmitChanges(). Any properties that are assigned the existing value will not be updated.
Keep track of the unmodified state of the object and use Attach with both the unmodified and modified values.
Initialize a new object with all state required by the optimistic concurrency check (if enabled, which it is by default). Then attach the object and finally update any changed properties after the attach to make the DataContext change tracker be aware of those updated.
I usually use the first option as it is easiest. There is a performance penalty with two DB calls but unless you're doing lots of updates it won't matter.

Does storage usage increase with long class names?

I am creating a server for an app with a Notifications table which will have A LOT of records (about 100 million records) but only two small values in each record. From what I understand, the name of the Datastore Entity is part of the Entity key and it looks as if the key gets longer with longer Entity names, so I am guessing it is not hashed to the same length for all names? Is this true? Will storage increase with long names?
If so, can I tell Objectify (3.x) what the Entity name in Datastore will be or do I need to rename my classes?
Initially I wrote that space used by keys is not being counted toward your quota because I heard something like that in one of the Google I/O videos. After extensive googling I can't find any info that would confirm this. So I think we should assume the longer the names of your entities the more you'll pay.
You can define name of the entity in annotation's attribute
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.TYPE})
public #interface Entity
{
/**
* Controls the actual kind name used in the datastore.
*/
String name() default "";
}

Resources