static SqlTypes() { // find the latest version of Microsoft.SqlServer.Types assembly that contains Sql spatial types var preferredSqlTypesAssemblies = new[] { "Microsoft.SqlServer.Types, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91", "Microsoft.SqlServer.Types, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91", }; Assembly sqlTypesAssembly = null; foreach (string assemblyFullName in preferredSqlTypesAssemblies) { AssemblyName asmName = new AssemblyName(assemblyFullName); try { sqlTypesAssembly = Assembly.Load(asmName); break; } catch (FileNotFoundException) { } catch (FileLoadException) { } } if (sqlTypesAssembly == null) { throw new InvalidOperationException("Microsoft.SqlServer.Types assembly not found"); } SqlGeographyType = sqlTypesAssembly.GetType("Microsoft.SqlServer.Types.SqlGeography", throwOnError: true); SqlGeometryType = sqlTypesAssembly.GetType("Microsoft.SqlServer.Types.SqlGeometry", throwOnError: true); SqlCharsType = SqlGeometryType.GetMethod("STAsText", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null).ReturnType; SqlStringType = SqlCharsType.Assembly.GetType("System.Data.SqlTypes.SqlString", throwOnError: true); SqlBytesType = SqlCharsType.Assembly.GetType("System.Data.SqlTypes.SqlBytes", throwOnError: true); SqlXmlType = SqlCharsType.Assembly.GetType("System.Data.SqlTypes.SqlXml", throwOnError: true); }
public SqlTypesAssembly(Assembly sqlSpatialAssembly) { // Retrieve SQL Server spatial types and static constructor methods var sqlGeog = sqlSpatialAssembly.GetType("Microsoft.SqlServer.Types.SqlGeography", throwOnError: true); var sqlGeom = sqlSpatialAssembly.GetType("Microsoft.SqlServer.Types.SqlGeometry", throwOnError: true); Debug.Assert(sqlGeog != null, "SqlGeography type was not properly retrieved?"); Debug.Assert(sqlGeom != null, "SqlGeometry type was not properly retrieved?"); SqlGeographyType = sqlGeog; sqlGeographyFromWKTString = CreateStaticConstructorDelegate <string>(sqlGeog, "STGeomFromText"); sqlGeographyFromWKBByteArray = CreateStaticConstructorDelegate <byte[]>(sqlGeog, "STGeomFromWKB"); sqlGeographyFromGMLReader = CreateStaticConstructorDelegate <XmlReader>(sqlGeog, "GeomFromGml"); SqlGeometryType = sqlGeom; sqlGeometryFromWKTString = CreateStaticConstructorDelegate <string>(sqlGeom, "STGeomFromText"); sqlGeometryFromWKBByteArray = CreateStaticConstructorDelegate <byte[]>(sqlGeom, "STGeomFromWKB"); sqlGeometryFromGMLReader = CreateStaticConstructorDelegate <XmlReader>(sqlGeom, "GeomFromGml"); // Retrieve SQL Server specific primitive types var asTextMethod = SqlGeometryType.GetMethod( "STAsText", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null); SqlCharsType = asTextMethod.ReturnType; SqlStringType = SqlCharsType.Assembly.GetType("System.Data.SqlTypes.SqlString", throwOnError: true); SqlBooleanType = SqlCharsType.Assembly.GetType("System.Data.SqlTypes.SqlBoolean", throwOnError: true); SqlBytesType = SqlCharsType.Assembly.GetType("System.Data.SqlTypes.SqlBytes", throwOnError: true); SqlDoubleType = SqlCharsType.Assembly.GetType("System.Data.SqlTypes.SqlDouble", throwOnError: true); SqlInt32Type = SqlCharsType.Assembly.GetType("System.Data.SqlTypes.SqlInt32", throwOnError: true); SqlXmlType = SqlCharsType.Assembly.GetType("System.Data.SqlTypes.SqlXml", throwOnError: true); // Create type conversion delegates to SQL Server types sqlBytesFromByteArray = Expressions.Lambda <byte[], object>("binaryValue", bytesVal => BuildConvertToSqlBytes(bytesVal, SqlBytesType)).Compile(); sqlStringFromString = Expressions.Lambda <string, object>("stringValue", stringVal => BuildConvertToSqlString(stringVal, SqlStringType)).Compile(); sqlCharsFromString = Expressions.Lambda <string, object>("stringValue", stringVal => BuildConvertToSqlChars(stringVal, SqlCharsType)).Compile(); sqlXmlFromXmlReader = Expressions.Lambda <XmlReader, object>("readerVaue", readerVal => BuildConvertToSqlXml(readerVal, SqlXmlType)).Compile(); // Create type conversion delegates from SQL Server types; all arguments are typed as 'object' and require Expression.Convert before use of members of the SQL Server type. // Explicit cast from SqlBoolean to bool sqlBooleanToBoolean = Expressions.Lambda <object, bool>("sqlBooleanValue", sqlBoolVal => sqlBoolVal.ConvertTo(SqlBooleanType).ConvertTo <bool>()). Compile(); // Explicit cast from SqlBoolean to bool? for non-Null values; otherwise null sqlBooleanToNullableBoolean = Expressions.Lambda <object, bool?>( "sqlBooleanValue", sqlBoolVal => sqlBoolVal.ConvertTo(SqlBooleanType).Property <bool>("IsNull") .IfTrueThen(Expressions.Null <bool?>()) .Else(sqlBoolVal.ConvertTo(SqlBooleanType).ConvertTo <bool>().ConvertTo <bool?>())).Compile(); // SqlBytes has instance byte[] property 'Value' sqlBytesToByteArray = Expressions.Lambda <object, byte[]>( "sqlBytesValue", sqlBytesVal => sqlBytesVal.ConvertTo(SqlBytesType).Property <byte[]>("Value")).Compile(); // SqlChars -> SqlString, SqlString has instance string property 'Value' sqlCharsToString = Expressions.Lambda <object, string>( "sqlCharsValue", sqlCharsVal => sqlCharsVal.ConvertTo(SqlCharsType).Call("ToSqlString").Property <string>("Value")). Compile(); // Explicit cast from SqlString to string sqlStringToString = Expressions.Lambda <object, string>( "sqlStringValue", sqlStringVal => sqlStringVal.ConvertTo(SqlStringType).Property <string>("Value")).Compile(); // Explicit cast from SqlDouble to double sqlDoubleToDouble = Expressions.Lambda <object, double>( "sqlDoubleValue", sqlDoubleVal => sqlDoubleVal.ConvertTo(SqlDoubleType).ConvertTo <double>()).Compile(); // Explicit cast from SqlDouble to double? for non-Null values; otherwise null sqlDoubleToNullableDouble = Expressions.Lambda <object, double?>( "sqlDoubleValue", sqlDoubleVal => sqlDoubleVal.ConvertTo(SqlDoubleType).Property <bool>("IsNull") .IfTrueThen(Expressions.Null <double?>()) .Else(sqlDoubleVal.ConvertTo(SqlDoubleType).ConvertTo <double>().ConvertTo <double?>())) .Compile(); // Explicit cast from SqlInt32 to int sqlInt32ToInt = Expressions.Lambda <object, int>("sqlInt32Value", sqlInt32Val => sqlInt32Val.ConvertTo(SqlInt32Type).ConvertTo <int>()). Compile(); // Explicit cast from SqlInt32 to int? for non-Null values; otherwise null sqlInt32ToNullableInt = Expressions.Lambda <object, int?>( "sqlInt32Value", sqlInt32Val => sqlInt32Val.ConvertTo(SqlInt32Type).Property <bool>("IsNull") .IfTrueThen(Expressions.Null <int?>()) .Else(sqlInt32Val.ConvertTo(SqlInt32Type).ConvertTo <int>().ConvertTo <int?>())).Compile(); // SqlXml has instance string property 'Value' sqlXmlToString = Expressions.Lambda <object, string>("sqlXmlValue", sqlXmlVal => sqlXmlVal.ConvertTo(SqlXmlType).Property <string>("Value")). Compile(); isSqlGeographyNull = Expressions.Lambda <object, bool>( "sqlGeographyValue", sqlGeographyValue => sqlGeographyValue.ConvertTo(SqlGeographyType).Property <bool>("IsNull")). Compile(); isSqlGeometryNull = Expressions.Lambda <object, bool>( "sqlGeometryValue", sqlGeometryValue => sqlGeometryValue.ConvertTo(SqlGeometryType).Property <bool>("IsNull")).Compile(); geographyAsTextZMAsSqlChars = Expressions.Lambda <object, object>( "sqlGeographyValue", sqlGeographyValue => sqlGeographyValue.ConvertTo(SqlGeographyType).Call("AsTextZM")).Compile(); geometryAsTextZMAsSqlChars = Expressions.Lambda <object, object>( "sqlGeometryValue", sqlGeometryValue => sqlGeometryValue.ConvertTo(SqlGeometryType).Call("AsTextZM")).Compile(); }