Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DLinq / Dlinq / SqlClient / Query / SqlTypeConverter.cs / 1 / SqlTypeConverter.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Linq;
using System.Diagnostics.CodeAnalysis;
namespace System.Data.Linq.SqlClient {
///
/// The standard SQL text for a type conversion is CONVERT([newtype],value)
/// Replace it with special SQL functions where necessary (e.g. char -> int uses UNICODE(value) instead).
///
internal class SqlTypeConverter : SqlVisitor {
protected SqlFactory sql;
internal SqlTypeConverter(SqlFactory sql) {
this.sql = sql;
}
bool StringConversionIsSafe(ProviderType oldSqlType, ProviderType newSqlType) {
// if we are dealing with a conversion from a fixed-size string or char
if (BothTypesAreStrings(oldSqlType, newSqlType)) {
// we assume we can convert to an unknown size
// we can do the conversion when both sizes are specified and the destination size is larger
return !newSqlType.HasSizeOrIsLarge || OldWillFitInNew(oldSqlType, newSqlType);
}
// give the benefit of the doubt for conversion from non-string types
return true;
}
bool StringConversionIsNeeded(ProviderType oldSqlType, ProviderType newSqlType) {
if (BothTypesAreStrings(oldSqlType, newSqlType)) {
bool stringsFixedSize = oldSqlType.IsFixedSize || newSqlType.IsFixedSize;
if (!newSqlType.HasSizeOrIsLarge) {
// we assume we can convert to an unknown size
return true;
}
else if (OldWillFitInNew(oldSqlType, newSqlType)) {
// we can do the conversion when both sizes are specified and the destination size is larger
// but we only need to do it when one is fixed size
return stringsFixedSize;
} else {
return false;
}
} else {
return true;
}
}
[SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")]
private bool OldWillFitInNew(ProviderType oldSqlType, ProviderType newSqlType) {
bool result = newSqlType.IsLargeType // we can fit into a large type
|| !newSqlType.HasSizeOrIsLarge // if the type is not large, and doesn't have a size specified, assume OK
|| (!oldSqlType.IsLargeType // else, if the old type isn't large
&& oldSqlType.HasSizeOrIsLarge // and both old ..
&& newSqlType.HasSizeOrIsLarge // .. and new sizes are specified
&& newSqlType.Size >= oldSqlType.Size); // and if the new size is larger or equal to the old, then OK
return result;
}
private bool BothTypesAreStrings(ProviderType oldSqlType, ProviderType newSqlType) {
bool result = oldSqlType.IsSameTypeFamily(sql.TypeProvider.From(typeof(string)))
&& newSqlType.IsSameTypeFamily(sql.TypeProvider.From(typeof(string)));
return result;
}
internal override SqlExpression VisitUnaryOperator(SqlUnary uo) {
uo.Operand = this.VisitExpression(uo.Operand);
if (uo.NodeType != SqlNodeType.Convert) {
return uo;
}
ProviderType oldSqlType = uo.Operand.SqlType;
ProviderType newSqlType = uo.SqlType;
Type oldClrType = TypeSystem.GetNonNullableType(uo.Operand.ClrType);
Type newClrType = TypeSystem.GetNonNullableType(uo.ClrType);
if (newClrType == typeof(char)) {
if (oldClrType == typeof(bool)) {
throw Error.ConvertToCharFromBoolNotSupported();
}
if (oldSqlType.IsNumeric) {
// numeric --> char
return sql.FunctionCall(uo.ClrType, "NCHAR", new SqlExpression[] { uo.Operand }, uo.SourceExpression);
}
if (StringConversionIsSafe(oldSqlType, newSqlType)) {
if (StringConversionIsNeeded(oldSqlType, newSqlType)) {
// set the new size to the (potentially smaller) oldSqlType.Size
uo.SetSqlType(sql.TypeProvider.From(uo.ClrType, oldSqlType.HasSizeOrIsLarge ? oldSqlType.Size : (int?)null));
}
} else {
throw Error.UnsafeStringConversion(oldSqlType.ToQueryString(), newSqlType.ToQueryString());
}
} else if (oldClrType == typeof(char) && (oldSqlType.IsChar || oldSqlType.IsString) && newSqlType.IsNumeric) {
// char --> int
return sql.FunctionCall(newClrType, sql.TypeProvider.From(typeof(int)), "UNICODE", new SqlExpression[] { uo.Operand }, uo.SourceExpression);
} else if (newClrType == typeof(string)) {
if (oldClrType == typeof(double)) {
// use longer format if it was a double in the CLR expression
return ConvertDoubleToString(uo.Operand, uo.ClrType);
} else if (oldClrType == typeof(bool)) {
// use 'true' or 'false' if it was a bool in the CLR expression
return ConvertBitToString(uo.Operand, uo.ClrType);
} else if (StringConversionIsSafe(oldSqlType, newSqlType)) {
if (StringConversionIsNeeded(oldSqlType, newSqlType)) {
// set the new size to the (potentially smaller) oldSqlType.Size
uo.SetSqlType(sql.TypeProvider.From(uo.ClrType, oldSqlType.HasSizeOrIsLarge ? oldSqlType.Size : (int?)null));
}
} else {
throw Error.UnsafeStringConversion(oldSqlType.ToQueryString(), newSqlType.ToQueryString());
}
}
return uo;
}
private SqlExpression ConvertDoubleToString(SqlExpression expr, Type resultClrType) {
// for double we need the form CONVERT(NVARCHAR(30),...,2) to get the full precision
// fake up a SqlExpression for NVARCHAR(30)
SqlExpression nvarchar = sql.FunctionCall(
typeof(void), "NVARCHAR",
new SqlExpression[] { sql.ValueFromObject(30, false, expr.SourceExpression) },
expr.SourceExpression
);
return sql.FunctionCall(
resultClrType, "CONVERT",
new SqlExpression[] { nvarchar, expr, sql.ValueFromObject(2, false, expr.SourceExpression) },
expr.SourceExpression
);
}
private SqlExpression ConvertBitToString(SqlExpression expr, Type resultClrType) {
return new SqlSearchedCase(
resultClrType,
new SqlWhen[] { new SqlWhen(expr, sql.ValueFromObject(true.ToString(), false, expr.SourceExpression)) },
sql.ValueFromObject(false.ToString(), false, expr.SourceExpression),
expr.SourceExpression
);
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Linq;
using System.Diagnostics.CodeAnalysis;
namespace System.Data.Linq.SqlClient {
///
/// The standard SQL text for a type conversion is CONVERT([newtype],value)
/// Replace it with special SQL functions where necessary (e.g. char -> int uses UNICODE(value) instead).
///
internal class SqlTypeConverter : SqlVisitor {
protected SqlFactory sql;
internal SqlTypeConverter(SqlFactory sql) {
this.sql = sql;
}
bool StringConversionIsSafe(ProviderType oldSqlType, ProviderType newSqlType) {
// if we are dealing with a conversion from a fixed-size string or char
if (BothTypesAreStrings(oldSqlType, newSqlType)) {
// we assume we can convert to an unknown size
// we can do the conversion when both sizes are specified and the destination size is larger
return !newSqlType.HasSizeOrIsLarge || OldWillFitInNew(oldSqlType, newSqlType);
}
// give the benefit of the doubt for conversion from non-string types
return true;
}
bool StringConversionIsNeeded(ProviderType oldSqlType, ProviderType newSqlType) {
if (BothTypesAreStrings(oldSqlType, newSqlType)) {
bool stringsFixedSize = oldSqlType.IsFixedSize || newSqlType.IsFixedSize;
if (!newSqlType.HasSizeOrIsLarge) {
// we assume we can convert to an unknown size
return true;
}
else if (OldWillFitInNew(oldSqlType, newSqlType)) {
// we can do the conversion when both sizes are specified and the destination size is larger
// but we only need to do it when one is fixed size
return stringsFixedSize;
} else {
return false;
}
} else {
return true;
}
}
[SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")]
private bool OldWillFitInNew(ProviderType oldSqlType, ProviderType newSqlType) {
bool result = newSqlType.IsLargeType // we can fit into a large type
|| !newSqlType.HasSizeOrIsLarge // if the type is not large, and doesn't have a size specified, assume OK
|| (!oldSqlType.IsLargeType // else, if the old type isn't large
&& oldSqlType.HasSizeOrIsLarge // and both old ..
&& newSqlType.HasSizeOrIsLarge // .. and new sizes are specified
&& newSqlType.Size >= oldSqlType.Size); // and if the new size is larger or equal to the old, then OK
return result;
}
private bool BothTypesAreStrings(ProviderType oldSqlType, ProviderType newSqlType) {
bool result = oldSqlType.IsSameTypeFamily(sql.TypeProvider.From(typeof(string)))
&& newSqlType.IsSameTypeFamily(sql.TypeProvider.From(typeof(string)));
return result;
}
internal override SqlExpression VisitUnaryOperator(SqlUnary uo) {
uo.Operand = this.VisitExpression(uo.Operand);
if (uo.NodeType != SqlNodeType.Convert) {
return uo;
}
ProviderType oldSqlType = uo.Operand.SqlType;
ProviderType newSqlType = uo.SqlType;
Type oldClrType = TypeSystem.GetNonNullableType(uo.Operand.ClrType);
Type newClrType = TypeSystem.GetNonNullableType(uo.ClrType);
if (newClrType == typeof(char)) {
if (oldClrType == typeof(bool)) {
throw Error.ConvertToCharFromBoolNotSupported();
}
if (oldSqlType.IsNumeric) {
// numeric --> char
return sql.FunctionCall(uo.ClrType, "NCHAR", new SqlExpression[] { uo.Operand }, uo.SourceExpression);
}
if (StringConversionIsSafe(oldSqlType, newSqlType)) {
if (StringConversionIsNeeded(oldSqlType, newSqlType)) {
// set the new size to the (potentially smaller) oldSqlType.Size
uo.SetSqlType(sql.TypeProvider.From(uo.ClrType, oldSqlType.HasSizeOrIsLarge ? oldSqlType.Size : (int?)null));
}
} else {
throw Error.UnsafeStringConversion(oldSqlType.ToQueryString(), newSqlType.ToQueryString());
}
} else if (oldClrType == typeof(char) && (oldSqlType.IsChar || oldSqlType.IsString) && newSqlType.IsNumeric) {
// char --> int
return sql.FunctionCall(newClrType, sql.TypeProvider.From(typeof(int)), "UNICODE", new SqlExpression[] { uo.Operand }, uo.SourceExpression);
} else if (newClrType == typeof(string)) {
if (oldClrType == typeof(double)) {
// use longer format if it was a double in the CLR expression
return ConvertDoubleToString(uo.Operand, uo.ClrType);
} else if (oldClrType == typeof(bool)) {
// use 'true' or 'false' if it was a bool in the CLR expression
return ConvertBitToString(uo.Operand, uo.ClrType);
} else if (StringConversionIsSafe(oldSqlType, newSqlType)) {
if (StringConversionIsNeeded(oldSqlType, newSqlType)) {
// set the new size to the (potentially smaller) oldSqlType.Size
uo.SetSqlType(sql.TypeProvider.From(uo.ClrType, oldSqlType.HasSizeOrIsLarge ? oldSqlType.Size : (int?)null));
}
} else {
throw Error.UnsafeStringConversion(oldSqlType.ToQueryString(), newSqlType.ToQueryString());
}
}
return uo;
}
private SqlExpression ConvertDoubleToString(SqlExpression expr, Type resultClrType) {
// for double we need the form CONVERT(NVARCHAR(30),...,2) to get the full precision
// fake up a SqlExpression for NVARCHAR(30)
SqlExpression nvarchar = sql.FunctionCall(
typeof(void), "NVARCHAR",
new SqlExpression[] { sql.ValueFromObject(30, false, expr.SourceExpression) },
expr.SourceExpression
);
return sql.FunctionCall(
resultClrType, "CONVERT",
new SqlExpression[] { nvarchar, expr, sql.ValueFromObject(2, false, expr.SourceExpression) },
expr.SourceExpression
);
}
private SqlExpression ConvertBitToString(SqlExpression expr, Type resultClrType) {
return new SqlSearchedCase(
resultClrType,
new SqlWhen[] { new SqlWhen(expr, sql.ValueFromObject(true.ToString(), false, expr.SourceExpression)) },
sql.ValueFromObject(false.ToString(), false, expr.SourceExpression),
expr.SourceExpression
);
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TreeView.cs
- XmlSchemaComplexContentRestriction.cs
- QueryCacheEntry.cs
- Hyperlink.cs
- TreeNodeConverter.cs
- MessagingDescriptionAttribute.cs
- ColorKeyFrameCollection.cs
- AncillaryOps.cs
- LabelAutomationPeer.cs
- CacheSection.cs
- DataServiceProviderMethods.cs
- SoapServerProtocol.cs
- assertwrapper.cs
- InternalConfigEventArgs.cs
- MimeObjectFactory.cs
- BaseDataListActionList.cs
- elementinformation.cs
- ParameterCollectionEditor.cs
- DesignerAttribute.cs
- X509ScopedServiceCertificateElementCollection.cs
- CloudCollection.cs
- SAPIEngineTypes.cs
- OdbcParameter.cs
- ConstraintManager.cs
- DesignerSerializationVisibilityAttribute.cs
- HostingEnvironmentException.cs
- SmiConnection.cs
- PropertyAccessVisitor.cs
- FixedElement.cs
- ZipFileInfoCollection.cs
- ToolStripMenuItem.cs
- TargetPerspective.cs
- Attributes.cs
- DetailsViewPagerRow.cs
- EntityCommandDefinition.cs
- EntityConnection.cs
- PropertyValueChangedEvent.cs
- SafeRightsManagementEnvironmentHandle.cs
- EventSinkHelperWriter.cs
- NaturalLanguageHyphenator.cs
- BlurEffect.cs
- XmlSchemaAnyAttribute.cs
- brushes.cs
- ScaleTransform3D.cs
- LoginView.cs
- QuerySafeNavigator.cs
- WindowsToolbar.cs
- Model3DCollection.cs
- MissingFieldException.cs
- CodeCompileUnit.cs
- ProjectionPathBuilder.cs
- ImageSourceConverter.cs
- DataGridViewColumnDesigner.cs
- PersonalizationProviderCollection.cs
- HttpsTransportElement.cs
- GridView.cs
- DBConnection.cs
- SelectedDatesCollection.cs
- DrawTreeNodeEventArgs.cs
- WindowsFormsHostAutomationPeer.cs
- TransactionManager.cs
- PrintController.cs
- UnrecognizedPolicyAssertionElement.cs
- ActiveXSerializer.cs
- DivideByZeroException.cs
- ThousandthOfEmRealDoubles.cs
- EllipseGeometry.cs
- FolderBrowserDialogDesigner.cs
- ParenthesizePropertyNameAttribute.cs
- SafeNativeMethodsMilCoreApi.cs
- FreezableCollection.cs
- RequestCacheValidator.cs
- Typeface.cs
- DecryptedHeader.cs
- Point3D.cs
- InternalEnumValidator.cs
- IdentityValidationException.cs
- AxDesigner.cs
- FontCollection.cs
- ThemeDictionaryExtension.cs
- DataGridViewSelectedCellCollection.cs
- StatusBar.cs
- GorillaCodec.cs
- FolderBrowserDialogDesigner.cs
- StreamingContext.cs
- SqlCommandBuilder.cs
- Attributes.cs
- HandleCollector.cs
- ListSourceHelper.cs
- assemblycache.cs
- StretchValidation.cs
- XmlNamespaceManager.cs
- RelativeSource.cs
- CacheEntry.cs
- NamespaceMapping.cs
- SqlReorderer.cs
- SystemTcpStatistics.cs
- ViewCellRelation.cs
- XmlSchemaSimpleTypeUnion.cs
- DateTimeConverter.cs