internal string Prepare ()
{
string typeName = TypeName;
-
- if (typeName == "varbinary") {
- int size = Size;
+ // Cf. GetDateTimeString
+ TdsColumnType actualType = TdsColumnType.Char;
+ int size;
+
+ switch (typeName) {
+ case "varbinary":
+ size = Size;
if (size <= 0) {
size = GetActualSize ();
}
-
+
if (size > 8000) {
typeName = "varbinary(max)";
}
+ break;
+ case "datetime2":
+ actualType = TdsColumnType.DateTime2;
+ typeName = "char";
+ break;
+ case "datetimeoffset":
+ actualType = TdsColumnType.DateTimeOffset;
+ typeName = "char";
+ break;
}
-
+
string includeAt = "@";
if (ParameterName [0] == '@')
includeAt = "";
case "varchar":
case "varbinary":
//A size of 0 is not allowed in declarations.
- int size = Size;
+ size = Size;
if (size <= 0) {
size = GetActualSize ();
if (size <= 0)
result.Append (paramSize > 0 ? (paramSize > 4000 ? "(max)" : String.Format ("({0})", paramSize)) : "(4000)");
break;
case "char":
+ size = -1;
+ if (actualType != TdsColumnType.Char)
+ size = GetDateTimeStringLength (actualType);
+ else if (isSizeSet)
+ size = Size;
+ if (size > 0)
+ result.Append (String.Format ("({0})", size));
+ break;
case "nchar":
case "binary":
if (isSizeSet && Size > 0)
case "float":
case "money":
return 8;
+ case "datetime2":
+ return GetDateTimeStringLength (TdsColumnType.DateTime2);
+ case "datetimeoffset":
+ return GetDateTimeStringLength (TdsColumnType.DateTimeOffset);
case "int":
case "real":
case "smalldatetime":
return size;
}
+ private int GetDateTimePrecision ()
+ {
+ int precision = Precision;
+
+ // http://msdn.microsoft.com/en-us/library/bb677335.aspx
+ // says that default precision is 7. How do
+ // we distinguish that from zero?
+ if (precision == 0 || precision > 7)
+ precision = 7;
+
+ return precision;
+ }
+
+ private int GetDateTimeStringLength (TdsColumnType type)
+ {
+ int precision = GetDateTimePrecision ();
+ int len = precision == 0 ? 19 : 20 + precision;
+
+ if (type == TdsColumnType.DateTimeOffset)
+ len += 6;
+
+ return len;
+ }
+
+ // HACK: Wire-level DateTime{2,Offset} require TDS
+ // 7.3, which this driver does not implement
+ // correctly--so we serialize to ASCII instead.
+ private string GetDateTimeString (TdsColumnType type)
+ {
+ int precision = GetDateTimePrecision ();
+ string fmt = "yyyy-MM-dd'T'HH':'mm':'ss";
+
+ if (precision > 0)
+ fmt += ".fffffff".Substring(0, precision + 1);
+
+ switch (type) {
+ case TdsColumnType.DateTime2:
+ DateTime dt = (DateTime)Value;
+ return dt.ToString(fmt);
+ case TdsColumnType.DateTimeOffset:
+ DateTimeOffset dto = (DateTimeOffset)Value;
+ return dto.ToString(fmt + "zzz");
+ }
+
+ throw new ApplicationException("Should be unreachable");
+ }
+
internal byte[] GetBytes ()
{
byte[] result = {};
case "char" :
case "text" :
return Encoding.Default.GetBytes ((string)Value);
+ case "datetime2":
+ return Encoding.Default.GetBytes (GetDateTimeString (TdsColumnType.DateTime2));
+ case "datetimeoffset":
+ return Encoding.Default.GetBytes (GetDateTimeString (TdsColumnType.DateTimeOffset));
default :
return ((byte[]) Value);
}
if (IsNullable)
return TdsColumnType.DateTimeN;
return TdsColumnType.DateTime4;
+ case "datetime2":
+ return TdsColumnType.DateTime2;
+ case "datetimeoffset":
+ return TdsColumnType.DateTimeOffset;
case "float":
if (IsNullable)
return TdsColumnType.FloatN ;