Thursday, March 8, 2012

Cannot use anonymous methods inside SQLCLR...

Hi all,

The problem is: when you're trying to call in method MyMethod anonymous method that doesn't use local variables, deployment of the assembly will fail referring that MyMethod tries to store smth. in the static variable. Indeed, looking at the compiled CLR code, you can see that anonymous delegate is cached in the private static delegate and the call looks like:

If(ClassName.privateStaticDelegate == null)
ClassName.privateStaticDelegate = new MyDelegate(HiddenMethodName);
CallAnonymousMethod(ClassName.privateStaticDelegate);

Is there any workaround to fix this problem.

P.S. I googled about this problem and found only one article on it:
http://www.ayende.com/Blog/default,date,2005-12-26.aspx

Hi Almaz,

I'm not quite sure I understand the question, but we're pretty picky about statics in SAFE and EXTERNAL ACCESS assemblies. They should be okay if they're readonly or const, but otherwise not.

Cheers,

-Isaac

|||

Hi Isaac,

Here is the repro: Create a new SQL Server Project, add a following stored procedure and try to deploy the assembly:

using System;
using Microsoft.SqlServer.Server;
public partial class StoredProcedures
{
[SqlProcedure]
public static void StoredProcedure1()
{
int[] myIntArray = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
int i = Array.FindIndex(myIntArray, delegate (int value)
{
return value == 5;
});
}
}

Following variant works:

using System;
using Microsoft.SqlServer.Server;
public partial class StoredProcedures
{
[SqlProcedure]
public static void StoredProcedure1()
{
int[] myIntArray = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
int valueToFind = 5;
int i = Array.FindIndex(myIntArray, delegate (int value)
{
return value == valueToFind;
});
}
}

Thanks in advance,
Sergei Almazov

|||

Right, the problem is that we don't allow store into a static field. In this case, the store was an optimization by the C# compiler. We have a requirement that whenever compiler does this, it should mark the static field with [System.Runtime.CompilerServices.CompilerGenerated] attribute. Apparently, this didn't happen here.

There are two possible workarounds here:

1) mark the class with [System.Runtime.CompilerServices.CompilerGenerated] attribute

2) register the assembly as UNSAFE assembly.

We will follow up with C# compiler and fix the issue, so you can remove your workaround in the future.

-Xiaowei

No comments:

Post a Comment