Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataEntity / System / Data / SqlClient / SqlGen / DmlSqlGenerator.cs / 1 / 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
- UncommonField.cs
- SecurityDescriptor.cs
- XmlMessageFormatter.cs
- SmtpCommands.cs
- NavigateUrlConverter.cs
- XmlToDatasetMap.cs
- GetImportedCardRequest.cs
- Variable.cs
- FileDialog.cs
- HttpHandlersSection.cs
- WCFServiceClientProxyGenerator.cs
- TemplateBaseAction.cs
- ClientUtils.cs
- LocationUpdates.cs
- HebrewNumber.cs
- BooleanSwitch.cs
- returneventsaver.cs
- Identity.cs
- UnauthorizedWebPart.cs
- listitem.cs
- TokenBasedSetEnumerator.cs
- Subtree.cs
- IteratorFilter.cs
- BamlRecordReader.cs
- DispatcherProcessingDisabled.cs
- SoapReflectionImporter.cs
- GeometryDrawing.cs
- SubMenuStyle.cs
- SqlMultiplexer.cs
- DateTimeFormatInfo.cs
- OpacityConverter.cs
- ProfileModule.cs
- CodeAttachEventStatement.cs
- PKCS1MaskGenerationMethod.cs
- PersonalizationDictionary.cs
- WebBrowserSiteBase.cs
- StringValueSerializer.cs
- WrappedIUnknown.cs
- WebPartMenuStyle.cs
- InvalidPropValue.cs
- TypeToArgumentTypeConverter.cs
- XmlSchemaGroupRef.cs
- SafeLocalMemHandle.cs
- HttpValueCollection.cs
- CommentEmitter.cs
- CodeCatchClause.cs
- ProcessModule.cs
- AuthenticateEventArgs.cs
- ErrorTableItemStyle.cs
- LicenseProviderAttribute.cs
- List.cs
- NameValuePair.cs
- contentDescriptor.cs
- ValueTypePropertyReference.cs
- Italic.cs
- HtmlInputFile.cs
- WebFaultException.cs
- validation.cs
- ReflectionPermission.cs
- RoutedEventArgs.cs
- DigestComparer.cs
- SoapMessage.cs
- TextEditorTables.cs
- CachedPathData.cs
- SqlTopReducer.cs
- HtmlMeta.cs
- EntityDataSourceContextCreatedEventArgs.cs
- Script.cs
- ClrPerspective.cs
- OciHandle.cs
- ActionFrame.cs
- ResourcePermissionBaseEntry.cs
- RegistrySecurity.cs
- XmlSerializationReader.cs
- MenuItemCollectionEditor.cs
- _NestedMultipleAsyncResult.cs
- DesignerAttribute.cs
- FontInfo.cs
- XhtmlBasicLinkAdapter.cs
- Brush.cs
- DbExpressionRules.cs
- GreenMethods.cs
- XhtmlBasicLinkAdapter.cs
- Predicate.cs
- TileModeValidation.cs
- PeerToPeerException.cs
- ChangePasswordDesigner.cs
- DynamicResourceExtension.cs
- ListViewCommandEventArgs.cs
- AssemblyBuilderData.cs
- PathGradientBrush.cs
- WebDisplayNameAttribute.cs
- embossbitmapeffect.cs
- AssemblyCache.cs
- DeadCharTextComposition.cs
- DataGridColumnEventArgs.cs
- XmlAtomicValue.cs
- QueueProcessor.cs
- QueryResult.cs
- DependencyPropertyAttribute.cs