Monday, October 31, 2011

VSDBCMD: fix possible reason for “The target database schema provider could not be determined” error

As you probably know VSDBCMD is utility which can be used in order to create database from the output of Sql Server 2008 database project (.dbproj file). Command line which creates database may look like this:

vsdbcmd /a:Deploy /dsp:SQL /dd+ /manifest:MyDatabase.deploymanifest /p:DeploymentConfigurationFile=MyDatabase_Database.sqldeployment /p:SqlCommandVariablesFile=MyDatabase_Database.sqlcmdvars /cs:"Data Source=(local);Integrated Security=True;Initial Catalog=MyDatabase"

(you may find full reference here).

However this particular command may cause error when you run it on the Sql server instance which doesn’t contain MyDatabase database yet: “The target database schema provider could not be determined.  Deployment can not continue”. Interesting that if Sql server instance contains the database this command works. Recently I faced with similar problem.

Event log contained the following information message from MSSQLSERVER component: “Login failed for user 'username'. Reason: Failed to open the explicitly specified database. [CLIENT: <local machine>]”. However if I deployed this project from VS which was ran using the same user account everything worked successfully.

Then I tried to run the command with less arguments:

vsdbcmd /a:Deploy /dd:+ /manifest:MyDatabase.deploymanifest

It was run successfully, i.e. database was created. If you will check .deploymanifest file you will find that it contains deployment properties including the following:

<TargetConnectionString>Data Source=(local);Integrated Security=True;Pooling=False</TargetConnectionString>
<TargetDatabase>MyDatabase</TargetDatabase>

Note that connection string passed to the command which doesn’t work contains “Initial Catalog” setting:

Initial Catalog=MyDatabase

which specifies the actual database. So I checked the command line reference for VSDBCMD and found that there is separate parameter for the target database:

/p:TargetDatabase="String"

So I removed “Initial Catalog” from the connection string parameter (/cs) and used /p:TargetDatabase with database name:

vsdbcmd /a:Deploy /dsp:SQL /dd+ /manifest:MyDatabase.deploymanifest /p:DeploymentConfigurationFile=MyDatabase_Database.sqldeployment /p:SqlCommandVariablesFile=MyDatabase_Database.sqlcmdvars /cs:”Data Source=(local);Integrated Security=True” /p:TargetDatabase=”MyDatabase”

In this case database was created successfully. Hope it will be helpful for you as well.

Saturday, October 29, 2011

“No coercion operator is defined between types” error in expression trees

Suppose that you have 2 inherited classes:

   1: public class Bar
   2: {
   3:     public static explicit operator Bar(string s) { return null; }
   4: }
   5: public class Foo : Bar
   6: {
   7: }

As shown above in the parent class Boo there is explicit cast operator from string (the fact that it returns null is not relevant for us). With this operator you may cast Bar from string:

   1: Bar b = (Bar)"foo";

Also you may cast to Foo and compiler will allow to do that:

   1: Foo f = (Foo)"foo";

Now let’s try to construct expression tree which converts string to Foo:

   1: var expr = Expression.Convert(Expression.Constant("foo"), typeof (Foo));

It will compile but will throw exception “No coercion operator is defined between types 'System.String' and 'Foo'”. This looks strange because compiler allows to do the same cast directly.

Ok, there is overridden version of Convert method and if you checked my previous post about similar problem with LessThan method, we can try to use it in order to avoid the problem:

   1: var mi = typeof(Bar).GetMethod("op_Explicit");
   2: var expr = Expression.Convert(Expression.Constant("foo"), typeof(Foo), mi);

Unfortunately no luck here as well: it throws exception “The operands for operator 'Convert' do not match the parameters of method 'op_Explicit'”.

If you will try to get op_Explicit using Foo type:

   1: var mi = typeof (Foo).GetMethod("op_Explicit");

you will again get “No coercion operator is defined between types 'System.String' and 'Foo'”” error. The same behavior exist both in .Net 3.5 and 4.0. This problem looks like a bug in expression trees.

Tuesday, October 25, 2011

VMWare became slow on SSD

Some time ago I faced with strange problem: I have SSD with 200 Gb, 16 Gb of memory and 8 CPUs. Who works with Sharepoint knows that it is not so big for development :) Also I use VMWare for development. Everything was fine until someday my host computer was hang. After that virtual machine became very slow. It used 12 Gb and 6 CPUs, so I suspected hard drive (Task manager also showed that there were many unused resources). However disk usage was also not very extensive.

I stopped all services, including Sql server which used IO operations very intensively. It didn’t help. Also I reinstalled VMWare tools – no luck also. I tried to defragment disks on VMWare guest OS, via VMWare workstation, also tried defragment disk on the host – without viewable effect. Tried to restart host without success.

Then I scheduled Check disk for the host OS (for guest it didn’t help). After restarting when Check disk finished work I started VMWare – and fortunately it helped. Virtual machine became much more faster (even faster before hang). This was strange keeping in mind that chkdsk utility didn’t show any errors or warnings – just regular traces. Anyway if you will face with similar problem try to do the same, hope it will help you as well.

Wednesday, October 19, 2011

Taxonomy Update Scheduler triggers list item event receivers in TaxonomyHiddenList

Update 2011-11-23: originally this post was written under impression (and it was confirmed by tests) that event receivers are triggered for any custom list which has managed metadata fields. However today my colleague found that event receiver is triggered only in TaxonomyHiddenList, but not on the exact supplier custom lists. The reason why my tests worked – is because event receiver was provisioned using elements manifest to all lists with specified list template id = 100 (custom lists). And guess what list template id is used for TaxonomyHiddenList – yes exactly the same 100. So my event receiver was triggered not for the custom list, but for TaxonomyHiddenList itself (it is enough to trace title of the parent list in the debugger to see it). Fortunately – it was also Ok for our case, because based on this information we also were able to determine what term from what term set was changed and force Update event on the lists items which contain this term. So everything what is wrote below is correct, but with assumption that it says about TaxonomyHiddenList only.

Taxonomy Update Scheduler is OTB Sharepoint timer job which synchronizes changes from Term store into Sharepoint web site. This timer jobs pushes changes from the Term store into TaxonomyHiddenList (list which contains all used managed metadata in the site). Here is the good explanation of the internal mechanisms in Sharepoint taxonomy.

As you probably know you can’t use managed metadata as lookup column when add lookup field into the Sharepoint. In our case data was stored in term store, but we also needed to create lookup column on this data in list A into another list B (managed metadata field was not the only one column in the list A – there were several fields, that’s why we needed to use lookup and couldn’t add managed metadata to the list B directly). As workaround we added plain text column and updated value in this column via custom item event receiver in ItemUpdated event.

There was one problem with this solution: customers wanted to update data only in one place (term store). After that changes should be automatically propagated into the custom list (into text field). As I already said, changes are not propagated from term store into Sharepoint site immediately. It is done by Taxonomy Update Scheduler timer job. Testing showed that Taxonomy Update Scheduler triggers our custom item event receivers (and it was completely ok for us).

For testing you can use simple event receiver which logs all events:

   1: public class EventReceiver1 : SPItemEventReceiver
   2: {
   3:     public static object lockObj = new object();
   4:  
   5:     private void log(SPItemEventProperties p)
   6:     {
   7:         lock (lockObj)
   8:         {
   9:             var version = p.ListItem.Versions[0];
  10:             File.AppendAllText("c:/temp/log_events.txt", string.Format("{0}:\t{1}\t{2}\t{3}\t{4}{5}",
  11:                 DateTime.Now, new StackTrace().GetFrame(1).GetMethod().Name,
  12:                 version.Level, version.VersionId, version.VersionLabel, Environment.NewLine));
  13:         }
  14:     }
  15:  
  16:    public override void ItemAdding(SPItemEventProperties p) { log(p); }
  17:    public override void ItemUpdating(SPItemEventProperties p) { log(p); }
  18:    public override void ItemDeleting(SPItemEventProperties p) { log(p); }
  19:    public override void ItemCheckingIn(SPItemEventProperties p) { log(p); }
  20:    public override void ItemCheckingOut(SPItemEventProperties p) { log(p); }
  21:    public override void ItemUncheckingOut(SPItemEventProperties p) { log(p); }
  22:    public override void ItemFileMoving(SPItemEventProperties p) { log(p); }
  23:    public override void ItemAdded(SPItemEventProperties p) { log(p); }
  24:    public override void ItemUpdated(SPItemEventProperties p) { log(p); }
  25:    public override void ItemDeleted(SPItemEventProperties p) { log(p); }
  26:    public override void ItemCheckedIn(SPItemEventProperties p) { log(p); }
  27:    public override void ItemCheckedOut(SPItemEventProperties p) { log(p); }
  28:    public override void ItemUncheckedOut(SPItemEventProperties p) { log(p); }
  29:    public override void ItemFileMoved(SPItemEventProperties p) { log(p); }
  30: }

Also we will need term set for testing:

image

Now lets create new item in the custom list with this event receiver and tag it with “English” language:

image

Then go back to the Term store and change “English” term to “English UK”:

image

If you will go to the default list view and refresh it, you will see that it will still have “English” tag. Then go to Central Administration > Job Definitions and force run of Taxonomy Update Scheduler job. After that field will have “English UK”:

image

Now let’s check log_events.txt file:

 

19.10.2011 20:24:50:    ItemAdded    Published    512    1.0

// item was added

 
 

10/19/2011 8:25:32 PM:    ItemUpdating    Published    512    1.0
10/19/2011 8:25:32 PM:    ItemUpdated    Published    512    1.0

// item was updated by Taxonomy Update Scheduler: "English" term was changed to "English UK"

 

As you can see ItemUpdating and ItemUpdated events were triggered when we changed term name automatically.

Friday, October 14, 2011

Support of Scandinavian characters in Sharepoint URLs

Often on the forms or on the work people ask me about whether or not Scandinavian characters (‘ä, ö, Ã¥) are supported in Sharepoint URLs. In order to have reference for the answer I decided to write it in this post.

Mentioned characters belong to so-called high-ASCII characters set (http://www.lorem.biz/htmlcodes.asp - characters with codes from 128 to 256). According to the technet article Sharepoint supports them, but URL should be encoded when you access resources with such symbols:

“If you have non-standard ASCII characters, such as high-ASCII or double-byte Unicode characters, in the SharePoint URL, each of those characters is URL-encoded into two or more ASCII characters when they are passed to the Web browser. Thus, a URL with many high-ASCII characters or double-byte Unicode characters can become longer than the original un-encoded URL.”

Also it is important to note that article says that “SharePoint Foundation 2010 adheres to the standards for URL encoding that are defined in The Internet Engineering Task Force (IETF) RFC 3986”.

Another useful link regarding Sharepoint URLs is Information about the characters that you cannot use in sites, folders, and files in SharePoint.

But of course as always in Sharepoint even if documentation says that it should work – it is not 100% guarantee that it will work in all cases. E.g. somewhere in internals of Sharepoint 2007 I found comment made by MS developer that in this place URLs should always contain only Latin symbols (it was in some of the doclib schema. I will update this post when will remember what exactly place it was).

My recommendation is that if possible it is better to avoid using of localized URLs with non-Latin symbols. Although it might have good impact for SEO (e.g. your pages will be shown in the search result made on local languages), you may face with not very pleasant issues during development.

Tuesday, October 11, 2011

Fixing error “The binary operator LessThan is not defined for the types 'Type1' and 'Type2'”

During the working over next version of Camlex.NET library we encountered with the interesting problem: when we tried to construct LessThan expression for our types the following exception was thrown:

The binary operator LessThan is not defined for the types 'System.Object' and 'SomeType'.

SomeType here is the inheritor of the class where operation “<” is defined. But at the same time there is no explicitly defined operator “<” in SomeType it self. Nevertheless it allows you to write the following correct C# code:

   1: class BaseType
   2: {
   3:     public static bool operator <(object c1, BaseType c2) { return false; }
   4:     public static bool operator >(object c1, BaseType c2) { return false; }
   5: }
   6:  
   7: class SomeType : BaseType
   8: {
   9: }
  10:  
  11: ...
  12:  
  13: var o = new object();
  14: var c = new DataTypes.Text();
  15: bool b = o < c;

This code is successfully compiled and executed, i.e. operator “<” is called for operands of object and SomeType types. However if you will try to construct LessThan expression with left operand of object type and right operand of SomeType type (using Expression.LessThan method), you will get the mentioned exception. If you will use right operand of type BaseType, expression will be constructed correctly. Also you can define operators “<” and “>” directly in SomeType (and use SomeType as 2nd parameter) – expression will also be created. Seems like Expression.LessThan doesn’t search for operators defined in base classes. Instead it searches only in specified class itself (thanks to Vladimir who found the problem).

However there is more elegant solution for the problem which doesn’t require changing of the code. It was crucial for us because as I said we faced with this issue when working on Camlex where we needed to construct expressions like this:

   1: x => x["Foo"] > (DataTypes.Integer)123

x has SPListItem type which has several indexers, one of them receives string as parameter and returns object. Here is more realistic test:

   1: public class BaseFieldType
   2: {
   3:     public static explicit operator BaseFieldType(string s) { return null; }
   4: }
   5:  
   6: public class BaseFieldTypeWithOperators : BaseFieldType
   7: {
   8:     public static bool operator <(object c1, BaseFieldTypeWithOperators c2) { return false; }
   9:     public static bool operator >(object c1, BaseFieldTypeWithOperators c2) { return false; }
  10: }
  11:  
  12: public class StringBasedFieldType : BaseFieldTypeWithOperators
  13: {
  14:     public bool Contains(string text) { return true; }
  15:     public bool StartsWith(string text) { return true; }
  16: }
  17:  
  18: public static class DataTypes
  19: {
  20:     public class Text : StringBasedFieldType
  21:     {
  22:     }
  23: }
  24:  
  25: public class SPListItem
  26: {
  27:     public object this[string s] { get { return null; } }
  28: }
  29:  
  30: class Program
  31: {
  32:     static void Main(string[] args)
  33:     {
  34:         var mi = typeof(SPListItem).GetProperty("Item",
  35:             typeof(object), new[] { typeof(string) }, null).GetGetMethod();
  36:         var left =
  37:                 Expression.Call(
  38:                     Expression.Parameter(typeof(SPListItem), "x"),
  39:                     mi, new[] { Expression.Constant("foo") });
  40:  
  41:  
  42:         var right = Expression.Convert(Expression.Convert(Expression.Constant("foo"),
  43:             typeof(BaseFieldType)), typeof(DataTypes.Text));
  44:  
  45:         var expr = Expression.LessThan(left, right);
  46:     }
  47: }

This code fails because on left operand passed on the line 48 has type object, and right operand has type DataTypes.Text which is subclass of BaseFieldTypeWithOperators and which doesn't has explicitly defined operators in it.

Solution is quite simple: you should use overridden version of Expression.LessThan method which receives 4 parameters:

   1: BinaryExpression LessThan(Expression left, Expression right, bool liftToNull, MethodInfo method)

In last parameter you should specify MethodInfo variable which represents operator “<” from the base class. I.e. the previous example will look like this:

   1: class Program
   2: {
   3:     static void Main(string[] args)
   4:     {
   5:         var mi = typeof(SPListItem).GetProperty("Item",
   6:             typeof(object), new[] { typeof(string) }, null).GetGetMethod();
   7:         var left =
   8:                 Expression.Call(
   9:                     Expression.Parameter(typeof(SPListItem), "x"),
  10:                     mi, new[] { Expression.Constant("foo") });
  11:  
  12:  
  13:         var right = Expression.Convert(Expression.Convert(Expression.Constant("foo"),
  14:             typeof(BaseFieldType)), typeof(DataTypes.Text));
  15:  
  16:  
  17:         var info = typeof(BaseFieldTypeWithOperators).GetMethod("op_LessThan");
  18:  
  19:         var expr = Expression.LessThan(left, right, false, info);
  20:     }
  21: }

Difference is in lines 17-19: at first we get reference to operator “<” (op_LessThan) and after that we pass it into Expression.LessThan() method. After this expression will be successfully created.