Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / SqlClient / SqlGen / DmlSqlGenerator.cs / 2 / DmlSqlGenerator.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....], [....] //--------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Text; using System.Data.Common; using System.Data.SqlClient; using System.Data.Metadata.Edm; using System.Data.Common.CommandTrees; using System.Data.Common.Utils; using System.Data.Mapping.Update.Internal; using System.Data.Mapping; namespace System.Data.SqlClient.SqlGen { ////// Class generating SQL for a DML command tree. /// internal static class DmlSqlGenerator { private const int s_commandTextBuilderInitialCapacity = 256; internal static string GenerateUpdateSql(DbUpdateCommandTree tree, SqlVersion sqlVersion, out Listparameters) { const string dummySetParameter = "@p"; StringBuilder commandText = new StringBuilder(s_commandTextBuilderInitialCapacity); ExpressionTranslator translator = new ExpressionTranslator(commandText, tree, null != tree.Returning, sqlVersion); if (tree.SetClauses.Count == 0) { commandText.AppendLine("declare " + dummySetParameter + " int"); } // update [schemaName].[tableName] commandText.Append("update "); tree.Target.Expression.Accept(translator); commandText.AppendLine(); // set c1 = ..., c2 = ..., ... bool first = true; commandText.Append("set "); foreach (DbSetClause setClause in tree.SetClauses) { if (first) { first = false; } else { commandText.Append(", "); } setClause.Property.Accept(translator); commandText.Append(" = "); setClause.Value.Accept(translator); } if (first) { // If first is still true, it indicates there were no set // clauses. Introduce a fake set clause so that: // - we acquire the appropriate locks // - server-gen columns (e.g. timestamp) get recomputed // // We use the following pattern: // // update Foo // set @p = 0 // where ... commandText.Append(dummySetParameter + " = 0"); } commandText.AppendLine(); // where c1 = ..., c2 = ... commandText.Append("where "); tree.Predicate.Accept(translator); commandText.AppendLine(); // generate returning sql GenerateReturningSql(commandText, tree, translator, tree.Returning); parameters = translator.Parameters; return commandText.ToString(); } internal static string GenerateDeleteSql(DbDeleteCommandTree tree, SqlVersion sqlVersion, out List parameters) { StringBuilder commandText = new StringBuilder(s_commandTextBuilderInitialCapacity); ExpressionTranslator translator = new ExpressionTranslator(commandText, tree, false, sqlVersion); // delete [schemaName].[tableName] commandText.Append("delete "); tree.Target.Expression.Accept(translator); commandText.AppendLine(); // where c1 = ... AND c2 = ... commandText.Append("where "); tree.Predicate.Accept(translator); parameters = translator.Parameters; return commandText.ToString(); } internal static string GenerateInsertSql(DbInsertCommandTree tree, SqlVersion sqlVersion, out List parameters) { StringBuilder commandText = new StringBuilder(s_commandTextBuilderInitialCapacity); ExpressionTranslator translator = new ExpressionTranslator(commandText, tree, null != tree.Returning, sqlVersion); // insert [schemaName].[tableName] commandText.Append("insert "); tree.Target.Expression.Accept(translator); if (0 < tree.SetClauses.Count) { // (c1, c2, c3, ...) commandText.Append("("); bool first = true; foreach (DbSetClause setClause in tree.SetClauses) { if (first) { first = false; } else { commandText.Append(", "); } setClause.Property.Accept(translator); } commandText.AppendLine(")"); // values c1, c2, ... first = true; commandText.Append("values ("); foreach (DbSetClause setClause in tree.SetClauses) { if (first) { first = false; } else { commandText.Append(", "); } setClause.Value.Accept(translator); translator.RegisterMemberValue(setClause.Property, setClause.Value); } commandText.AppendLine(")"); } else { // default values commandText.AppendLine().AppendLine("default values"); } // generate returning sql GenerateReturningSql(commandText, tree, translator, tree.Returning); parameters = translator.Parameters; return commandText.ToString(); } // Generates T-SQL describing a member // Requires: member must belong to an entity type (a safe requirement for DML // SQL gen, where we only access table columns) private static string GenerateMemberTSql(EdmMember member) { EntityType entityType = (EntityType)member.DeclaringType; string sql; if (!entityType.TryGetMemberSql(member, out sql)) { sql = SqlGenerator.QuoteIdentifier(member.Name); entityType.SetMemberSql(member, sql); } return sql; } /// /// Generates SQL fragment returning server-generated values. /// Requires: translator knows about member values so that we can figure out /// how to construct the key predicate. /// /// Builder containing command text /// Modification command tree /// Translator used to produce DML SQL statement /// for the tree /// Returning expression. If null, the method returns /// immediately without producing a SELECT statement. private static void GenerateReturningSql(StringBuilder commandText, DbModificationCommandTree tree, ExpressionTranslator translator, DbExpression returning) { // Nothing to do if there is no Returning expression if (null == returning) { return; } // select commandText.Append("select "); returning.Accept(translator); commandText.AppendLine(); // from commandText.Append("from "); tree.Target.Expression.Accept(translator); commandText.AppendLine(); // where commandText.Append("where @@ROWCOUNT > 0"); EntitySetBase table = ((DbScanExpression)tree.Target.Expression).Target; bool identity = false; foreach (EdmMember keyMember in table.ElementType.KeyMembers) { commandText.Append(" and "); commandText.Append(GenerateMemberTSql(keyMember)); commandText.Append(" = "); // retrieve member value sql. the translator remembers member values // as it constructs the DML statement (which precedes the "returning" // SQL) SqlParameter value; if (translator.MemberValues.TryGetValue(keyMember, out value)) { commandText.Append(value.ParameterName); } else { // if no value is registered for the key member, it means it is an identity // which can be retrieved using the scope_identity() function if (identity) { // there can be only one server generated key throw EntityUtil.NotSupported(System.Data.Entity.Strings.Update_NotSupportedServerGenKey(table.Name)); } if (!IsValidIdentityColumnType(keyMember.TypeUsage)) { throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.Update_NotSupportedIdentityType( keyMember.Name, keyMember.TypeUsage.ToString())); } commandText.Append("scope_identity()"); identity = true; } } } private static bool IsValidIdentityColumnType(TypeUsage typeUsage) { // SQL Server supports the following types for identity columns: // tinyint, smallint, int, bigint, decimal(p,0), or numeric(p,0) // make sure it's a primitive type if (typeUsage.EdmType.BuiltInTypeKind != BuiltInTypeKind.PrimitiveType) { return false; } // check if this is a supported primitive type (compare by name) string typeName = typeUsage.EdmType.Name; // integer types if (typeName == "tinyint" || typeName == "smallint" || typeName == "int" || typeName == "bigint") { return true; } // variable scale types (require scale = 0) if (typeName == "decimal" || typeName == "numeric") { Facet scaleFacet; return (typeUsage.Facets.TryGetValue(DbProviderManifest.ScaleFacetName, false, out scaleFacet) && Convert.ToInt32(scaleFacet.Value, CultureInfo.InvariantCulture) == 0); } // type not in supported list return false; } ////// Sample SQL: /// /// select IdentityValue /// from dbo.MyTable /// where @@ROWCOUNT > 0 and IdentityValue = scope_identity() /// /// or /// /// select TimestamptValue /// from dbo.MyTable /// where @@ROWCOUNT > 0 and Id = 1 /// /// Note that we filter on rowcount to ensure no rows are returned if no rows were modified. ///
////// Lightweight expression translator for DML expression trees, which have constrained /// scope and support. /// private class ExpressionTranslator : BasicExpressionVisitor { ////// Initialize a new expression translator populating the given string builder /// with command text. Command text builder and command tree must not be null. /// /// Command text with which to populate commands /// Command tree generating SQL /// Indicates whether the translator should preserve /// member values while compiling t-SQL (only needed for server generation) internal ExpressionTranslator(StringBuilder commandText, DbModificationCommandTree commandTree, bool preserveMemberValues, SqlVersion version) { Debug.Assert(null != commandText); Debug.Assert(null != commandTree); _commandText = commandText; _commandTree = commandTree; _version = version; _parameters = new List(); _memberValues = preserveMemberValues ? new Dictionary () : null; } private readonly StringBuilder _commandText; private readonly DbModificationCommandTree _commandTree; private readonly List _parameters; private readonly Dictionary _memberValues; private readonly static AliasGenerator s_parameterNames = new AliasGenerator("@", 1000); private readonly SqlVersion _version; internal List Parameters { get { return _parameters; } } internal Dictionary MemberValues { get { return _memberValues; } } // generate parameter (name based on parameter ordinal) internal SqlParameter CreateParameter(object value, TypeUsage type) { // Suppress the MaxLength facet in the type usage because // SqlClient will silently truncate data when SqlParameter.Size < |SqlParameter.Value|. const bool ignoreMaxLengthFacet = true; SqlParameter parameter = SqlProviderServices.CreateSqlParameter(s_parameterNames.GetName(_parameters.Count), type, ParameterMode.In, value, ignoreMaxLengthFacet, _version); _parameters.Add(parameter); return parameter; } public override void Visit(DbAndExpression expression) { VisitBinary(expression, " and "); } public override void Visit(DbOrExpression expression) { VisitBinary(expression, " or "); } public override void Visit(DbComparisonExpression expression) { Debug.Assert(expression.ExpressionKind == DbExpressionKind.Equals, "only equals comparison expressions are produced in DML command trees in V1"); VisitBinary(expression, " = "); RegisterMemberValue(expression.Left, expression.Right); } /// /// Call this method to register a property value pair so the translator "remembers" /// the values for members of the row being modified. These values can then be used /// to form a predicate for server-generation (based on the key of the row) /// /// DbExpression containing the column reference (property expression). /// DbExpression containing the value of the column. internal void RegisterMemberValue(DbExpression propertyExpression, DbExpression value) { if (null != _memberValues) { // register the value for this property Debug.Assert(propertyExpression.ExpressionKind == DbExpressionKind.Property, "DML predicates and setters must be of the form property = value"); // get name of left property EdmMember property = ((DbPropertyExpression)propertyExpression).Property; // don't track null values if (value.ExpressionKind != DbExpressionKind.Null) { Debug.Assert(value.ExpressionKind == DbExpressionKind.Constant, "value must either constant or null"); // retrieve the last parameter added (which describes the parameter) _memberValues[property] = _parameters[_parameters.Count - 1]; } } } public override void Visit(DbIsNullExpression expression) { expression.Argument.Accept(this); _commandText.Append(" is null"); } public override void Visit(DbNotExpression expression) { _commandText.Append("not ("); expression.Accept(this); _commandText.Append(")"); } public override void Visit(DbConstantExpression expression) { SqlParameter parameter = CreateParameter(expression.Value, expression.ResultType); _commandText.Append(parameter.ParameterName); } public override void Visit(DbScanExpression expression) { // we know we won't hit this code unless there is no function defined for this // ModificationOperation, so if this EntitySet is using a DefiningQuery, instead // of a table, that is an error if (expression.Target.DefiningQuery != null) { string missingCudElement; if (_commandTree.CommandTreeKind == DbCommandTreeKind.Delete) { missingCudElement = StorageMslConstructs.DeleteFunctionElement; } else if (_commandTree.CommandTreeKind == DbCommandTreeKind.Insert) { missingCudElement = StorageMslConstructs.InsertFunctionElement; } else { Debug.Assert(_commandTree.CommandTreeKind == DbCommandTreeKind.Update, "did you add a new option?"); missingCudElement = StorageMslConstructs.UpdateFunctionElement; } throw EntityUtil.Update(System.Data.Entity.Strings.Update_SqlEntitySetWithoutDmlFunctions(expression.Target.Name, missingCudElement, StorageMslConstructs.ModificationFunctionMappingElement), null); } _commandText.Append(SqlGenerator.GetTargetTSql(expression.Target)); } public override void Visit(DbPropertyExpression expression) { _commandText.Append(GenerateMemberTSql(expression.Property)); } public override void Visit(DbNullExpression expression) { _commandText.Append("null"); } public override void Visit(DbNewInstanceExpression expression) { // assumes all arguments are self-describing (no need to use aliases // because no renames are ever used in the projection) bool first = true; foreach (DbExpression argument in expression.Arguments) { if (first) { first = false; } else { _commandText.Append(", "); } argument.Accept(this); } } private void VisitBinary(DbBinaryExpression expression, string separator) { _commandText.Append("("); expression.Left.Accept(this); _commandText.Append(separator); expression.Right.Accept(this); _commandText.Append(")"); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....], [....] //--------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Text; using System.Data.Common; using System.Data.SqlClient; using System.Data.Metadata.Edm; using System.Data.Common.CommandTrees; using System.Data.Common.Utils; using System.Data.Mapping.Update.Internal; using System.Data.Mapping; namespace System.Data.SqlClient.SqlGen { ////// Class generating SQL for a DML command tree. /// internal static class DmlSqlGenerator { private const int s_commandTextBuilderInitialCapacity = 256; internal static string GenerateUpdateSql(DbUpdateCommandTree tree, SqlVersion sqlVersion, out Listparameters) { const string dummySetParameter = "@p"; StringBuilder commandText = new StringBuilder(s_commandTextBuilderInitialCapacity); ExpressionTranslator translator = new ExpressionTranslator(commandText, tree, null != tree.Returning, sqlVersion); if (tree.SetClauses.Count == 0) { commandText.AppendLine("declare " + dummySetParameter + " int"); } // update [schemaName].[tableName] commandText.Append("update "); tree.Target.Expression.Accept(translator); commandText.AppendLine(); // set c1 = ..., c2 = ..., ... bool first = true; commandText.Append("set "); foreach (DbSetClause setClause in tree.SetClauses) { if (first) { first = false; } else { commandText.Append(", "); } setClause.Property.Accept(translator); commandText.Append(" = "); setClause.Value.Accept(translator); } if (first) { // If first is still true, it indicates there were no set // clauses. Introduce a fake set clause so that: // - we acquire the appropriate locks // - server-gen columns (e.g. timestamp) get recomputed // // We use the following pattern: // // update Foo // set @p = 0 // where ... commandText.Append(dummySetParameter + " = 0"); } commandText.AppendLine(); // where c1 = ..., c2 = ... commandText.Append("where "); tree.Predicate.Accept(translator); commandText.AppendLine(); // generate returning sql GenerateReturningSql(commandText, tree, translator, tree.Returning); parameters = translator.Parameters; return commandText.ToString(); } internal static string GenerateDeleteSql(DbDeleteCommandTree tree, SqlVersion sqlVersion, out List parameters) { StringBuilder commandText = new StringBuilder(s_commandTextBuilderInitialCapacity); ExpressionTranslator translator = new ExpressionTranslator(commandText, tree, false, sqlVersion); // delete [schemaName].[tableName] commandText.Append("delete "); tree.Target.Expression.Accept(translator); commandText.AppendLine(); // where c1 = ... AND c2 = ... commandText.Append("where "); tree.Predicate.Accept(translator); parameters = translator.Parameters; return commandText.ToString(); } internal static string GenerateInsertSql(DbInsertCommandTree tree, SqlVersion sqlVersion, out List parameters) { StringBuilder commandText = new StringBuilder(s_commandTextBuilderInitialCapacity); ExpressionTranslator translator = new ExpressionTranslator(commandText, tree, null != tree.Returning, sqlVersion); // insert [schemaName].[tableName] commandText.Append("insert "); tree.Target.Expression.Accept(translator); if (0 < tree.SetClauses.Count) { // (c1, c2, c3, ...) commandText.Append("("); bool first = true; foreach (DbSetClause setClause in tree.SetClauses) { if (first) { first = false; } else { commandText.Append(", "); } setClause.Property.Accept(translator); } commandText.AppendLine(")"); // values c1, c2, ... first = true; commandText.Append("values ("); foreach (DbSetClause setClause in tree.SetClauses) { if (first) { first = false; } else { commandText.Append(", "); } setClause.Value.Accept(translator); translator.RegisterMemberValue(setClause.Property, setClause.Value); } commandText.AppendLine(")"); } else { // default values commandText.AppendLine().AppendLine("default values"); } // generate returning sql GenerateReturningSql(commandText, tree, translator, tree.Returning); parameters = translator.Parameters; return commandText.ToString(); } // Generates T-SQL describing a member // Requires: member must belong to an entity type (a safe requirement for DML // SQL gen, where we only access table columns) private static string GenerateMemberTSql(EdmMember member) { EntityType entityType = (EntityType)member.DeclaringType; string sql; if (!entityType.TryGetMemberSql(member, out sql)) { sql = SqlGenerator.QuoteIdentifier(member.Name); entityType.SetMemberSql(member, sql); } return sql; } /// /// Generates SQL fragment returning server-generated values. /// Requires: translator knows about member values so that we can figure out /// how to construct the key predicate. /// /// Builder containing command text /// Modification command tree /// Translator used to produce DML SQL statement /// for the tree /// Returning expression. If null, the method returns /// immediately without producing a SELECT statement. private static void GenerateReturningSql(StringBuilder commandText, DbModificationCommandTree tree, ExpressionTranslator translator, DbExpression returning) { // Nothing to do if there is no Returning expression if (null == returning) { return; } // select commandText.Append("select "); returning.Accept(translator); commandText.AppendLine(); // from commandText.Append("from "); tree.Target.Expression.Accept(translator); commandText.AppendLine(); // where commandText.Append("where @@ROWCOUNT > 0"); EntitySetBase table = ((DbScanExpression)tree.Target.Expression).Target; bool identity = false; foreach (EdmMember keyMember in table.ElementType.KeyMembers) { commandText.Append(" and "); commandText.Append(GenerateMemberTSql(keyMember)); commandText.Append(" = "); // retrieve member value sql. the translator remembers member values // as it constructs the DML statement (which precedes the "returning" // SQL) SqlParameter value; if (translator.MemberValues.TryGetValue(keyMember, out value)) { commandText.Append(value.ParameterName); } else { // if no value is registered for the key member, it means it is an identity // which can be retrieved using the scope_identity() function if (identity) { // there can be only one server generated key throw EntityUtil.NotSupported(System.Data.Entity.Strings.Update_NotSupportedServerGenKey(table.Name)); } if (!IsValidIdentityColumnType(keyMember.TypeUsage)) { throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.Update_NotSupportedIdentityType( keyMember.Name, keyMember.TypeUsage.ToString())); } commandText.Append("scope_identity()"); identity = true; } } } private static bool IsValidIdentityColumnType(TypeUsage typeUsage) { // SQL Server supports the following types for identity columns: // tinyint, smallint, int, bigint, decimal(p,0), or numeric(p,0) // make sure it's a primitive type if (typeUsage.EdmType.BuiltInTypeKind != BuiltInTypeKind.PrimitiveType) { return false; } // check if this is a supported primitive type (compare by name) string typeName = typeUsage.EdmType.Name; // integer types if (typeName == "tinyint" || typeName == "smallint" || typeName == "int" || typeName == "bigint") { return true; } // variable scale types (require scale = 0) if (typeName == "decimal" || typeName == "numeric") { Facet scaleFacet; return (typeUsage.Facets.TryGetValue(DbProviderManifest.ScaleFacetName, false, out scaleFacet) && Convert.ToInt32(scaleFacet.Value, CultureInfo.InvariantCulture) == 0); } // type not in supported list return false; } ////// Sample SQL: /// /// select IdentityValue /// from dbo.MyTable /// where @@ROWCOUNT > 0 and IdentityValue = scope_identity() /// /// or /// /// select TimestamptValue /// from dbo.MyTable /// where @@ROWCOUNT > 0 and Id = 1 /// /// Note that we filter on rowcount to ensure no rows are returned if no rows were modified. ///
////// Lightweight expression translator for DML expression trees, which have constrained /// scope and support. /// private class ExpressionTranslator : BasicExpressionVisitor { ////// Initialize a new expression translator populating the given string builder /// with command text. Command text builder and command tree must not be null. /// /// Command text with which to populate commands /// Command tree generating SQL /// Indicates whether the translator should preserve /// member values while compiling t-SQL (only needed for server generation) internal ExpressionTranslator(StringBuilder commandText, DbModificationCommandTree commandTree, bool preserveMemberValues, SqlVersion version) { Debug.Assert(null != commandText); Debug.Assert(null != commandTree); _commandText = commandText; _commandTree = commandTree; _version = version; _parameters = new List(); _memberValues = preserveMemberValues ? new Dictionary () : null; } private readonly StringBuilder _commandText; private readonly DbModificationCommandTree _commandTree; private readonly List _parameters; private readonly Dictionary _memberValues; private readonly static AliasGenerator s_parameterNames = new AliasGenerator("@", 1000); private readonly SqlVersion _version; internal List Parameters { get { return _parameters; } } internal Dictionary MemberValues { get { return _memberValues; } } // generate parameter (name based on parameter ordinal) internal SqlParameter CreateParameter(object value, TypeUsage type) { // Suppress the MaxLength facet in the type usage because // SqlClient will silently truncate data when SqlParameter.Size < |SqlParameter.Value|. const bool ignoreMaxLengthFacet = true; SqlParameter parameter = SqlProviderServices.CreateSqlParameter(s_parameterNames.GetName(_parameters.Count), type, ParameterMode.In, value, ignoreMaxLengthFacet, _version); _parameters.Add(parameter); return parameter; } public override void Visit(DbAndExpression expression) { VisitBinary(expression, " and "); } public override void Visit(DbOrExpression expression) { VisitBinary(expression, " or "); } public override void Visit(DbComparisonExpression expression) { Debug.Assert(expression.ExpressionKind == DbExpressionKind.Equals, "only equals comparison expressions are produced in DML command trees in V1"); VisitBinary(expression, " = "); RegisterMemberValue(expression.Left, expression.Right); } /// /// Call this method to register a property value pair so the translator "remembers" /// the values for members of the row being modified. These values can then be used /// to form a predicate for server-generation (based on the key of the row) /// /// DbExpression containing the column reference (property expression). /// DbExpression containing the value of the column. internal void RegisterMemberValue(DbExpression propertyExpression, DbExpression value) { if (null != _memberValues) { // register the value for this property Debug.Assert(propertyExpression.ExpressionKind == DbExpressionKind.Property, "DML predicates and setters must be of the form property = value"); // get name of left property EdmMember property = ((DbPropertyExpression)propertyExpression).Property; // don't track null values if (value.ExpressionKind != DbExpressionKind.Null) { Debug.Assert(value.ExpressionKind == DbExpressionKind.Constant, "value must either constant or null"); // retrieve the last parameter added (which describes the parameter) _memberValues[property] = _parameters[_parameters.Count - 1]; } } } public override void Visit(DbIsNullExpression expression) { expression.Argument.Accept(this); _commandText.Append(" is null"); } public override void Visit(DbNotExpression expression) { _commandText.Append("not ("); expression.Accept(this); _commandText.Append(")"); } public override void Visit(DbConstantExpression expression) { SqlParameter parameter = CreateParameter(expression.Value, expression.ResultType); _commandText.Append(parameter.ParameterName); } public override void Visit(DbScanExpression expression) { // we know we won't hit this code unless there is no function defined for this // ModificationOperation, so if this EntitySet is using a DefiningQuery, instead // of a table, that is an error if (expression.Target.DefiningQuery != null) { string missingCudElement; if (_commandTree.CommandTreeKind == DbCommandTreeKind.Delete) { missingCudElement = StorageMslConstructs.DeleteFunctionElement; } else if (_commandTree.CommandTreeKind == DbCommandTreeKind.Insert) { missingCudElement = StorageMslConstructs.InsertFunctionElement; } else { Debug.Assert(_commandTree.CommandTreeKind == DbCommandTreeKind.Update, "did you add a new option?"); missingCudElement = StorageMslConstructs.UpdateFunctionElement; } throw EntityUtil.Update(System.Data.Entity.Strings.Update_SqlEntitySetWithoutDmlFunctions(expression.Target.Name, missingCudElement, StorageMslConstructs.ModificationFunctionMappingElement), null); } _commandText.Append(SqlGenerator.GetTargetTSql(expression.Target)); } public override void Visit(DbPropertyExpression expression) { _commandText.Append(GenerateMemberTSql(expression.Property)); } public override void Visit(DbNullExpression expression) { _commandText.Append("null"); } public override void Visit(DbNewInstanceExpression expression) { // assumes all arguments are self-describing (no need to use aliases // because no renames are ever used in the projection) bool first = true; foreach (DbExpression argument in expression.Arguments) { if (first) { first = false; } else { _commandText.Append(", "); } argument.Accept(this); } } private void VisitBinary(DbBinaryExpression expression, string separator) { _commandText.Append("("); expression.Left.Accept(this); _commandText.Append(separator); expression.Right.Accept(this); _commandText.Append(")"); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ThreadPool.cs
- GestureRecognitionResult.cs
- ExpressionBuilder.cs
- HttpRuntimeSection.cs
- PerfCounterSection.cs
- RelationshipEndMember.cs
- EnumValAlphaComparer.cs
- ValuePatternIdentifiers.cs
- TextOutput.cs
- SHA512CryptoServiceProvider.cs
- LabelLiteral.cs
- CommonProperties.cs
- ExpandedWrapper.cs
- StringAnimationUsingKeyFrames.cs
- DoubleAnimationUsingKeyFrames.cs
- DataGridLinkButton.cs
- FileDataSource.cs
- activationcontext.cs
- CompositeCollection.cs
- ScriptControl.cs
- Timer.cs
- GridViewRowPresenter.cs
- LinqDataSourceSelectEventArgs.cs
- InputQueueChannel.cs
- HttpHandlerActionCollection.cs
- X509Utils.cs
- LocationFactory.cs
- UTF32Encoding.cs
- DataGridViewIntLinkedList.cs
- NamespaceMapping.cs
- LongTypeConverter.cs
- EncodingTable.cs
- PublisherMembershipCondition.cs
- SqlProvider.cs
- InkCanvasSelection.cs
- RadioButtonBaseAdapter.cs
- Vector3DAnimationUsingKeyFrames.cs
- autovalidator.cs
- DesignBinding.cs
- ConnectAlgorithms.cs
- FormsAuthenticationConfiguration.cs
- DesignerLoader.cs
- BitmapVisualManager.cs
- ControlAdapter.cs
- PingOptions.cs
- WebPartsPersonalizationAuthorization.cs
- EncoderFallback.cs
- XmlLanguageConverter.cs
- HttpHeaderCollection.cs
- FileLoadException.cs
- PageCatalogPart.cs
- SingleAnimation.cs
- RuntimeDelegateArgument.cs
- AssemblyHash.cs
- ServiceReflector.cs
- AmbientLight.cs
- CollectionDataContract.cs
- IdleTimeoutMonitor.cs
- DataContractJsonSerializer.cs
- QuotedPrintableStream.cs
- DragCompletedEventArgs.cs
- IProvider.cs
- PropertyStore.cs
- DataGridViewColumnConverter.cs
- XmlSchemaImport.cs
- CultureInfoConverter.cs
- GlobalDataBindingHandler.cs
- TcpProcessProtocolHandler.cs
- ResourceProviderFactory.cs
- DeploymentSectionCache.cs
- GridViewUpdateEventArgs.cs
- CustomAssemblyResolver.cs
- IdleTimeoutMonitor.cs
- PathFigureCollection.cs
- EdgeProfileValidation.cs
- DataGridViewMethods.cs
- FontStyleConverter.cs
- CodeMethodMap.cs
- ExtenderHelpers.cs
- VectorAnimationBase.cs
- WebContext.cs
- TextOutput.cs
- DbProviderFactoriesConfigurationHandler.cs
- EastAsianLunisolarCalendar.cs
- WindowsToolbarAsMenu.cs
- WebPermission.cs
- StatusBarPanel.cs
- DataGridHeaderBorder.cs
- DataTableMapping.cs
- QualifiedCellIdBoolean.cs
- SQLInt16.cs
- ArgumentOutOfRangeException.cs
- LineInfo.cs
- MessageBox.cs
- EditorZoneBase.cs
- FileReservationCollection.cs
- TypeGeneratedEventArgs.cs
- StreamingContext.cs
- EntityDataSourceDesignerHelper.cs
- Assert.cs