Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / 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
- input.cs
- RayMeshGeometry3DHitTestResult.cs
- MULTI_QI.cs
- SafeNativeMethods.cs
- SettingsSavedEventArgs.cs
- WebServicesDescriptionAttribute.cs
- DocumentReferenceCollection.cs
- CodeVariableReferenceExpression.cs
- DesignOnlyAttribute.cs
- RawMouseInputReport.cs
- TemplateColumn.cs
- _ConnectOverlappedAsyncResult.cs
- TargetConverter.cs
- HttpChannelHelpers.cs
- _Win32.cs
- DesignerEventService.cs
- FontUnitConverter.cs
- XPathBinder.cs
- SafeSecurityHelper.cs
- DataGridViewCell.cs
- EditingCoordinator.cs
- SignedInfo.cs
- DbMetaDataColumnNames.cs
- InstanceStore.cs
- BamlTreeUpdater.cs
- JoinTreeSlot.cs
- NegotiationTokenAuthenticatorState.cs
- FilteredReadOnlyMetadataCollection.cs
- RuntimeConfig.cs
- Types.cs
- Peer.cs
- PageCodeDomTreeGenerator.cs
- ManualWorkflowSchedulerService.cs
- CookieParameter.cs
- TdsParserSessionPool.cs
- PartialClassGenerationTask.cs
- DoubleLink.cs
- X509Certificate.cs
- NullableDecimalMinMaxAggregationOperator.cs
- SignatureHelper.cs
- HttpServerVarsCollection.cs
- ReferencedCollectionType.cs
- CqlParser.cs
- PasswordBox.cs
- ConfigurationStrings.cs
- safex509handles.cs
- RuntimeConfigLKG.cs
- GridViewRowEventArgs.cs
- Icon.cs
- VisualBasicReference.cs
- SqlDataSourceFilteringEventArgs.cs
- CompilerGeneratedAttribute.cs
- CodeAttributeArgumentCollection.cs
- DrawingGroup.cs
- StreamSecurityUpgradeProvider.cs
- EntityDataSourceEntityTypeFilterItem.cs
- LicenseManager.cs
- CategoryNameCollection.cs
- SplitterPanelDesigner.cs
- NamedPipeDuplicateContext.cs
- TypeRefElement.cs
- AutomationEvent.cs
- PanelStyle.cs
- XhtmlConformanceSection.cs
- IOThreadScheduler.cs
- RadioButtonList.cs
- Rect3DConverter.cs
- SecurityPolicySection.cs
- FusionWrap.cs
- IndentTextWriter.cs
- ResourceCategoryAttribute.cs
- UpdateExpressionVisitor.cs
- ConfigurationElementProperty.cs
- SoapSchemaMember.cs
- EmptyQuery.cs
- GZipDecoder.cs
- ContentFilePart.cs
- CompositeActivityCodeGenerator.cs
- FtpRequestCacheValidator.cs
- ToolStripArrowRenderEventArgs.cs
- ReaderWriterLock.cs
- SymbolUsageManager.cs
- StringWriter.cs
- OleDbCommand.cs
- ResizingMessageFilter.cs
- ToolStripProgressBar.cs
- XPathMultyIterator.cs
- NullRuntimeConfig.cs
- DataGridItemEventArgs.cs
- LinqDataSourceStatusEventArgs.cs
- MimeMapping.cs
- ResourceManager.cs
- KeyManager.cs
- UserPreferenceChangingEventArgs.cs
- WebServicesInteroperability.cs
- DataGridViewRowHeightInfoNeededEventArgs.cs
- XPathAncestorIterator.cs
- AssociationEndMember.cs
- Geometry.cs
- TreePrinter.cs