I am trying to test the functionality of CLR Functions in SQL Server 2012. I found a tutorial online on how to basically do this and got it to work on my server.(https://www.skylinetechnologies.com/Blog/Skyline-Blog/March-2013/CLR-Functions-in-SQL-Server-A-Tutorial)
Now, i wanted to create a function that doesnt return a table but a string instead. In my understanding, the SQL Server needs some kind of object to work with, so i tried it with the following test method:
public static class TestSingleValue
{
[SqlFunction(DataAccess = DataAccessKind.None, FillRowMethodName = "MyFillRowMethod", IsDeterministic = true)]
public static SqlChars Test123()
{
SqlChars test = new SqlChars("teststring");
return test;
}
}
On the SQL server, i did the following:
ALTER ASSEMBLY ClassLibrary2 from 'D:\SQL\TestCLR\ClassLibrary2.dll' with Permission_set = SAFE
CREATE FUNCTION TestCLR()
returns nvarchar(max)
AS
EXTERNAL name ClassLibrary2.[CLRTest.TestSingleValue].Test123
GO
Execute TestCLR
The SQL Server throws an error when executing the test method, saying that an "Object reference not set to an instance of an object" and further:
System.NullReferenceException:
System.Data.SqlServer.Internal.ClrLevelContext.GetCurrentContextForLobAccess(>>CClrLobContext* pLobContext)
System.Data.SqlServer.Internal.ClrLevelContext.GetXvarWlobStream(CXVariantBasepxvarSource, XvarLOBStreamInitCode eCode, Int64 lcid, SqlCompareOptions compareOpts, CClrLobContext pLobContext).
Can anyone tell me where i got the concept wrong or maybe provide a link to a good tutorial? I couldnt find one until now. Thanks in advance.
Ok i found the answer myself, the problem is with "nvarchar(max)" as return type. You got to define a length to the nvarchar or use a workaround, then it works just fine.
Related: How to create CLR stored procedure with Nvarchar(max) parameter?
Related
I have a PoC to use some existing Java-codebase in some UWP-app using the most current Visual Studio Community 19 version 16.3.2 and the latest released IKVM 8.1.7195.0. The app builds and runs fine in Debug-mode, but fails to build already in Release-mode with the following error:
MCG0004:InternalAssert Assert Failed: ICE: trying to add a local var
with the same name, but different types. during
[_RegisterClipboardFormat] Ams.Oms.Poc
RegisterClipboardFormat is part of IKVM:
#DllImportAttribute.Annotation(value = "user32.dll", EntryPoint = "RegisterClipboardFormat")
private native static int _RegisterClipboardFormat(String format);
#cli.System.Security.SecuritySafeCriticalAttribute.Annotation
private static int RegisterClipboardFormat(String format)
{
return _RegisterClipboardFormat(format);
}
https://github.com/ikvm-revived/ikvm/blob/master/openjdk/sun/awt/IkvmDataTransferer.java#L95
What I'm wondering is which local variable the error message is referring to? Might be something added implicitly or might have to do with String in Java vs. string in C#? OTOH that file is clearly named .java.
Didn't find much about the error message in general, only the following two links seems to be more interesting:
Variables having same name but different type
Why doesn't C# allow me to use the same variable name in different scopes?
So I'm currently even unsure where the message comes from, Visual Studio/C# directly or IKVM during running code during building Release-mode. I strongly suspect the error is coming from Visual Studio/C#, though.
Searching for the function itself doesn't reveal much of help as well:
Sorry, AWT is not a supported part of IKVM.
https://sourceforge.net/p/ikvm/bugs/225/
Others seemed to have the same problem, because CN1 simply disabled that code entirely in their fork of IKVM:
//#DllImportAttribute.Annotation(value = "user32.dll", EntryPoint = "RegisterClipboardFormat")
//private native static int _RegisterClipboardFormat(String format);
#cli.System.Security.SecuritySafeCriticalAttribute.Annotation
private static int RegisterClipboardFormat(String format)
{
throw new Error("Not implemented");
//return _RegisterClipboardFormat(format);
}
https://github.com/ams-ts-ikvm/cn1-ikvm-uwp/blob/master/openjdk/sun/awt/IkvmDataTransferer.java#L95
Any ideas? Thanks!
There seems to be a workaround by not changing any code at all: The settings of the Release-build contain a checkbox if to use the .NET native toolbox for the build, which is enabled by default. By disabling that the build succeeds without any code change and is as fast as the Debug-build again. Before changing that, the Release-build took a lot longer as well.
Don't know what that means regarding actually calling native code, if that fails or not, because my app doesn't use those. I guess it would fail, depending on if it works in Debug or not. Additionally, I'm not sure if the Windows store accepts such a modified Release-build, but as UWP-apps aren't forced to use native code at all, I guess there's a good chance things are going to work.
I have the simplest of apps that I thought I would try on my device before I got too engrossed. However, I am getting the strangest error message when I run it on my iPhone (as apposed to the the emulator on my macbook).
Table has no (public) columns .
I am using the SQLite.Net PCL and I have built it from git hub as I had some problems with it not having the platform dlls for IOS otherwise.
Relevant code.
In my models I have this:
public class Setting
{
[PrimaryKey, AutoIncrement]
public long Id { get; set; }
[Indexed]
public string Key { get; set; }
public string Value { get; set; }
}
The code that throws this error message is the simple:
using (SQLiteConnection db = GetCon ()) {
db.CreateTable<Setting> ();
}
but in my opinion the strangest thing is that this code works fine on the emulator but crashes the application on the iphone itself.
If anyone has some ideas that would be great.
EDIT:
This error is thrown on the SQLite.Net-PCL library on this file line 380 but only on the device and not on the emulator.
For others to whom this may concern, I found the answer to my problem. The issue was with the Type not having any properties (the type in question the simple model class). Knowing that to be rubbish I found the following links that gave more information which I will relate in this post in case the links go dead:
Type.GetProperties returning nothing
NOTE: Be careful with assembly linker
If you're building with linker enabled you may need to use the class
somewhere, so it will not be ripped off at compile time. Sometimes,
only instantiating the class in your code is not enough, the linker
may detect that the instance is never used and will remove it anyway.
http://developer.xamarin.com/guides/ios/advanced_topics/linker/
The linking process can be customized via the linker behavior
drop-down in Project Options. To access this double-click on the iOS
project and browse to iOS Build > Linker Options, as illustrated below
(see link for details)
I have for now left it to be unlinked, however, I will try before release to get the linker to ignore these classes. Thanks for all your help.
I found my problem was just a (not that subtle) programming error. I was working with the TypeInfo class and wanted to use the Sqlite Connection method:
CreateTable (Type type);
What I had in my hand was a TypeInfo instance which I needed to convert back to the System.Type. I accidentally without thinking used the GetType() method instead of AsType() method which is obvious when you think about it. The clue I got was in the exception message along with the OP message was does System.Runtime have public properties?
var type = table.TypeInfo.AsType();
// var type = table.TypeInfo.GetType(); *WRONG*
connection.CreateTable(type);
I needed to make a change to my webAPI service and what happened was I lost my project files. I had the dll file so I decompiled the file and got my code back. When I tried to build the solution I got an error.
Can anyone tell me why am I getting this error?
The reference to Microsoft.Practices.EnterpriseLibrary.Data exist in my code.
I could not find what is it that causes the error.
The error occurs on the line:
DbCommand dbCommand = databaseObject.get_DbProviderFactory().CreateCommand();
The DatabaseObject type has a property for DbProviderFactory, something like:
public DbProviderFactory DbProviderFactory { get; set; }
In C# properties are compiled to a backing field and a get_Foo() and set_Foo() method. What you're seeing is the decompiled get accessor.
You can change it back to a property access instead of a method call:
DbCommand dbCommand = databaseObject.DbProviderFactory.CreateCommand();
This is also explained in among others get form proterty `cannot explicitly call operator or accessor` and Unable to run Console Application in c#. And please start using version control to prevent the loss of source code.
I migrated Mining Structures from a 2008 server to a 2012 server. When I try my CLR UDF (which is working fine on SQL server 2008) in a DMX query on the 2012 server, I am getting this error:
Exception has been thrown by the target of an invocation. Object reference not set to an instance of an object.
My original goal was to get the GetNodeDescription(...) method running. While debugging the problem, I could isolate the problem to this UDF which fails on my SQL server 2012
[SafeToPrepare(true)]
public static string test()
{
return Context.CurrentMiningModel.Name;
}
My guess is that CurrentMiningModel is null because the following code works fine
[SafeToPrepare(true)]
public static string testUser()
{
return Context.CurrentConnection.User.Name;
}
Any Idea on how to solve this?
Is somebody out there who can reproduce this?
Thanks.
Jan
UPDATE:
A contact at Microsoft confirmed this behaviour as desired due to a "Metadata-Refactoring" (whatever this means...). However, the website still pends to be updated appropiately.
This is not the ultimate answer but it's a workaround to get Microsoft's GetNodeDescription working (by explicitly providing the mining model):
[SafeToPrepare(true)]
public static string GetNodeDescription(string MiningModel, string nodeUniqueName)
{
if (Context.ExecuteForPrepare)
{
return string.Empty;
}
return Context.MiningModels[MiningModel].GetNodeFromUniqueName(nodeUniqueName).Description;
}
I am trying to run the CREATE ASSEMBLY command for a SQL CLR (.Net 3.5) assembly on SQL Server 2008. It returns a cryptic error message:
An error occurred while gathering metadata from assembly 'My.Awesome.Assembly' with HRESULT 0x80004005.
Why is it doing this, and how can I fix it without deploying it as UNSAFE?
steps I have done:
Followed all rules in http://msdn.microsoft.com/en-us/library/ms403273.aspx
Used no static fields
Have created 2 other SQL CLR assemblies that deploy just fine
This is what solved the problem for me; for future reference to anyone out there, SQL CLR stuff is very, very picky.
I had a constructor like this:
public MyObject(IEnumerable<T> items)
{
_innerItems = items.ToDictionary(i => i.Key);
}
I changed it to this:
public MyObject(IEnumerable<T> items)
{
_innerItems = new Dictionary<int, T>();
foreach (var item in items)
{
_innerItems.Add(item.Key, item);
}
}
And it was then able to deploy. I then proceeded to pound my head against my desk. Two methods, functionally equivalent; one works, and one has a cryptic deployment error message.