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
- PinnedBufferMemoryStream.cs
- TypeUsage.cs
- CodeNamespace.cs
- ComponentEditorForm.cs
- Variant.cs
- ResolveMatchesMessageCD1.cs
- ContextMenuService.cs
- DataGridViewDataErrorEventArgs.cs
- WebControlsSection.cs
- CapabilitiesPattern.cs
- Stroke.cs
- WmlTextBoxAdapter.cs
- EntityDataSourceDataSelection.cs
- HtmlEncodedRawTextWriter.cs
- Inline.cs
- WebExceptionStatus.cs
- FontInfo.cs
- ColumnClickEvent.cs
- ArgumentDirectionHelper.cs
- MemberListBinding.cs
- Debug.cs
- Matrix.cs
- RightsController.cs
- ResourceReferenceExpressionConverter.cs
- EncryptedXml.cs
- XmlSerializerSection.cs
- GeometryModel3D.cs
- Group.cs
- DataGridViewTopLeftHeaderCell.cs
- NamedPipeTransportSecurityElement.cs
- ArgIterator.cs
- CheckBoxPopupAdapter.cs
- Peer.cs
- PrtTicket_Base.cs
- ActivitiesCollection.cs
- AuthenticationSection.cs
- SoapSchemaImporter.cs
- nulltextnavigator.cs
- SimpleLine.cs
- TrackingQuery.cs
- InputScope.cs
- ReferencedAssembly.cs
- DataBindEngine.cs
- HealthMonitoringSectionHelper.cs
- TextTreeRootTextBlock.cs
- XmlHierarchicalEnumerable.cs
- DBCSCodePageEncoding.cs
- DispatcherObject.cs
- MsmqAppDomainProtocolHandler.cs
- VisualCollection.cs
- BamlTreeUpdater.cs
- XmlRootAttribute.cs
- ListBoxItem.cs
- SizeLimitedCache.cs
- SystemDropShadowChrome.cs
- handlecollector.cs
- NullableBoolConverter.cs
- SvcMapFile.cs
- OperationBehaviorAttribute.cs
- propertyentry.cs
- XmlParserContext.cs
- EastAsianLunisolarCalendar.cs
- Int64Storage.cs
- EventSourceCreationData.cs
- TextBounds.cs
- KeySplineConverter.cs
- ImmutableObjectAttribute.cs
- __Error.cs
- CapiHashAlgorithm.cs
- DispatchChannelSink.cs
- RandomNumberGenerator.cs
- CreateRefExpr.cs
- ToolStripRendererSwitcher.cs
- SelectedDatesCollection.cs
- SourceLineInfo.cs
- PrivacyNoticeElement.cs
- List.cs
- ParameterBuilder.cs
- SiteMapDataSourceView.cs
- StronglyTypedResourceBuilder.cs
- MorphHelper.cs
- XamlTemplateSerializer.cs
- StringBlob.cs
- EventSinkHelperWriter.cs
- KeyGesture.cs
- ClientSettingsSection.cs
- Win32Native.cs
- OraclePermission.cs
- MessagingDescriptionAttribute.cs
- RuntimeArgumentHandle.cs
- CreationContext.cs
- SqlNotificationEventArgs.cs
- CachedTypeface.cs
- RelOps.cs
- Effect.cs
- NullableDoubleSumAggregationOperator.cs
- DataConnectionHelper.cs
- SoapUnknownHeader.cs
- DataRow.cs
- CallContext.cs