Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / 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
- RawTextInputReport.cs
- SystemTcpStatistics.cs
- PropertyKey.cs
- SemanticTag.cs
- WebControlsSection.cs
- XPathExpr.cs
- InputScope.cs
- RSAPKCS1KeyExchangeFormatter.cs
- PageStatePersister.cs
- ElementMarkupObject.cs
- COM2IPerPropertyBrowsingHandler.cs
- HttpInputStream.cs
- BaseCodeDomTreeGenerator.cs
- DiffuseMaterial.cs
- MetadataCacheItem.cs
- XmlSerializerAssemblyAttribute.cs
- VirtualPathProvider.cs
- TextChange.cs
- ErrorsHelper.cs
- EntityDataSourceEntityTypeFilterItem.cs
- Clause.cs
- ChangePasswordAutoFormat.cs
- CompositeFontParser.cs
- RichTextBoxConstants.cs
- PrintControllerWithStatusDialog.cs
- InsufficientMemoryException.cs
- Highlights.cs
- AnimationClock.cs
- DiagnosticsConfigurationHandler.cs
- MinMaxParagraphWidth.cs
- OleDbMetaDataFactory.cs
- BamlRecordHelper.cs
- MSAAWinEventWrap.cs
- WindowsTokenRoleProvider.cs
- Attributes.cs
- Decimal.cs
- InfoCardKeyedHashAlgorithm.cs
- SecurityTokenSerializer.cs
- BaseTypeViewSchema.cs
- RightsController.cs
- GeometryCombineModeValidation.cs
- DataColumnMapping.cs
- ConfigurationElementProperty.cs
- ParseHttpDate.cs
- VSDExceptions.cs
- SqlRowUpdatingEvent.cs
- Event.cs
- _SSPIWrapper.cs
- WorkflowViewManager.cs
- DiscoveryClientBindingElement.cs
- CaseStatement.cs
- CompositeTypefaceMetrics.cs
- HtmlEmptyTagControlBuilder.cs
- CodeTypeParameterCollection.cs
- SchemaDeclBase.cs
- InvalidContentTypeException.cs
- DataColumnMappingCollection.cs
- Ray3DHitTestResult.cs
- AppDomainCompilerProxy.cs
- TextCharacters.cs
- ToolboxItemCollection.cs
- UpdateCompiler.cs
- OdbcError.cs
- TextTreeText.cs
- SchemaMerger.cs
- WebPartTransformerCollection.cs
- WindowsSysHeader.cs
- ControlParameter.cs
- EditingCommands.cs
- Sql8ExpressionRewriter.cs
- TreeIterator.cs
- BrowserDefinition.cs
- XmlSchemas.cs
- StateItem.cs
- GridItemCollection.cs
- WindowsToolbarAsMenu.cs
- SendActivityDesigner.cs
- StrokeSerializer.cs
- DispatcherBuilder.cs
- TemplatedAdorner.cs
- Attributes.cs
- ToolStripProgressBar.cs
- XmlArrayAttribute.cs
- SqlXmlStorage.cs
- ComplusTypeValidator.cs
- objectquery_tresulttype.cs
- EntityDataSourceMemberPath.cs
- LocalizabilityAttribute.cs
- HwndSubclass.cs
- UnauthorizedWebPart.cs
- XmlAggregates.cs
- Condition.cs
- DbInsertCommandTree.cs
- Dictionary.cs
- XsltConvert.cs
- ReadOnlyDataSourceView.cs
- XmlAttributes.cs
- InputMethodStateTypeInfo.cs
- CLRBindingWorker.cs
- XmlUtil.cs