SqlServer nvarchar(max) AddScalarType
See original GitHub issueHi! Linq2db generate invalid SQL for user type (registered with AddScalarType function) columns with db type ‘nvarchar(max)’ ( Parameter Length is 4000 ) User Type:
[Serializable]
public class UserType: IConvertible
{
public string StringProperty{ get; set; }
public int IntProperty{ get; set; }
public UserType()
{
}
public UserType(string stringProperty, int intProperty)
{
this.StringProperty = stringProperty;
this.IntProperty = intProperty;
}
public static UserType CreateFromString(string xml)
{
if(string.IsNullOrEmpty(xml))
{
return null;
}
var reader = new XmlSerializer(typeof(UserType));
using(var sr = new StringReader(xml))
{
return (UserType)reader.Deserialize(sr);;
}
}
public static string ConvertToString(UserType item)
{
if(item == null)
{
return null;
}
var writer = new XmlSerializer(typeof(UserType));
var sb = new StringBuilder();
using(var sw = new StringWriter(sb, CultureInfo.InvariantCulture))
{
using(var xw = XmlWriter.Create(sw, new XmlWriterSettings(){OmitXmlDeclaration = true,NewLineHandling =NewLineHandling.Entitize,Indent =false}))
{
var ns = new XmlSerializerNamespaces();
ns.Add(string.Empty, string.Empty);
writer.Serialize(xw, item, ns);
return sb.ToString();
}
}
}
string IConvertible.ToString(IFormatProvider provider)
{
var str = ConvertToString(this);
return str;
}
object IConvertible.ToType(Type conversionType, IFormatProvider provider)
{
if(conversionType == typeof(string))
{
var str = ConvertToString(this);
return str;
}
return Convert.ChangeType(this, conversionType, provider);;
}
TypeCode IConvertible.GetTypeCode()
{
return TypeCode.Object;
}
bool IConvertible.ToBoolean(IFormatProvider provider)
{
throw new NotImplementedException();
}
char IConvertible.ToChar(IFormatProvider provider)
{
throw new NotImplementedException();
}
sbyte IConvertible.ToSByte(IFormatProvider provider)
{
throw new NotImplementedException();
}
byte IConvertible.ToByte(IFormatProvider provider)
{
throw new NotImplementedException();
}
short IConvertible.ToInt16(IFormatProvider provider)
{
throw new NotImplementedException();
}
ushort IConvertible.ToUInt16(IFormatProvider provider)
{
throw new NotImplementedException();
}
int IConvertible.ToInt32(IFormatProvider provider)
{
throw new NotImplementedException();
}
uint IConvertible.ToUInt32(IFormatProvider provider)
{
throw new NotImplementedException();
}
long IConvertible.ToInt64(IFormatProvider provider)
{
throw new NotImplementedException();
}
ulong IConvertible.ToUInt64(IFormatProvider provider)
{
throw new NotImplementedException();
}
float IConvertible.ToSingle(IFormatProvider provider)
{
throw new NotImplementedException();
}
double IConvertible.ToDouble(IFormatProvider provider)
{
throw new NotImplementedException();
}
decimal IConvertible.ToDecimal(IFormatProvider provider)
{
throw new NotImplementedException();
}
DateTime IConvertible.ToDateTime(IFormatProvider provider)
{
throw new NotImplementedException();
}
}
Table Class:
[Table(Name = "Table1")]
public class Table1
{
[Column(DataType = DataType.Int32)]
[PrimaryKey]
[Identity]
public int Id{ get; set; }
[Column(CanBeNull = true, DataType = DataType.NVarChar, Length = int.MaxValue)]
[Nullable]
public UserType UserTypeColumn{ get; set; }
}
Connection Class:
public class TestDbConnection: DataConnection
{
static TestDbConnection()
{
var mapping = MappingSchema.Default;
mapping.AddScalarType(typeof(UserType), DataType.NVarChar);
mapping.SetConvertExpression<string, UserType>(arg => UserType.CreateFromString(arg));
mapping.SetConvertExpression<UserType,string>(arg => UserType.ConvertToString(arg));
}
public TestDbConnection()
: base(SqlServerTools.GetDataProvider(SqlServerVersion.v2012), GetConnectionString())
{
TurnTraceSwitchOn();
WriteTraceLine = this.WriteSql;
}
private void WriteSql(string arg1, string arg2)
{
Debug.WriteLine(arg1, arg2);
}
public ITable<Table1> Table1{ get{ return this.GetTable<Table1>(); } }
private static string GetConnectionString()
{
// return you connection string
}
}
Test Project:
class Program
{
static void Main(string[] args)
{
try
{
using(var connection = new TestDbConnection())
{
var value1 = new UserType(new string('0',10),1);
connection.Table1.Insert(() =>new Table1() { UserTypeColumn = value1});
var value2 = connection.Table1.OrderByDescending(table1 => table1.Id).Select(table1 => table1.UserTypeColumn).First();
Debug.Assert(value1.IntProperty==value2.IntProperty);
Debug.Assert(value1.StringProperty==value2.StringProperty);
Console.WriteLine("Test1 passed...");
value1 = new UserType(new string('0',4001),1);
connection.Table1.Insert(() =>new Table1() { UserTypeColumn = value1});
value2 = connection.Table1.OrderByDescending(table1 => table1.Id).Select(table1 => table1.UserTypeColumn).First();
Debug.Assert(value1.IntProperty==value2.IntProperty);
Debug.Assert(value1.StringProperty==value2.StringProperty);
Console.WriteLine("Test2 passed...");
}
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.WriteLine("Press any key...");
Console.ReadKey(false);
}
}
Debug Output:
– SqlServer.2012 DECLARE @value1 NVarChar(4000) – String <— always 4000! SET @value1 = linq2dbTest.UserType <— better show result from Convert function!
INSERT INTO [Table1] ( [UserTypeColumn] ) VALUES ( @value1 )
Thank you!!!
Environment details
linq2db version: 2.6.3 Database Server: MS Sql Server 2017 Framework version: .NET Framework 4.6.1
Issue Analytics
- State:
- Created 5 years ago
- Comments:11 (5 by maintainers)
Top Results From Across the Web
What is the maximum characters for the NVARCHAR(MAX)?
The max size for a column of type NVARCHAR(MAX) is 2 GByte of storage. Since NVARCHAR uses 2 bytes per character, that's approx....
Read more >nchar and nvarchar (Transact-SQL) - SQL Server
max indicates that the maximum storage size is 2^31-1 characters (2 GB). The storage size is two times n bytes + 2 bytes....
Read more >SQL NVARCHAR(Max) Data Type
The NVARCHAR(Max) data type stores variable-length character strings. NVARCHAR(Max) is used to store very large character data. NVARCHAR(Max) can hold as much ...
Read more >Comparing VARCHAR(max) vs VARCHAR(n) data types in ...
This article gives an overview of varchar(max) data type and its comparison with the varchar(n) data type.
Read more >NVARCHAR(MAX) string appears to have 6326 characters ...
1 Answer 1 ... This is a limitation of what can be displayed in the "Messages" tab via either PRINT or RAISERROR ....
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
if (value is string strValue && strValue.Length > 4000)
strValue is null because value is UserType
Thank you!