1 //--------------------------------------------------------------------- 2 // <copyright file="ExpressionDumper.cs" company="Microsoft"> 3 // Copyright (c) Microsoft Corporation. All rights reserved. 4 // </copyright> 5 // 6 // @owner Microsoft 7 // @backupOwner Microsoft 8 //--------------------------------------------------------------------- 9 10 using System; 11 using System.Collections.Generic; 12 using System.Diagnostics; 13 14 using System.Data.Common; 15 using System.Data.Metadata.Edm; 16 using System.Data.Common.CommandTrees; 17 18 namespace System.Data.Common.CommandTrees.Internal 19 { 20 /// <summary> 21 /// Writes a description of a given expression, in a format determined by the specific implementation of a derived type 22 /// </summary> 23 internal abstract class ExpressionDumper : DbExpressionVisitor 24 { 25 #region Constructors ExpressionDumper()26 internal ExpressionDumper() { } 27 #endregion 28 29 #region (Pseudo) Public API 30 31 /// <summary> 32 /// Begins a new Dump block with the specified name 33 /// </summary> 34 /// <param name="name">The name of the block</param> Begin(string name)35 internal void Begin(string name) { Begin(name, (Dictionary<string, object>)null); } 36 37 /// <summary> 38 /// Begins a new Dump block with the specified name and specified attributes 39 /// </summary> 40 /// <param name="name">The name of the block</param> 41 /// <param name="attrs">The named attributes of the block. May be null</param> Begin(string name, Dictionary<string, object> attrs)42 internal abstract void Begin(string name, Dictionary<string, object> attrs); 43 44 /// <summary> 45 /// Ends the Dump block with the specified name. 46 /// The caller should not assumer that this name will be verified 47 /// against the last name used in a Begin call. 48 /// </summary> 49 /// <param name="name">The name of the block</param> End(string name)50 internal abstract void End(string name); 51 52 /// <summary> 53 /// Dumps a DbExpression by visiting it. 54 /// </summary> 55 /// <param name="target">The DbExpression to dump</param> Dump(DbExpression target)56 internal void Dump(DbExpression target) 57 { 58 target.Accept(this); 59 } 60 61 /// <summary> 62 /// Dumps a DbExpression with the specified block name preceeding and succeeding (decorating) it. 63 /// </summary> 64 /// <param name="e">The DbExpression to dump</param> 65 /// <param name="name">The decorating block name</param> Dump(DbExpression e, string name)66 internal void Dump(DbExpression e, string name) 67 { 68 Begin(name); 69 Dump(e); 70 End(name); 71 } 72 73 /// <summary> 74 /// Dumps a DbExpressionBinding with the specified decoration 75 /// </summary> 76 /// <param name="binding">The DbExpressionBinding to dump</param> 77 /// <param name="name">The decorating block name</param> Dump(DbExpressionBinding binding, string name)78 internal void Dump(DbExpressionBinding binding, string name) 79 { 80 Begin(name); 81 Dump(binding); 82 End(name); 83 } 84 85 /// <summary> 86 /// Dumps a DbExpressionBinding including its VariableName and DbExpression 87 /// </summary> 88 /// <param name="binding">The DbExpressionBinding to dump</param> Dump(DbExpressionBinding binding)89 internal void Dump(DbExpressionBinding binding) 90 { 91 Begin("DbExpressionBinding", "VariableName", binding.VariableName); 92 Begin("Expression"); 93 Dump(binding.Expression); 94 End("Expression"); 95 End("DbExpressionBinding"); 96 97 } 98 99 /// <summary> 100 /// Dumps a DbGroupExpressionBinding with the specified decoration 101 /// </summary> 102 /// <param name="binding">The DbGroupExpressionBinding to dump</param> 103 /// <param name="name">The decorating block name</param> Dump(DbGroupExpressionBinding binding, string name)104 internal void Dump(DbGroupExpressionBinding binding, string name) 105 { 106 Begin(name); 107 Dump(binding); 108 End(name); 109 } 110 111 /// <summary> 112 /// Dumps a DbGroupExpressionBinding including its VariableName, GroupVariableName and DbExpression 113 /// </summary> 114 /// <param name="binding">The DbGroupExpressionBinding to dump</param> Dump(DbGroupExpressionBinding binding)115 internal void Dump(DbGroupExpressionBinding binding) 116 { 117 Begin("DbGroupExpressionBinding", "VariableName", binding.VariableName, "GroupVariableName", binding.GroupVariableName); 118 Begin("Expression"); 119 Dump(binding.Expression); 120 End("Expression"); 121 End("DbGroupExpressionBinding"); 122 } 123 124 /// <summary> 125 /// Dumps each DbExpression in the specified enumerable. The entire output is decorated with the 'pluralName' 126 /// block name while each element DbExpression is decorated with the 'singularName' block name. 127 /// If the list is empty only the pluralName decoration start/end will appear. 128 /// </summary> 129 /// <param name="exprs">The enumerable list of Expressions to dump</param> 130 /// <param name="pluralName">The overall list decoration block name</param> 131 /// <param name="singularName">The decoration block name that will be applied to each element DbExpression</param> Dump(IEnumerable<DbExpression> exprs, string pluralName, string singularName)132 internal void Dump(IEnumerable<DbExpression> exprs, string pluralName, string singularName) 133 { 134 Begin(pluralName); 135 136 foreach (DbExpression expr in exprs) 137 { 138 Begin(singularName); 139 this.Dump(expr); 140 End(singularName); 141 } 142 143 End(pluralName); 144 } 145 146 /// <summary> 147 /// Dumps each Parameter metadata in the specified enumerable. The entire output is decorated with the "Parameters" 148 /// block name while each metadata element is decorated with the "Parameter" block name. 149 /// If the list is empty only the "Parameters" decoration start/end will appear. 150 /// </summary> 151 /// <param name="paramList">The enumerable list of Parameter metadata to dump</param> Dump(IEnumerable<FunctionParameter> paramList)152 internal void Dump(IEnumerable<FunctionParameter> paramList) 153 { 154 Begin("Parameters"); 155 foreach (FunctionParameter param in paramList) 156 { 157 Begin("Parameter", "Name", param.Name); 158 Dump(param.TypeUsage, "ParameterType"); 159 End("Parameter"); 160 } 161 End("Parameters"); 162 } 163 164 /// <summary> 165 /// Dumps the specified Type metadata instance with the specified decoration 166 /// </summary> 167 /// <param name="type">The Type metadata to dump</param> 168 /// <param name="name">The decorating block name</param> Dump(TypeUsage type, string name)169 internal void Dump(TypeUsage type, string name) 170 { 171 Begin(name); 172 Dump(type); 173 End(name); 174 } 175 176 /// <summary> 177 /// Dumps the specified Type metadata instance 178 /// </summary> 179 /// <param name="type">The Type metadata to dump</param> Dump(TypeUsage type)180 internal void Dump(TypeUsage type) 181 { 182 Dictionary<string, object> facetInfo = new Dictionary<string, object>(); 183 foreach (Facet facet in type.Facets) 184 { 185 facetInfo.Add(facet.Name, facet.Value); 186 } 187 188 Begin("TypeUsage", facetInfo); 189 Dump(type.EdmType); 190 End("TypeUsage"); 191 } 192 193 /// <summary> 194 /// Dumps the specified EDM type metadata instance with the specified decoration 195 /// </summary> 196 /// <param name="type">The type metadata to dump</param> 197 /// <param name="name">The decorating block name</param> Dump(EdmType type, string name)198 internal void Dump(EdmType type, string name) 199 { 200 Begin(name); 201 Dump(type); 202 End(name); 203 } 204 205 /// <summary> 206 /// Dumps the specified type metadata instance 207 /// </summary> 208 /// <param name="type">The type metadata to dump</param> Dump(EdmType type)209 internal void Dump(EdmType type) 210 { 211 Begin("EdmType", 212 "BuiltInTypeKind", Enum.GetName(typeof(BuiltInTypeKind), type.BuiltInTypeKind), 213 "Namespace", type.NamespaceName, 214 "Name", type.Name); 215 End("EdmType"); 216 } 217 218 /// <summary> 219 /// Dumps the specified Relation metadata instance with the specified decoration 220 /// </summary> 221 /// <param name="type">The Relation metadata to dump</param> 222 /// <param name="name">The decorating block name</param> Dump(RelationshipType type, string name)223 internal void Dump(RelationshipType type, string name) 224 { 225 Begin(name); 226 Dump(type); 227 End(name); 228 } 229 230 /// <summary> 231 /// Dumps the specified Relation metadata instance 232 /// </summary> 233 /// <param name="type">The Relation metadata to dump</param> Dump(RelationshipType type)234 internal void Dump(RelationshipType type) 235 { 236 Begin( 237 "RelationshipType", 238 "Namespace", type.NamespaceName, 239 "Name", 240 type.Name 241 ); 242 End("RelationshipType"); 243 } 244 245 /// <summary> 246 /// Dumps the specified EdmFunction metadata instance 247 /// </summary> 248 /// <param name="function">The EdmFunction metadata to dump.</param> Dump(EdmFunction function)249 internal void Dump(EdmFunction function) 250 { 251 Begin("Function", "Name", function.Name, "Namespace", function.NamespaceName); 252 Dump(function.Parameters); 253 if (function.ReturnParameters.Count == 1) 254 { 255 Dump(function.ReturnParameters[0].TypeUsage, "ReturnType"); 256 } 257 else 258 { 259 Begin("ReturnTypes"); 260 foreach (var returnParameter in function.ReturnParameters) 261 { 262 Dump(returnParameter.TypeUsage, returnParameter.Name); 263 } 264 End("ReturnTypes"); 265 } 266 End("Function"); 267 } 268 269 /// <summary> 270 /// Dumps the specified EdmProperty metadata instance 271 /// </summary> 272 /// <param name="prop">The EdmProperty metadata to dump</param> Dump(EdmProperty prop)273 internal void Dump(EdmProperty prop) 274 { 275 Begin("Property", "Name", prop.Name, "Nullable", prop.Nullable); 276 Dump(prop.DeclaringType, "DeclaringType"); 277 Dump(prop.TypeUsage, "PropertyType"); 278 End("Property"); 279 } 280 281 /// <summary> 282 /// Dumps the specified Relation End EdmMember metadata instance with the specified decoration 283 /// </summary> 284 /// <param name="end">The Relation End metadata to dump</param> 285 /// <param name="name">The decorating block name</param> Dump(RelationshipEndMember end, string name)286 internal void Dump(RelationshipEndMember end, string name) 287 { 288 Begin(name); 289 Begin( 290 "RelationshipEndMember", 291 "Name", end.Name, 292 //"IsParent", end.IsParent, 293 "RelationshipMultiplicity", Enum.GetName(typeof(RelationshipMultiplicity), end.RelationshipMultiplicity) 294 ); 295 Dump(end.DeclaringType, "DeclaringRelation"); 296 Dump(end.TypeUsage, "EndType"); 297 End("RelationshipEndMember"); 298 End(name); 299 } 300 301 /// <summary> 302 /// Dumps the specified Navigation Property EdmMember metadata instance with the specified decoration 303 /// </summary> 304 /// <param name="navProp">The Navigation Property metadata to dump</param> 305 /// <param name="name">The decorating block name</param> Dump(NavigationProperty navProp, string name)306 internal void Dump(NavigationProperty navProp, string name) 307 { 308 Begin(name); 309 Begin( 310 "NavigationProperty", 311 "Name", navProp.Name, 312 //"IsParent", end.IsParent, 313 "RelationshipTypeName", navProp.RelationshipType.FullName, 314 "ToEndMemberName", navProp.ToEndMember.Name 315 ); 316 Dump(navProp.DeclaringType, "DeclaringType"); 317 Dump(navProp.TypeUsage, "PropertyType"); 318 End("NavigationProperty"); 319 End(name); 320 } 321 322 #if METHOD_EXPRESSION 323 /// <summary> 324 /// Dumps the specified Method metadata instance 325 /// </summary> 326 /// <param name="meth">The Method metadata to dump</param> Dump(MethodMetadata meth)327 internal void Dump(MethodMetadata meth) 328 { 329 Begin("MethodMetadata", "Name", meth.Name, "IsStatic", meth.IsStatic); 330 Dump(meth.DefiningType, "DeclaringType"); 331 Dump(meth.Parameters); 332 Dump(meth.Type, "ReturnType"); 333 End("MethodMetadata"); 334 } 335 #endif 336 337 /// <summary> 338 /// Dumps the specified DbLambda instance 339 /// </summary> 340 /// <param name="lambda">The DbLambda to dump.</param> Dump(DbLambda lambda)341 internal void Dump(DbLambda lambda) 342 { 343 Begin("DbLambda"); 344 Dump(System.Linq.Enumerable.Cast<DbExpression>(lambda.Variables), "Variables", "Variable"); 345 Dump(lambda.Body, "Body"); 346 End("DbLambda"); 347 } 348 349 #endregion 350 351 #region Private Implementation Begin(DbExpression expr)352 private void Begin(DbExpression expr) 353 { 354 Begin(expr, new Dictionary<string, object>()); 355 } 356 Begin(DbExpression expr, Dictionary<string, object> attrs)357 private void Begin(DbExpression expr, Dictionary<string, object> attrs) 358 { 359 attrs.Add("DbExpressionKind", Enum.GetName(typeof(DbExpressionKind), expr.ExpressionKind)); 360 Begin(expr.GetType().Name, attrs); 361 Dump(expr.ResultType, "ResultType"); 362 } 363 Begin(DbExpression expr, string attributeName, object attributeValue)364 private void Begin(DbExpression expr, string attributeName, object attributeValue) 365 { 366 Dictionary<string, object> attrs = new Dictionary<string, object>(); 367 attrs.Add(attributeName, attributeValue); 368 Begin(expr, attrs); 369 } 370 Begin(string expr, string attributeName, object attributeValue)371 private void Begin(string expr, string attributeName, object attributeValue) 372 { 373 Dictionary<string, object> attrs = new Dictionary<string, object>(); 374 attrs.Add(attributeName, attributeValue); 375 Begin(expr, attrs); 376 } 377 Begin(string expr, string attributeName1, object attributeValue1, string attributeName2, object attributeValue2)378 private void Begin(string expr, 379 string attributeName1, 380 object attributeValue1, 381 string attributeName2, 382 object attributeValue2) 383 { 384 Dictionary<string, object> attrs = new Dictionary<string, object>(); 385 attrs.Add(attributeName1, attributeValue1); 386 attrs.Add(attributeName2, attributeValue2); 387 Begin(expr, attrs); 388 } 389 Begin(string expr, string attributeName1, object attributeValue1, string attributeName2, object attributeValue2, string attributeName3, object attributeValue3)390 private void Begin(string expr, 391 string attributeName1, 392 object attributeValue1, 393 string attributeName2, 394 object attributeValue2, 395 string attributeName3, 396 object attributeValue3) 397 { 398 Dictionary<string, object> attrs = new Dictionary<string, object>(); 399 attrs.Add(attributeName1, attributeValue1); 400 attrs.Add(attributeName2, attributeValue2); 401 attrs.Add(attributeName3, attributeValue3); 402 Begin(expr, attrs); 403 } 404 End(DbExpression expr)405 private void End(DbExpression expr) 406 { 407 End(expr.GetType().Name); 408 } 409 BeginUnary(DbUnaryExpression e)410 private void BeginUnary(DbUnaryExpression e) 411 { 412 Begin(e); 413 Begin("Argument"); 414 Dump(e.Argument); 415 End("Argument"); 416 } 417 BeginBinary(DbBinaryExpression e)418 private void BeginBinary(DbBinaryExpression e) 419 { 420 Begin(e); 421 Begin("Left"); 422 Dump(e.Left); 423 End("Left"); 424 Begin("Right"); 425 Dump(e.Right); 426 End("Right"); 427 } 428 #endregion 429 430 #region DbExpressionVisitor<DbExpression> Members 431 Visit(DbExpression e)432 public override void Visit(DbExpression e) 433 { 434 Begin(e); 435 End(e); 436 } 437 Visit(DbConstantExpression e)438 public override void Visit(DbConstantExpression e) 439 { 440 Dictionary<string, object> attrs = new Dictionary<string,object>(); 441 attrs.Add("Value", e.Value); 442 Begin(e, attrs); 443 End(e); 444 } 445 Visit(DbNullExpression e)446 public override void Visit(DbNullExpression e) 447 { 448 Begin(e); 449 End(e); 450 } 451 Visit(DbVariableReferenceExpression e)452 public override void Visit(DbVariableReferenceExpression e) 453 { 454 Dictionary<string, object> attrs = new Dictionary<string, object>(); 455 attrs.Add("VariableName", e.VariableName); 456 Begin(e, attrs); 457 End(e); 458 } 459 Visit(DbParameterReferenceExpression e)460 public override void Visit(DbParameterReferenceExpression e) 461 { 462 Dictionary<string, object> attrs = new Dictionary<string, object>(); 463 attrs.Add("ParameterName", e.ParameterName); 464 Begin(e, attrs); 465 End(e); 466 } 467 Visit(DbFunctionExpression e)468 public override void Visit(DbFunctionExpression e) 469 { 470 Begin(e); 471 Dump(e.Function); 472 Dump(e.Arguments, "Arguments", "Argument"); 473 End(e); 474 } 475 Visit(DbLambdaExpression expression)476 public override void Visit(DbLambdaExpression expression) 477 { 478 Begin(expression); 479 Dump(expression.Lambda); 480 Dump(expression.Arguments, "Arguments", "Argument"); 481 End(expression); 482 } 483 484 #if METHOD_EXPRESSION Visit(MethodExpression e)485 public override void Visit(MethodExpression e) 486 { 487 Begin(e); 488 Dump(e.Method); 489 Dump(e.Arguments, "Arguments", "Argument"); 490 if (e.Instance != null) 491 { 492 Dump(e.Instance, "Instance"); 493 } 494 End(e); 495 } 496 #endif 497 Visit(DbPropertyExpression e)498 public override void Visit(DbPropertyExpression e) 499 { 500 // 501 // Currently the DbPropertyExpression.EdmProperty member property may only be either: 502 // - EdmProperty 503 // - RelationshipEndMember 504 // - NavigationProperty 505 // 506 Begin(e); 507 RelationshipEndMember end = e.Property as RelationshipEndMember; 508 if (end != null) 509 { 510 Dump(end, "Property"); 511 } 512 else if (Helper.IsNavigationProperty(e.Property)) 513 { 514 Dump((NavigationProperty)e.Property, "Property"); 515 } 516 else 517 { 518 Dump((EdmProperty)e.Property); 519 } 520 521 if (e.Instance != null) 522 { 523 Dump(e.Instance, "Instance"); 524 } 525 End(e); 526 } 527 Visit(DbComparisonExpression e)528 public override void Visit(DbComparisonExpression e) 529 { 530 BeginBinary(e); 531 End(e); 532 } 533 Visit(DbLikeExpression e)534 public override void Visit(DbLikeExpression e) 535 { 536 Begin(e); 537 Dump(e.Argument, "Argument"); 538 Dump(e.Pattern, "Pattern"); 539 Dump(e.Escape, "Escape"); 540 End(e); 541 } 542 Visit(DbLimitExpression e)543 public override void Visit(DbLimitExpression e) 544 { 545 Begin(e, "WithTies", e.WithTies); 546 Dump(e.Argument, "Argument"); 547 Dump(e.Limit, "Limit"); 548 End(e); 549 } 550 Visit(DbIsNullExpression e)551 public override void Visit(DbIsNullExpression e) 552 { 553 BeginUnary(e); 554 End(e); 555 } 556 Visit(DbArithmeticExpression e)557 public override void Visit(DbArithmeticExpression e) 558 { 559 Begin(e); 560 Dump(e.Arguments, "Arguments", "Argument"); 561 End(e); 562 } 563 Visit(DbAndExpression e)564 public override void Visit(DbAndExpression e) 565 { 566 BeginBinary(e); 567 End(e); 568 } 569 Visit(DbOrExpression e)570 public override void Visit(DbOrExpression e) 571 { 572 BeginBinary(e); 573 End(e); 574 } 575 Visit(DbNotExpression e)576 public override void Visit(DbNotExpression e) 577 { 578 BeginUnary(e); 579 End(e); 580 } 581 Visit(DbDistinctExpression e)582 public override void Visit(DbDistinctExpression e) 583 { 584 BeginUnary(e); 585 End(e); 586 } 587 Visit(DbElementExpression e)588 public override void Visit(DbElementExpression e) 589 { 590 BeginUnary(e); 591 End(e); 592 } 593 Visit(DbIsEmptyExpression e)594 public override void Visit(DbIsEmptyExpression e) 595 { 596 BeginUnary(e); 597 End(e); 598 } 599 Visit(DbUnionAllExpression e)600 public override void Visit(DbUnionAllExpression e) 601 { 602 BeginBinary(e); 603 End(e); 604 } 605 Visit(DbIntersectExpression e)606 public override void Visit(DbIntersectExpression e) 607 { 608 BeginBinary(e); 609 End(e); 610 } 611 Visit(DbExceptExpression e)612 public override void Visit(DbExceptExpression e) 613 { 614 BeginBinary(e); 615 End(e); 616 } 617 Visit(DbTreatExpression e)618 public override void Visit(DbTreatExpression e) 619 { 620 BeginUnary(e); 621 End(e); 622 } 623 Visit(DbIsOfExpression e)624 public override void Visit(DbIsOfExpression e) 625 { 626 BeginUnary(e); 627 Dump(e.OfType, "OfType") ; 628 End(e); 629 } 630 Visit(DbCastExpression e)631 public override void Visit(DbCastExpression e) 632 { 633 BeginUnary(e); 634 End(e); 635 } 636 Visit(DbCaseExpression e)637 public override void Visit(DbCaseExpression e) 638 { 639 Begin(e); 640 Dump(e.When, "Whens", "When"); 641 Dump(e.Then, "Thens", "Then"); 642 Dump(e.Else, "Else"); 643 } 644 Visit(DbOfTypeExpression e)645 public override void Visit(DbOfTypeExpression e) 646 { 647 BeginUnary(e); 648 Dump(e.OfType, "OfType"); 649 End(e); 650 } 651 Visit(DbNewInstanceExpression e)652 public override void Visit(DbNewInstanceExpression e) 653 { 654 Begin(e); 655 Dump(e.Arguments, "Arguments", "Argument"); 656 if (e.HasRelatedEntityReferences) 657 { 658 Begin("RelatedEntityReferences"); 659 foreach (DbRelatedEntityRef relatedRef in e.RelatedEntityReferences) 660 { 661 Begin("DbRelatedEntityRef"); 662 Dump(relatedRef.SourceEnd, "SourceEnd"); 663 Dump(relatedRef.TargetEnd, "TargetEnd"); 664 Dump(relatedRef.TargetEntityReference, "TargetEntityReference"); 665 End("DbRelatedEntityRef"); 666 } 667 End("RelatedEntityReferences"); 668 } 669 End(e); 670 } 671 Visit(DbRelationshipNavigationExpression e)672 public override void Visit(DbRelationshipNavigationExpression e) 673 { 674 Begin(e); 675 Dump(e.NavigateFrom, "NavigateFrom"); 676 Dump(e.NavigateTo, "NavigateTo"); 677 Dump(e.Relationship, "Relationship"); 678 Dump(e.NavigationSource, "NavigationSource"); 679 End(e); 680 } 681 Visit(DbRefExpression e)682 public override void Visit(DbRefExpression e) 683 { 684 BeginUnary(e); 685 End(e); 686 } 687 Visit(DbDerefExpression e)688 public override void Visit(DbDerefExpression e) 689 { 690 BeginUnary(e); 691 End(e); 692 } 693 Visit(DbRefKeyExpression e)694 public override void Visit(DbRefKeyExpression e) 695 { 696 BeginUnary(e); 697 End(e); 698 } 699 Visit(DbEntityRefExpression e)700 public override void Visit(DbEntityRefExpression e) 701 { 702 BeginUnary(e); 703 End(e); 704 } 705 Visit(DbScanExpression e)706 public override void Visit(DbScanExpression e) 707 { 708 Begin(e); 709 Begin("Target", "Name", e.Target.Name, "Container", e.Target.EntityContainer.Name); 710 Dump(e.Target.ElementType, "TargetElementType"); 711 End("Target"); 712 End(e); 713 } 714 Visit(DbFilterExpression e)715 public override void Visit(DbFilterExpression e) 716 { 717 Begin(e); 718 Dump(e.Input, "Input"); 719 Dump(e.Predicate, "Predicate"); 720 End(e); 721 } 722 Visit(DbProjectExpression e)723 public override void Visit(DbProjectExpression e) 724 { 725 Begin(e); 726 Dump(e.Input, "Input"); 727 Dump(e.Projection, "Projection"); 728 End(e); 729 } 730 Visit(DbCrossJoinExpression e)731 public override void Visit(DbCrossJoinExpression e) 732 { 733 Begin(e); 734 Begin("Inputs"); 735 foreach (DbExpressionBinding binding in e.Inputs) 736 { 737 Dump(binding, "Input"); 738 } 739 End("Inputs"); 740 End(e); 741 } 742 Visit(DbJoinExpression e)743 public override void Visit(DbJoinExpression e) 744 { 745 Begin(e); 746 Dump(e.Left, "Left"); 747 Dump(e.Right, "Right"); 748 Dump(e.JoinCondition, "JoinCondition"); 749 End(e); 750 } 751 Visit(DbApplyExpression e)752 public override void Visit(DbApplyExpression e) 753 { 754 Begin(e); 755 Dump(e.Input, "Input"); 756 Dump(e.Apply, "Apply"); 757 End(e); 758 } 759 Visit(DbGroupByExpression e)760 public override void Visit(DbGroupByExpression e) 761 { 762 Begin(e); 763 Dump(e.Input, "Input"); 764 Dump(e.Keys, "Keys", "Key"); 765 Begin("Aggregates"); 766 foreach (DbAggregate agg in e.Aggregates) 767 { 768 DbFunctionAggregate funcAgg = agg as DbFunctionAggregate; 769 770 if (funcAgg != null) 771 { 772 Begin("DbFunctionAggregate"); 773 Dump(funcAgg.Function); 774 Dump(funcAgg.Arguments, "Arguments", "Argument"); 775 End("DbFunctionAggregate"); 776 } 777 else 778 { 779 DbGroupAggregate groupAgg = agg as DbGroupAggregate; 780 Debug.Assert(groupAgg != null, "Invalid DbAggregate"); 781 Begin("DbGroupAggregate"); 782 Dump(groupAgg.Arguments, "Arguments", "Argument"); 783 End("DbGroupAggregate"); 784 } 785 } 786 End("Aggregates"); 787 End(e); 788 } 789 Dump(IList<DbSortClause> sortOrder)790 protected virtual void Dump(IList<DbSortClause> sortOrder) 791 { 792 Begin("SortOrder"); 793 foreach (DbSortClause clause in sortOrder) 794 { 795 string collStr = clause.Collation; 796 if (null == collStr) 797 { 798 collStr = ""; 799 } 800 801 Begin("DbSortClause", "Ascending", clause.Ascending, "Collation", collStr); 802 Dump(clause.Expression, "Expression"); 803 End("DbSortClause"); 804 } 805 End("SortOrder"); 806 } 807 Visit(DbSkipExpression e)808 public override void Visit(DbSkipExpression e) 809 { 810 Begin(e); 811 Dump(e.Input, "Input"); 812 Dump(e.SortOrder); 813 Dump(e.Count, "Count"); 814 End(e); 815 } 816 Visit(DbSortExpression e)817 public override void Visit(DbSortExpression e) 818 { 819 Begin(e); 820 Dump(e.Input, "Input"); 821 Dump(e.SortOrder); 822 End(e); 823 } 824 Visit(DbQuantifierExpression e)825 public override void Visit(DbQuantifierExpression e) 826 { 827 Begin(e); 828 Dump(e.Input, "Input"); 829 Dump(e.Predicate, "Predicate"); 830 End(e); 831 } 832 833 #endregion 834 } 835 } 836