I have a block of code where I'm trying to disable event firing when editing a file, once the debugger hits the item.SystemUpdate(false) line it throws an exception that states "The file xxxx has been modified by xxxxx"
HandleEventsFiring handle = new HandleEventsFiring();
handle.DisableHandleEventFiring();
try
{
web.AllowUnsafeUpdates = true;
SPFile rptFile = web.GetFile(item.Url); //item is an SPListItem
if (rptFile.Exists)
{
WordDocUtility word = new WordDocUtility();
using (System.IO.Stream stream = rptFile.OpenBinaryStream())
{
word.ReplaceKeys(stream, keys);
rptFile.SaveBinary(stream);
}
}
item.SystemUpdate(false); // the line throwing the exception
}
finally
{
handle.EnableHandleEventFiring();
web.AllowUnsafeUpdates = allowUnsafeUpdates;
}
public class HandleEventsFiring: SPItemEventReceiver
{
public void DisableHandleEventFiring()
{
this.EventFiringEnabled = false;
}
public void EnableHandleEventFiring()
{
this.EventFiringEnabled = true;
}
}
Does anyone know of a way around this or am I doing something wrong?
Any help would be greatly appreciated.
You haven't really shown enough of the code for us to point you to the exact problem. The error that you're getting means that after you pulled the list item that is in item from the content database it was later updated. Chances are, if you get the error every single time, that you're pulling down the same item more than once and your changes are conflicting with yourself. My guess is that item represents a file in a document library, and that you're modifying the file in addition to the splist item. These changes are what are conflicting. You need to fetch the item, update the item, then fetch the file and update the file. If you need to fetch the item and then update the file you will need to fetch the item again so that you don't end up updating an item when another update occurred between the fetch and update.
Related
The issue is encountered when I was trying to fetch some images from a folder,
The issue gets resolved whenever I switch the media to a new folder.
Any help is appreciated.
The code below is used for fetching Umbraco media
foreach (var mediaItem in mediasList)
{
IPublishedContent media = null;
Udi udiId;
if (Udi.TryParse(mediaItem, out udiId))
{
media = Umbraco.TypedMedia(udiId);
}
else
{
media = Umbraco.TypedMedia(mediaItem);
}
if (media.DocumentTypeAlias == "Folder")
{
var childrens = media.Children(); //getting error in this line
foreach (var image in childrens)
{
}
}
}
From the MSDN forum:
This isn't an error in and of itself, but more of a feature of your debugger. Some properties require code to be executed in order for the property to be read, but if this requires cross-thread interaction, then other threads may have to run as well. The debugger doesn't do this automatically, but certainly can, with your permission. Just click the little evaluate icon and it will run your code and evaluate the property.
Also, you can get the results if you do var childrens = media.Children().ToList() for example.
I added an entry in the Properties.Settings named strCol that is of type NameValueCollection. I am using this to save items from a listview to the settings so that when the application reboots, the ListView gets re-populated again with the items that were saved previously. I'm only storing the item name and the tag from the ListViewItems.
But something strange is happening I cant explain.
I am using this code to save the items to the settings:
NameValueCollection nvCol = new NameValueCollection();
foreach (ListViewItem lviP in lvParmNames.Items)
{
nvCol.Add(lviP.Text, lviP.Tag.ToString());
}
Properties.Settings.Default.strCol = nvCol;
Properties.Settings.Default.Save();
For some reason the Save and load in and from settings works fine, as long as the application is still active. But when the application has been closed and rebooted, the load doesn't work as if the NameValueCollection was not saved.
What am I missing here ?
How I'm currently loading the setting:
The call for loading, but it already seem to fail at the check if its null
if (Properties.Settings.Default.strCol != null)
{
NameValueCollection nv = Properties.Settings.Default.strCol;
foreach (string key in nv)
{
try
{
var value = nv[key];
ListViewItem lvi = new ListViewItem(key);
lvi.Tag = value;
lvFamNames.Items.Add(lvi);
}
catch (Exception ex)
{
TaskDialog.Show("Error", "Error while parsing Family Names from saved settings. \n" + ex.Message);
}
}
}
Just noticed something:
Though i added the NameValueCollection in the sections it is actually not added when building the application. When i open the config file, the setting is not there.
So i guess the issue is here, though now i need to figure out how to add it now.
Looking into the Settings.Designer.cs file, i guess this part looks wrong for the type of 'NameValueCollection`:
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public global::System.Collections.Specialized.NameValueCollection strColExcelFamNames {
get {
return ((global::System.Collections.Specialized.NameValueCollection)(this["strCol"]));
}
set {
this["strCol"] = value;
}
}
I'm automating a mailmerge process which uses a CSV file. Part of this process requires creating a database (OpenOffice odb file) and then registering this as a datasource. When I come to delete the database I get an exception stating 'Cannot delete yourFile:It is being used by another person or program'. The problem is that I cannot get the OpenOffice process to release this resource (without killing it). My current code is:
public string DeleteDatasource(string datasourceName)
{
string result = string.Empty;
object databaseContext = _MultiServiceFactory.createInstance("com.sun.star.sdb.DatabaseContext");;
try
{
XDatabaseRegistrations databaseRegistrations = (XDatabaseRegistrations)databaseContext;
if(databaseRegistrations.hasRegisteredDatabase(datasourceName))
{
/* //attempt one
XNameAccess nameAccess = (XNameAccess)OODatabaseContext;
object datasource = nameAccess.getByName(datasourceName);
XNamingService namingservice = (XNamingService)OODatabaseContext;
namingservice.revokeObject(datasourceName);
*/
//attempt 2
string databaseLocation = databaseRegistrations.getDatabaseLocation(datasourceName);
databaseRegistrations.revokeDatabaseLocation(datasourceName);
if (!String.IsNullOrEmpty(databaseLocation))
try
{
//As File Path converts the uno file string into a standard form i.e. "file:///c:/temp/DatabaseFile.odb" to "c:\\temp\\DatabaseFile.odb"
File.Delete(databaseLocation.AsFilepath());
}
catch (System.Exception ex)
{
//some error handling
}
}
return result;
}
catch (System.Exception ex)
{
//More error handling
}
}
Any ideas how I can unregister this datasource such that I can then delete the odb.
Thanks
Managed to get around this issue and just in case anyone else is interested here's how.
The key was to get a reference to the actual datasource and to then dispose of this.
The basic steps are:
Check if a datasource exists with the specified name
Get datasource object
Get the datasource filename
Dispose of the database document associated with the datasource
Dispose the actual datasource
Delete the database file :)
The source code for this looks something like
XNameAccess nameAccess = (XNameAccess)_MultiServiceFactory.createInstance("com.sun.star.sdb.DatabaseContext");
object datasource = nameAccess.getByName(datasourceName);
XDocumentDataSource obj = (XDocumentDataSource)((Any)datasource).Value;
//get the location of the associated odb file before we dispose the document object
//and deregister the datasource
string databaseLocation = databaseRegistrations.getDatabaseLocation(datasourceName);
databaseRegistrations.revokeDatabaseLocation(datasourceName);
((XComponent)obj.DatabaseDocument).dispose();
((XComponent)obj).dispose();
//put in a try block as we want to continue even if this fails
//AsFilepath converts the OpenOffice file path to standard for that can be used with the standard IO file access classes
File.Delete(databaseLocation.AsFilepath());
If there are any improvements please let me know...
Click View,Click Data Sources,
Right Click Registered Databases you wanted to remove,
Click Registered Databases,
Click Delete for the highlighted registered database you want to remove.
I'm trying to save a TFS Work Item programmatically but always get the exception:
TF237124: Work Item is not ready to save
Now, I understand what this is telling me - that the Work Item is missing a required field or similar - and my code is anticipating this by calling:
ArrayList ValidationResult = wi.Validate();
before the save. However my ArrayList contains no elements following this call.
I've tried logging in to the TFS web interface using the same credentials and creating a Work Item that way which works fine.
How can I discover why my Work Item won't save? Here's my code:
// get a reference to the team project collection (authenticate as generic service account)
using (var tfs = new TfsTeamProjectCollection(tfsuri, new System.Net.NetworkCredential("My_User", "password")))
{
tfs.EnsureAuthenticated();
var workItemStore = GetWorkItemStore(tfs);
// create a new work item
WorkItem wi = new WorkItem(GetWorkItemType(type, workItemStore));
{
//Values are supplied as a KVP - Field Name/Value
foreach (KeyValuePair<string,string> kvp in values)
{
if (wi.Fields.Contains(kvp.Key))
{
wi.Fields[kvp.Key].Value = kvp.Value;
}
}
ValidationResult = wi.Validate();
}
if (ValidationResult.Count == 0)
{
wi.State = wi.GetNextState("Microsoft.VSTS.Actions.Checkin");
wi.Save();
return wi.Id;
}
else
{
return 0;
}
}
}
You are validating the work item before you are changing it's state. Transitioning to a new state can cause Work Item Template actions/rules to be processed. These could be changing the values of some of your fields and/or adding new rules to the fields which would cause the previously valid data to be invalid.
Moving from an Open state to a Closed state might require someone to complete a "Review" field (for example) - if it's empty it cannot transission.
Try validating after the State change and see if there are any failures.
I am using C# code and Tridion(CMS) classes to fetch data from Tridion, below is the code to get all the publications List from Tridion.
protected void btnPublishPublicationList_Click(object sender, EventArgs e)
{
try
{
PublicationBL pubBL = new PublicationBL();
TridionCollection<Publication> pubAllList = pubBL.getAllPublicationList();
List<PublicationsBO> pubBos = new List<PublicationsBO>();
foreach (Publication pub in pubAllList)
{
if ((pub.Title.StartsWith("07"))||(pub.Title.StartsWith("08")))
{
PublicationsBO pubBO = new PublicationsBO();
pubBO.publicationID = pub.ID;
pubBO.publicationName = pub.Title;
pubBos.Add(pubBO);
}
}
pubBL.createPublicationListXML(pubBos);
}
catch (Exception ex)
{
log.Error(ex.Message);
}
}
In above code on the button click, I am using .net code and using Tridion class to get all the publications List as below:
TridionCollection<Publication> pubAllList = pubBL.getAllPublicationList();
I am getting my all the publications list very fast from the Tridion, however when I am going for foreach loop as below my process gets stuck and it takes lots of time to do this.
foreach (Publication pub in pubAllList)
{
if ((pub.Title.StartsWith("07"))||(pub.Title.StartsWith("08")))
{
PublicationsBO pubBO = new PublicationsBO();
pubBO.publicationID = pub.ID;
pubBO.publicationName = pub.Title;
pubBos.Add(pubBO);
}
}
After debugging I found that when debugger comes to foreach (Publication pub in pubAllList) it is taking lots of time. I think while making the Publication class object is taking time and it is Tridion class.
Please suggest any other way to do this or suggest what is wrong in above code.
Thanks.
It is indeed because of Tridion's lazy-loading. If all you need is a list of Publication IDs and Titles, I'd recommend using:
TDSE tdse = new TDSEClass():
XmlDocument publicationList = new XmlDocument();
publicationList.LoadXml(tdse.GetListPublications(ListColumnFilter.XMLListIDAndTitle));
This will give you an XML document containing a list of all publications (/tcm:ListPublications/tcm:Item), and each Item will contain a Title and ID attributes.
If you need more detail than just ID and Title, then you will have to individually load each publication, which you can do by using the ID attribute tdse.GetObject().
Hope this helps.
N
according to this which I think is the developers site... it looks like getAllPublicationList is using some sort of lazy loading so even though you have the collection you don't really have the items in it.
It appears that you can set filters on their collection rather than after the fact so that it will only load the records you are interested in.
to clarify, lazy loading means that when the collection is returned the data needed to populate the items in it are not yet laded. It isn't until you access the item in the collection that the data (e.g. by creating a Publication item) for that item is actually loaded. The purpose for using a lazy collection is to allow filtering on the collection so that unnecessary expensive loads can be avoided.
HTH