I'm trying to debug a CLR User Defined Type in SQL Server 2014 / Visual Studio 2013. I can deploy my UDT to the database and execute the script that calls that UDT in the debugger from within visual studio but it throws an error and doesn't hit my breakpoint. The error happens in the static Parse method on the type.
My DBA thought it might be a permissions issue (preventing me from debugging, not the underlying error) but didn't have time to look into it. Any suggestions on what I need to do to debug my UDT?
The SQL Server is a local instance
Per request, the code of Parse:
public static SqlQueryDescriptor Parse(SqlString s)
{
if (s.IsNull)
return Null;
var queryDescriptor = new JsonSerializer().Deserialize<QueryDescriptor>(s.Value);
//var queryDescriptor = new QueryDescriptor();
SortContext sort = new SortContext();
if (queryDescriptor.Sorts != null)
{
foreach (var sortDescriptor in queryDescriptor.Sorts)
{
sort.AddSort(sortDescriptor.Property, sortDescriptor.Direction);
}
}
return new SqlQueryDescriptor(sort, queryDescriptor.Filters, queryDescriptor.Page);
}
The error is a NRE in the Json deserialization library, I need to debug to figure out why that is happening as I didn't write that library and imported it from the web. Although the break point still doesn't hit even if I don't use the deserializer (commented out line)
Related
Below is the code to build a cache which stores (typeName,type) found in the assemblies loaded in the current app domain.
I am facing this weird issue when trying to load types from one particular assembly say assemblyK. The assemblyK has around 954 types. Logs are in sync and it works all well when locally hosted in Visual Studio. Also, when I deploy the website in IIS it works well in when the buildCache is called for the first time.
However when the application pool is restarted/ after calling it later, it runs the nested loop for only for 5 types and goes on to execute the next function i.e. it does not throw any exception and moves forward.
private static void BuildCache()
{
Assembly[] assemblies= AppDomain.CurrentDomain.GetAssemblies();
foreach(Assembly assembly in assemblies){
if(assembly.GlobalAssemblyCache){
if(assemblly.ToString().Contains("assemblyK"))
Logger.Log("GAC");
continue;
}
try
{
if(assembly.ToString().Contains("AssemblyK"))
{
string allTypes = string.Join(",",assembly.GetTypes().Select(x => x.ToString()).ToArray())
Logger.Log("All types :{0}",allTypes);
}
foreach(Type type in assembly.GetTypes())
{
if(assembly.ToString().Contains("AssemblyK"))
{
Logger.Log("Type parsed :{0}",type);
}
if(!typeCache.ContainsKey(type.FullName))
{
if(assembly.ToString().Contains("AssemblyK"))
{
Logger.Log("Adding to cache :{0}",type);
}
typeCache.Add(type.FullName,type);
}
}
catch(Exception ex)
{
Logger.Log("Exception Caught : {0}",ex.ToString());
}
}
}
Notably, The AssemblyK.dll build in Visual Studio 2008 in .Net 3.5 version works all well and when complied in Visual Studio 2019 causing the issue. Application Pool is 2.0. And the assemblyK is loaded in the "assemblies" always. Please Help.
P.S.: I copied the logs for allTypes received in both the cases(when it works and doesnt) in two files and did a file compare using cmd, with fc file1 file2.
Both contained the identical data i.e.954 types. So my question is how can the foreach run randomly? What could be the issue here?
Update : The logs read:
1) In Working case :
All Types : Type1,Type2,Type3,..Type954
Type Parsed 954 times
Adding to cache 954 times
2) In Not Working case :
All Types : Type1,Type2,Type3,..Type954.
Type Pased 4 Times.
typeCache is a private static readonly Dictionary
I rarely get an ArrayTypeMismatchException in my program:
public Map(Map otherMap)
{
var cpyArr = new char[otherMap.PlayingField.GetLength(0), otherMap.PlayingField.GetLength(1)];
Array.Copy(otherMap.PlayingField, cpyArr, otherMap.PlayingField.Length);
PlayingField = cpyArr;
var cpyTrans = new List<Transition>();
foreach (var item in otherMap.Transitions)
{
cpyTrans.Add(new Transition(item.X1, item.Y1, item.D1, item.X2, item.Y2, item.D2));
}
Transitions = cpyTrans;
}
The PlayingField property is a twodimensional char array.
Here is the output:
Unhandled Exception: System.ArrayTypeMismatchException: (Types:
source=System.Char; target=System.Char)
The strange thing is that this doesn't happen all the time, just occasionally.
The exception gets thrown at Array.Copy, but the error clearly states that the types actually do match.
How do I fix this?
EDIT: I should also add that the program is being compiled using the current Mono version and run on Linux. But I couldn't reproduce the error on my testing systems. The program is supposed to run on a server system which I sadly have neither access to, nor do I have any information about except that it also runs linux.
The main Problem is completely different, please skip to the Edit
I have an exception of an unknown type which doesn't even get thrown properly. Following Code provides the Context:
MMDataAccess.InitDemoDB();
MMDataAccess.InitInternalDB();
MMDataAccess.InitMaintDB();
try
{
SQLiteToDBLib sqltdbl = new SQLiteToDBLib();
sqltdbl.WriteToSQLite();
}
catch(Exception ex)
{
string message = ex.Message;
}
These are the very first lines of my first Activity in my app. The first 3 lines belong to my very own implementation of an in-memory database and are behaving nicely. The problem rises with the next two lines inside the try-block. The declaration and initalistation of the sqltdbl variable never happens. The constructor of SQLiteToDBLib looks like this:
public SQLiteToDBLib()
{
msc = new MSConnection();
}
The MSConnection class doesn't even have a constructor (except for the default one of course).
As you can see i've tried to catch any exceptions, but without success. everything i can figure out is, that a exception is thrown because of the debugger going into the catch section while ignoring everything that has to do with "ex". Without breakpoints everything seems fine. Just without the call to WriteToSQLite which should create a .sqlite file on the external Memory.
What can I do to resolve this error? Is there anything i can catch except the default Exception?
Edit:
After some testing with commented code something interresting happened. I could step into commented code. Well not exactly the commented code, but the code that was there before my changes. Visual Studio somehow shows me the things, that are changed in the file, but is compiling the old code. Up to now i tried to rebuild, clean and build the project in various combinations, unload and reload the project, Restart Visual Studio and restart Windows. Nothing has changed so far. I Will now proceed to create a new .cs File With the exact same Code. I'm working with VS 2013 Community
add static constructor to your SQLiteToDBLib class and perform all static objects initialization in it:
static SQLiteToDBLib()
{
// initialize static members here
}
If this doesn't give you a clue, try enabling CLRE exceptions-break in visual-studio:
DEBUG
Exceptions
Check the 'Common Language Runtime Exceptions' option (under the 'Thrown' column)
Press OK
Restart your app and try again
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.