Is it possible to import managed keywords into SharePoint 2010?
Where are the keywords stored within which database?
Background -
I'm currently working on a migration from a legacy system into SharePoint 2010. So far everything is going well, and I can even bring across the managed meta data across along with most other data.
The process I use was built for SharePoint 2007 to update Lists over SOAP. With a few manual tweaks I've managed to get the metadata to come across.
To bring across either managed metadata or managed keywords I need to know the ID for the existing label/keyword. I have this for the Managed Metadata however not for the Managed Keyword.
Currently I create a CSV file to be imported for managed metadata before working out the reverent GUID for the source label.
Many Thanks
Luke
Yes, you can import managed terms (keywords aren't managed) into SP2010. The OOTB Managed Metadata service app can import a CSV file... also has a sample. Importing via the API is very easy as well. The following shows how to get reference to the term store and start adding terms. To add terms, look at the Term object.
// get refrerence to the taxonomy term store
TaxonomySession taxonomySession = new TaxonomySession(siteCollection);
// get reference to first term store (can also get by name)
TermStore termStore = taxonomySession.TermStores[0];
string termGroupName = "Locations";
Group termGroup = termStore.Groups.Where(x => x.Name == termGroupName).Count() > 0 ?
termStore.Groups[termGroupName] :
termStore.CreateGroup(termGroupName);
string termSetName = "United States Geography";
TermSet termSet = termGroup.TermSets.Where(x => x.Name == termSetName).Count() > 0 ?
termGroup.TermSets[termSetName] :
termGroup.CreateTermSet(termSetName);
Term newTerm = termSet.CreateTerm("Level 1",1033);
newTerm.CreateTerm("Level 1a",1033);
termStore.CommitAll();
Don't concern yourself with the DB. Read/write ops directly on the DBs are not supported. There's a VERY robust taxonomy API (M.SharePoint.Taxonomy.dll) available.
Related
I am xpages enabling an old Notes application which is using profile documents to store translated labels. The translated lables in the notes form are read from the profile document using #GetProfileField depending on which language the user have selected in their profile.
I have read that profile documents are not recommended to use with xpages so I need a better solution for my xpages users. but it is important that users using Notes client still use the "old" profile document solution.
How can I provide these translation lables to my xpages users?
Thanks
Thomas
In addition to Knut's answer there is also the option to "double" your translated labels via the way to prefer in XPages dev by using the localization options as described here: http://www-10.lotus.com/ldd/ddwiki.nsf/dx/UsingLocalizationOptions.htm
You need to split the task into two. First have a function that is called inside the XPage to get the label you are looking for, secondly have a way to provide that value inside the function.
Making a direct call to the profile isn't a good idea since it fixes the way you provide the data (besides potentially creating a memory leak if you don't recycle dilligently). I would see 4 potential solutions:
Define your profile document as additional data source and simply bind the labels to items in the document. Saves you most of the recycling work, but couples tight
Use a SsJS function: getLabel(name). It would check for a scope variable (a Map) and if not found load it - currently from your profile. If application scope is good enough, you touch the profile once only- speed. If you change the loader later on - you don't need to change anything in the XPage.
Use a managed bean. Same approach as #2, only now you can use el data binding. Your bean needs to implement Map
If the labels hardly change do a design time conversion and write the profile doc out into properties files (works nicely with ODP) and use XPages internal mechanism for internationalization
Let us know how it goes
You can use profile documents for this use case as the content gets changed only with new versions of your project probably. So, you can easily live with profile document's caching.
You get the label translation from a profile document with
var doc = database.getProfileDocument("LabelsEnglish", "");
var label = doc.getItemValueString("label1");
doc.recycle();
return label;
You could read all labels in an application scope variable Map too and do your own caching. This way profile documents would get read only once.
if (!applicationScope.labels) {
var map = new java.util.HashMap();
var doc = database.getProfileDocument("LabelsEnglish", "");
var allItems = doc.getItems();
for (var i = 0; i < allItems.size(); i++) {
var item = allItems.elementAt(i);
item.getName();
map.put(item.getName(), item.getValueString());
item.recycle();
}
doc.recycle();
applicationScope.labels = map;
}
Execute the SSJS code above in a custom control which is included in every XPage (e.g. application layout custom control) in before page load event so you can be sure application scope variable "labels" is initialized when you want to use it. You can access the labels easily with EL
applicationScope.labels.label1
How can I access information about Imports (which you can access via Workplace => Imports, see picture), using SDK? Partucularly I'm interested in a list of errors associated with each Import entry. Even a hint at which classes I should look/check would also be great.
The main entity is ImportFile, you can check the structure here:
MSDN - ImportFile Entity Metadata
you can check the fields totalcount successcount failurecount partialfailurecount
the errors are inside the entity ImportLog, you can check the structure here:
MSDN - ImportLog Entity Metadata
you can check the fields importfileid (the lookup that contains the relationship with importfile) linenumber errornumber
Enforce Unique Values for external data type column - I know that it is not possible out of the box. What are the soultions for validating external data type columns for duplicates? workflows? others?
Well, external lists can't have workflows or event receivers where you could validate data, so doing this in SharePoint would actually be very complicated. My opinion is that you should validate your data before importing it into SP. If your datasource is a DB then add a constraint, if it's a web service then the external system should enforce uniqueness, if it's a custom external content type you can enforce it through code.
Though it doesn't seem to mention it in the MS Documentation you can Enforce uniqueness onto an 'External Data' type column using PowerShell. I've just tried the example below and it works on an SP2013 Farm.
https://msdn.microsoft.com/en-us/library/office/ee536168%28v=office.14%29.aspx?f=255&MSPPError=-2147217396
Example from Office DEV Center
SPSite site = new SPSite("http://localhost");
SPWeb web = site.OpenWeb();
SPList custList = web.Lists["Customers"];
SPField custPhone = custList.Fields["Phone Number"];
custPhone.Indexed = true;
custPhone.EnforceUniqueValues = true;
/// You must call the Update() method
/// when you change the EnforceUniqueValues property
custPhone.Update();
We currently have a field which has the wrong ID. the IDs and Internal Names of Sharepoint Fields are readonly on the domain model. I was wondering if there is a way to update them even by using the content database.
One sure way is to delete the field and recreate it. but it already has data and there are thousands of pages. I was wondering if there is a way just to update the IDs and Internal Name without doing the dropping and recreation of fields.
Thanks
Even if it may work, don't do it.
It's:
Dangerous, as you may skip dependencies
Not supported
Recreating the field using some script to keep data is safer.
We ran into the same problem. Messing with the DB was not an option for us (and shouldn't be for you either), but you can work around it. Unfortunately, it will require touching each page to update the metadata.
First, create the column like it should be in the list. Then, you can copy the data from the old column to the new column in a variety of ways:
DataSheet view
Programmatically via web services (don't need to have access to the server)
Programmatically via console app (will need to run locally on the server)
Honestly, writing a small console app will be the quickest. For example:
string siteUrl = "http://server/sitecollection/";
string webUrl = "subsite1/subsite2/";
string listName = "Your List Name";
using (SPSite site = new SPSite(siteUrl))
{
using (SPWeb web = site.OpenWeb(webUrl))
{
SPList list = web.Lists[listName];
foreach (SPListItem item in list.Items)
{
item["New_x0020_Column_x0020_Name"] = item["Old_x0020_Column_x0020_Name"];
}
}
}
Also, it would HIGHLY recommend trying this in a DEV environment first. Just do an STSADM restore from your production environment and test your console app. Then, validate your data and delete the old column!
I would not suggest modifying the content database, since it is:
unsupported (if you do it, Microsoft will not help you when you're in real trouble even if you have MS Premier Support)
very complicated to do. You'd have to update a number of tables and you would never be sure if you actually updated all the required things.
What you can try to do - see if the internal name property is actually "read only" or it is defined as "friend" and you cannot call it from a different code assembly. If it's the latter case, you can use .Net reflection to set the property value. See this MSDN documentation link for details.
Environment:
I have a windows network shared desktop application written in C# that leans against an MSSQL database. Windows sharepoint services 3.0 is installed (default installation, single processor, default sql express content database and so on) on the same Windows Server 2003 machine.
Scenario:
The application generates MS Word documents during processing (creating work orders) that need to be saved on sharepoint, and the result of the process must be linked to the corresponding document.
So, for each insert in dbo.WorkOrders (one work order), there is one MS Word document. I would need to save the document ID from the sharepoint library to my database so that later on, possible manual corrections can be made to the document related. When a work order is deleted, the sharepoint document would also have to be deleted.
Also, there is a dbo.Jobs table which is parent to dbo.WorkOrders and can have several work orders.
I was thinking about making a custom list on sharepoint, that would have two ID fields - one is the documents ID and the other AutoID of the document. I don't think this would be a good way performance-wise and it requires too much upkeep, therefore it's more error prone.
Another path I was contemplating is metadata. I could have an Identity field in dbo.WorkOrders that would be unique and auto incremented, and I could save that value as a file name (1.docx, 2.docx 3.docx ... n.docx where n would be the value in dbo.WorkOrder's identity field). In the metadata field of the Word document, I could save the job ID from dbo.Jobs.
I could also just increment the identity field in the WorkOrder (it would be a bigint), but then the file names would get ugly and maybe I'd overflow the ID range (since there could be a lot of documents).
There are other options also that I have considered and dismissed, since none of them satisfied the requirements (linked data sources, subfolder structures etc.). I'm not sure how to proceed. I'm new to sharepoint and it's still a bit of a mystery to me, as I don't understand all the inner workings of the system.
What do you suggest?
Edit:
I think I'll be using guid as file names and save those guids in my database after sending documents to sharepoint. What do you think of that?
All the documents in SharePoint under the same Content Database (SQL Database) are stored in the same table, that said, you have an unique ID for files no matter where they are in the sharepoint structure.
When retrieving files by their UniqueID The API only gives you the option to get them if you also know their SPWeb, so you could easily store, for each record you have in your external database (or your custom list, the SPFile GUID and the SPWeb GUID) retrieving them with:using(SPWeb subweb = (SPContext.Current.Site.OpenWeb(new Guid("{000...}")))
{
SPFile file = subweb.GetFile(new Guid("{111...}"));
// file logic
}
ps.: As Colin pointed out, url retrieval is possible but messy. I also changed the SPSite to the context since you are always under the same Site Collection in my example.
Like F.Aquino said, all items in sharepoint have a UniqueId field already (i.e. SPListItem.UniqueId and SPFile.UniqueId), which is a guid. Save that to your database, along with your web.'s guid. Then you can use the code provided by F.Aquino to get the file, or even the byte[] of the stream.
P.S. for F.Aquino, your code leaves the SPSite in memory, use this instead:
P.P.S this is just clarification, mark F.Aquino as the answer.
using(SPSite site = new SPSite("http://url"))
{
using(SPWeb subweb = site.OpenWeb(new Guid("{000...}"))
{
SPFile file = subweb.GetFile(new Guid("{111...}"));
// file logic
}
}