Skip to content

.NET Core 2.1, SQL Server, UDT type, Exception: UdtTypeName property must be set for UDT parameters. #1349

Closed
@JechoJekov

Description

I am trying to use the spatial types in the Unofficial.Microsoft.SqlServer.Types package. The following error occurs when trying to use an SqlGeography or SqlGeometry value in a query:

System.ArgumentException
  HResult=0x80070057
  Message=UdtTypeName property must be set for UDT parameters.
  Source=System.Data.SqlClient
  StackTrace:
   at System.Data.SqlClient.SqlParameter.Validate(Int32 index, Boolean isCommandProc)
   at System.Data.SqlClient.SqlCommand.BuildParamList(TdsParser parser, SqlParameterCollection parameters)
   at System.Data.SqlClient.SqlCommand.BuildExecuteSql(CommandBehavior behavior, String commandText, SqlParameterCollection parameters, _SqlRPC& rpc)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite, String methodName)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at LinqToDB.Data.DataConnection.ExecuteNonQuery()
   at LinqToDB.Linq.QueryRunner.NonQueryQuery(Query query, IDataContext dataContext, Expression expr, Object[] parameters)
   at LinqToDB.Linq.QueryRunner.<>c__DisplayClass28_0.<SetNonQueryQuery>b__0(IDataContext db, Expression expr, Object[] ps)
   at LinqToDB.Linq.ExpressionQuery`1.System.Linq.IQueryProvider.Execute[TResult](Expression expression)

linq2db correctly sets SqlParameter.SqlDbType to Udt and SqlParameter.TypeName to Geography, however, it does not set SqlParameter.UdtTypeName which causes the exception. The reason is the following code from the SqlServerDataProvider class:

https://github.com/linq2db/linq2db/blob/master/Source/LinqToDB/DataProvider/SqlServer/SqlServerDataProvider.cs

case DataType.Udt        :
	{
		string s;
		if (value != null && _udtTypes.TryGetValue(value.GetType(), out s))
			if (parameter is SqlParameter)
#if NETSTANDARD1_6 || NETSTANDARD2_0
				((SqlParameter)parameter).TypeName = s;
#else
				((SqlParameter)parameter).UdtTypeName = s;
#endif

	}

Steps to reproduce

I used SqlServerTools.AddUdtType to register the types before opening a connection.

SqlServerTools.AddUdtType<SqlGeography>("Geography", null, LinqToDB.DataType.Udt);
SqlServerTools.AddUdtType<SqlGeometry>("Geometry", null, LinqToDB.DataType.Udt);

using (var db = new Database(...))
{
    var value = new SqlGeographyBuilder();
    value.BeginGeography(OpenGisGeographyType.Point);
    value.AddLine(1, 1);
    value.EndGeography();

    db.GeoValues
        .Where(x => x.Id == -1)
        .Set(x => x.Position, value.ConstructedGeography)
        .Update();
}

Environment details

linq2db version: 2.4.0
Database Server: SQL Server 2016
Database Provider: Any SQL Server provider
Operating system: Windows 10
Framework version: .NET Core 2.1

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions