How to clean up after Sitecore template "Shared" setting was "packaged" and "installed" and items using this field are unaware - sitecore

we faced very specific scenario in our Sitecore enviroment. In our Sitecore we have a item, lets call it "Promotion". Promotion was using "End date" field that was shared.
On our dev instance we "unshared" the field. Which naturally triggers the background process that changes the items to use field in unshared mode.
Similar process is described here: http://sitecoreblog.alexshyba.com/2011/10/changing-field-sharing-settings-in.html
So then we packaged and installed change of "unsharing field" on production "master" database. As I assume during installation the background process of "updating the items" has not been triggered. Which now behaves in the way, that "unshared" field on our production master database cannot be saved. Cahnges of value after clicking save are "vanishing". I am sure they are now being saved in some language agnostic mode.
Of course simple fix for that is to "share" it back and "unshare" it again. However when we tried to do this experiment on copy of our enviroment and we noticed all the values were lost. As the items from mentioned template are heavily used, we cannot really afford loosing those values.
Any ideas?

I would go "database digging". Sitecore stores these field values in their respective databases inside the "SharedFields", "VersionedFields" and "UnversionedFields" tables.
Assuming you shut off your Sitecore instances (this is important), you should be able to SELECT the data out of the wrong table, and INSERT it into the correct one.
(you need to look for items where FieldId matches the field you are having trouble with)
From what you've described, I don't believe Sitecore has removed any data on your production environment (yet).

So the solution we came up to, was to use Sitecore Rocks tool. We exported all the Items containing the fields before changing the field to "Share". The query was more or less like that:
SELECT ##ID, ##Start Date#, ##End Date# FROM //*[##templateid='{993DC54F-6724-46C3-B8D2-3EE13F15366A}']
It gave us proper values at that point, even though to items were pointing to the SharedFields table. We just simply converted the result of this query (around 9000 rows) in Excel to Sitecore Rocks update query -
UPDATE SET ##Start Date#='20120531T000000',##End Date#='20120614T000000' FROM //* [##ID='{E3FD9819-3DBD-4FAA-8DEF-FEF2A6272723}'];
After prepared this migrations script, we shared the appropriate field and apply the script of 9000 updates queries through Sitecore Rocks. We need to to exactly the same on Live database. Everything went pretty smooth.
The same approach could be easily done with the database I believe, however this solution was better for us, because of non-technical reasons (security policies etc.). Anyway Sitecore Rocks rocks!

Related

How to not lose hasMany changes on Ember query?

In my application, I search for documents with query.
Then I edit one attribute in a single document, and then I call search query again.
Result is OK, I see document still in a dirty state with changed attribute.
Then I again pick one of documents and edit its hasMany relation (from 2 items to 4 items). And then I call search query again.
Result is NOT OK, hasMany relation change is lost/disposed/rollbacked.
Is there a way so Ember query (i guess it's some Ember internal reload) does not rollback not saved relation changes ?
I am using Ember 2.9.1
For now i have no other way than prohibit any filter query actions or route actions anything that could call query again, since that would cause lost data that user set.
Ember's store.query method always refetches the models from the backend (unlike the find* methods). With a query, it's the only way to make sure you have the most up-to-date data (and that the models loaded into the store are still valid). Even in your instance, you may run into unexpected results if you change the data such that it no longer meets your query criteria.
If you would like to keep edits around between queries, I would recommend making a copy of all models which are dirty (check the hasDirtyAttributes attribute). You can gather them with peekAll. Once copied, you can then make the query and patch the records by ID. Perhaps by using Ember.assign.
Even using that method, I would still think that you will get into trouble tracking the changes and making sure the records stay consistent with your query. Like what do you if that record wasn't returned (deleted on the server or no longer meets your criteria)? Do you drop your edits? What if you have a conflict between the data from the server and your local version (e.g. another user patched the hasMany relationship that the other user is now querying and modifying)?
ember-changeset seems like it could be useful here. However, it's not obvious how to get a ChangeSet to apply to a new instance of the same model. Though it may be possible to keep a snapshot and match them up manually. However, you still run into data consistency issues.

Sitecore ItemID does it change from deployment to deployment?

I am new to Sitecore and have a basic question around this. When I create a Sitecore item a Unique ID is created for this item. Is it ok if I use this item ID in the code to hold a reference to it? Does this change from deployment to deployment?
If you actually "deploy" your items -using a package or serialization (tool)-, the ID will stay the same and you can keep a reference to it in your code.
It is a good coding practice however not to spread hard-coded guids (as that is what the ID actually is wrapping) around all over your code. So either bundle them somewhere in a piece of code that can easily be deployed without side-effects or put them in a configuration file (but again, bundle them and don't mix with other stuff).
If for some reason the item would be gone some day and you need to re-create it (meaning: the id is changed) or you just need it to point to a new one, you will be grateful that you did keep it somewhere separated ;)
This is Sitecore behaviour to have Sitecore ID like a GUID. It is a very good aproach. The ID of an item can be also use in your C# code
The ID class in Sitecore is used to identify all types of item in Sitecore i.e. content items, templates, media items etc. It is a wrapper around .NET's own System.Guid struct and has a property called Guid which returns a System.Guid. Internally Sitecore stores IDs in it's SQL Server database using the uniqueidentifier type.
For exemple a template is also an item and it has a unique ID. If it wasn't the same ID between environments you need to modify your code between environments.
Sitecore ItemID always remain unique. So If you publish the content from your CM server to CD server, Item ID will not change. You can use ItemID as this ensure even if you change the name, you still reference to right Sitecore Content Item.
It is recommended to use some kind of class and put the item id there and reference from there so that in future, if you ever need to change then you change it in one place.
Using directly GUID or any number value for that matter are kind of magic values and is always prone to bugs.
A quick answer is yes, an ID does not change during deployments, so you can hold a reference in your code.
Sitecore Item Id will not change from deployment to deployment, You can use this ID in your code like:
Creating a class holding IDs
Or maybe a configuration file

Sitecore item will not go into edit mode; any suggestions on how to troubleshoot?

I have several Sitecore items (whose template is connected to an approval workflow) that will not go into Edit mode when clicking "Edit" from the "Review" tab. The same workflow is used elsewhere on the site successfully (the site is more than 3 years old), but clicking Edit in this case doesn't seem to affect the workflow state.
I've turned on verbose logging, which provides a lot of detail, but nothing to indicate any error conditions. I've been comparing how this template is configured with other "working" templates for a couple of days and everything looks Kosher, but surely I'm missing something obvious.
EDIT: The item(s) in question are imported by a data provider, and I've confirmed that for some reason Sitecore is not setting the "Workflow" and "State" system standard fields with a default value. That appears to be at least part of the issue.
EDIT 2: Followed the steps in this thread http://sdn.sitecore.net/Forum/ShowPost.aspx?PostID=45991 to use Sitecore Rocks to update all of the items to the correct Workflow State, but the update did not stick. For some reason workflow changes are not persisted for imported items.
EDIT 3: Clicking the Edit dropdown button under the Home tab displays the message "The item is currently not part of a workflow."
Standard values set correctly? Only have one Standard Values item for this template?
Generally, almost every time I run into a situation where X works on certain items, but not on others... it's a permissions issue. You've tested this as an Administrator I hope?
Sorry my suggestions are so vague, but it's hard to be specific here. We need some more information from you... When you click on Edit what exactly are you expecting to happen? I'm not entirely sure what you mean by "Edit mode" here. In Content Editor, all items are essentially in edit mode all the time... In my configuration, when I click on Edit, I am just locking the item. It does not change workflow state or create a new version.
These items are coming from a data provider... is your data provider handling Lock/Unlock calls properly? I know it's possible to use a data provider without implementing the entire Item API.

Need help optimizing this Django aggregate query

I have the following model
class Plugin(models.Model):
name = models.CharField(max_length=50)
# more fields
which represents a plugin that can be downloaded from my site. To track downloads, I have
class Download(models.Model):
plugin = models.ForiegnKey(Plugin)
timestamp = models.DateTimeField(auto_now=True)
So to build a view showing plugins sorted by downloads, I have the following query:
# pbd is plugins by download - commented here to prevent scrolling
pbd = Plugin.objects.annotate(dl_total=Count('download')).order_by('-dl_total')
Which works, but is very slow. With only 1,000 plugins, the avg. response is 3.6 - 3.9 seconds (devserver with local PostgreSQL db), where a similar view with a much simpler query (sorting by plugin release date) takes 160 ms or so.
I'm looking for suggestions on how to optimize this query. I'd really prefer that the query return Plugin objects (as opposed to using values) since I'm sharing the same template for the other views (Plugins by rating, Plugins by release date, etc.), so the template is expecting Plugin objects - plus I'm not sure how I would get things like the absolute_url without a reference to the plugin object.
Or, is my whole approach doomed to failure? Is there a better way to track downloads? I ultimately want to provide users some nice download statistics for the plugins they've uploaded - like downloads per day/week/month. Will I have to calculate and cache Downloads at some point?
EDIT: In my test dataset, there are somewhere between 10-20 Download instances per Plugin - in production I expect this number would be much higher for many of the plugins.
That does seem unusually slow. There's nothing obvious in your query that would cause that slowness, though. I've done very similar queries in the past, with larger datasets, and they have executed in milliseconds.
The only suggestion I have for now is to install the Django debug toolbar, and in its SQL tab find the offending query and go to EXPLAIN to get the database to tell you exactly what it is doing when it executes. If it's doing subqueries, for example, check that they are using an index - if not, you may need to define one manually in the db. If you like, post the result of EXPLAIN here and I'll help further if possible.
Annotations are obviously slow, as they need to update every record in the db.
One direct way would be to denormalize the db field. Use a download_count field on the plugin models that is incremented on the new save of Download. Use the sort by the aggregate query on Plugins.
If you think there are going to be too many downloads to update another record of the Plugin all the time, you can update the download_count field on the Plugin via a cron.

How are write conflicts avoided in django administration?

Suppose there are two (or more) django administrators who have read a database record and then change and save it. There is no database problem, but some administrators are going to be surprised that the record they wrote was overwritten.
Is this issue ever addressed? One way would be to have an explicit "edit in progress" button which sets a flag in the record. If another administrator reads the same record and then clicks his "edit in progress" he will be warned that there is a previous edit in progress. Or a field could be added to the record which is incremented when a record is saved. If the field is different from when the record was read, the administrator is warned that the record has been changed by someone else since he read it.
Is there a native django way of handling this?
The Django admin does not implement any write conflict protection out of the box. It would not be hard to add it yourself. Personally, I would take the "version number field" approach.
Generally this is where you want to read up on your database's transaction-isolation features, because that's why it has them.
If you'd really rather not do that, various patterns exist for doing this at the application layer, but there is no canonical way to do it -- some people set a sort of "last access" timestamp and refuse to allow editing within a certain period after that, others set version numbers, etc., etc.