I wanted to test what would happen with different SQL messages in my app. Based on their error codes, I'd wrap a friendlier message around them and send em on up.
Problem is, SqlException is sealed AND has no public constructors. Great. How the heck do you test that?
This fails.
You'd soon find that throwing native errors from sql doesn't work.
using System;
using System.Data.SqlClient;
using System.Reflection;
using System.Runtime.Serialization;
public class SqlExceptionCreator
{
public static SqlException CreateSqlException(string errorMessage, int errorNumber)
{
SqlErrorCollection collection = GetErrorCollection();
SqlError error = GetError(errorNumber, errorMessage);
MethodInfo addMethod = collection.GetType().GetMethod("Add", BindingFlags.NonPublic | BindingFlags.Instance);
addMethod.Invoke(collection, new object[] { error });
SerializationInfo info = new SerializationInfo(typeof(SqlException), new FormatterConverter());
info.AddValue("Errors", collection, typeof(SqlErrorCollection));
info.AddValue("ClassName",typeof(SqlException).ToString());
info.AddValue("Message", errorMessage);
info.AddValue("InnerException", null);
info.AddValue("LineNumber",1);
info.AddValue("Procedure","procedure");
info.AddValue("Server","server");
info.AddValue("Source","src");
info.AddValue("State",0);
info.AddValue("HelpURL",null);
info.AddValue("StackTraceString",null);
info.AddValue("RemoteStackTraceString", null);
info.AddValue("RemoteStackIndex", 0);
info.AddValue("ExceptionMethod", null);
info.AddValue("HResult", 1);
info.AssemblyName = "System.Data";
Type[] types = new Type[] { typeof(SerializationInfo), typeof(StreamingContext) };
ConstructorInfo constructor = typeof(SqlException).GetConstructor( BindingFlags.NonPublic | BindingFlags.Instance, null, types, null);
object[] objects = new object[] { info, null };
SqlException exception = (SqlException)constructor.Invoke(objects);
return exception;
}
private static SqlError GetError(int errorCode, string message)
{
object[] parameters = new object[] { errorCode, (byte)0, (byte)10,"server", message, "procedure", 0 };
Type[] types = new Type[] { typeof(int), typeof(byte), typeof(byte), typeof(string), typeof(string), typeof(string), typeof(int) };
ConstructorInfo constructor = typeof(SqlError).GetConstructor( BindingFlags.NonPublic | BindingFlags.Instance, null, types, null);
SqlError error = (SqlError)constructor.Invoke(parameters);
return error;
}
private static SqlErrorCollection GetErrorCollection()
{
ConstructorInfo constructor = typeof(SqlErrorCollection).GetConstructor( BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { }, null);
SqlErrorCollection collection = (SqlErrorCollection)constructor.Invoke(new object[] { });
return collection;
}
}