diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/ChildFactory.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/ChildFactory.cs
index 0eb6ad4f..682d5348 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/ChildFactory.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/ChildFactory.cs
@@ -45,12 +45,12 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
///
/// Returns the node sub type if the object can have sub types otehr wise returns empty string
///
- public abstract string GetNodeSubType(object context);
+ public abstract string GetNodeSubType(object smoObject, SmoQueryContext smoContext);
///
/// Returns the status of the object assigned to node. If the object doesn't spport status returns empty string
///
- public abstract string GetNodeStatus(object context);
+ public abstract string GetNodeStatus(object smoObject, SmoQueryContext smoContext);
///
/// Returns the custom name of the object assigned to the node. If the object doesn't have custom name, returns empty string
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeObservableCollection.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeObservableCollection.cs
index b7d8fad5..735ecffe 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeObservableCollection.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeObservableCollection.cs
@@ -3,6 +3,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
+using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@@ -29,6 +30,15 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
get { return numInits.HasValue && numInits != 0; }
}
+ public bool IsSorted
+ {
+ get
+ {
+ // SMO objects are already sorted so no need to sort them again
+ return this.FirstOrDefault() is SmoTreeNode;
+ }
+ }
+
public void BeginInit()
{
if (!numInits.HasValue)
@@ -54,7 +64,10 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
{
try
{
- DoSort();
+ if (!IsSorted)
+ {
+ DoSort();
+ }
if (deferredChildren != null)
{
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoChildFactoryBase.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoChildFactoryBase.cs
index 045f0a76..0cdb24fa 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoChildFactoryBase.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoChildFactoryBase.cs
@@ -17,6 +17,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
public class SmoChildFactoryBase : ChildFactory
{
+ private IEnumerable smoProperties;
public override IEnumerable ApplicableParents()
{
return null;
@@ -230,6 +231,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
}
else
{
+ smoProperties = SmoProperties;
SmoTreeNode childAsMeItem = (SmoTreeNode)child;
childAsMeItem.CacheInfoFromModel(smoObj);
SmoQueryContext smoContext = parent.GetContextAs();
@@ -241,8 +243,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
childAsMeItem.NodeValue = customizedName;
}
- childAsMeItem.NodeSubType = GetNodeSubType(context);
- childAsMeItem.NodeStatus = GetNodeStatus(context);
+ childAsMeItem.NodeSubType = GetNodeSubType(context, smoContext);
+ childAsMeItem.NodeStatus = GetNodeStatus(context, smoContext);
}
}
@@ -270,6 +272,14 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
}
}
+ internal IEnumerable CachedSmoProperties
+ {
+ get
+ {
+ return smoProperties == null ? SmoProperties : smoProperties;
+ }
+ }
+
///
/// Returns true if any final validation of the object to be added passes, and false
/// if validation fails. This provides a chance to filter specific items out of a list
@@ -282,16 +292,31 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
return true;
}
- public override string GetNodeSubType(object context)
+ public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
return string.Empty;
}
- public override string GetNodeStatus(object context)
+ public override string GetNodeStatus(object smoObject, SmoQueryContext smoContext)
{
return string.Empty;
}
+ public static bool IsPropertySupported(string propertyName, SmoQueryContext context, NamedSmoObject smoObj, IEnumerable supportedProperties)
+ {
+ var property = supportedProperties.FirstOrDefault(x => string.Compare(x.Name, propertyName, StringComparison.InvariantCultureIgnoreCase) == 0);
+ if (property != null)
+ {
+ return ServerVersionHelper.IsValidFor(context.ValidFor, property.ValidFor);
+ }
+ else
+ {
+ // Return true if cannot find the proeprty, SMO still tries to get that property but adding the property to supported list can make loading the nodes faster
+ Logger.Write(LogLevel.Verbose, $"Smo property name {propertyName} for Smo type {smoObj.GetType()} is not added as supported properties. This can cause the performance of loading the OE nodes");
+ return true;
+ }
+ }
+
public override string GetNodeCustomName(object smoObject, SmoQueryContext smoContext)
{
return string.Empty;
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoDatabaseCustomNode.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoDatabaseCustomNode.cs
index 700f87ff..b76ce5d5 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoDatabaseCustomNode.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoDatabaseCustomNode.cs
@@ -4,6 +4,8 @@
//
using Microsoft.SqlServer.Management.Smo;
+using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
+using System.Collections.Generic;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
@@ -12,21 +14,22 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
///
internal partial class DatabasesChildFactory : SmoChildFactoryBase
{
- public override string GetNodeStatus(object context)
+ public override string GetNodeStatus(object smoObject, SmoQueryContext smoContext)
{
- return DatabasesCustomNodeHelper.GetStatus(context);
+ return DatabasesCustomNodeHelper.GetStatus(smoObject, smoContext, CachedSmoProperties);
}
}
internal static class DatabasesCustomNodeHelper
{
- internal static string GetStatus(object context)
+ internal static string GetStatus(object smoObject, SmoQueryContext smoContext, IEnumerable supportedProperties)
{
- Database db = context as Database;
- if (db != null)
+ Database db = smoObject as Database;
+ if (db != null && SmoChildFactoryBase.IsPropertySupported("Status", smoContext, db, supportedProperties))
{
DatabaseStatus status;
- try {
+ try
+ {
status = db.Status;
}
catch (SqlServer.Management.Common.ConnectionFailureException)
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoKeyCustomNode.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoKeyCustomNode.cs
index 9a9cafe3..cf852806 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoKeyCustomNode.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoKeyCustomNode.cs
@@ -12,9 +12,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
///
internal partial class KeysChildFactory : SmoChildFactoryBase
{
- public override string GetNodeSubType(object context)
+ public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
- return IndexCustomeNodeHelper.GetSubType(context);
+ return IndexCustomeNodeHelper.GetSubType(smoObject);
}
}
@@ -23,9 +23,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
///
internal partial class IndexesChildFactory : SmoChildFactoryBase
{
- public override string GetNodeSubType(object context)
+ public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
- return IndexCustomeNodeHelper.GetSubType(context);
+ return IndexCustomeNodeHelper.GetSubType(smoObject);
}
public override string GetNodeCustomName(object smoObject, SmoQueryContext smoContext)
@@ -39,9 +39,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
///
internal partial class UserDefinedTableTypeKeysChildFactory : SmoChildFactoryBase
{
- public override string GetNodeSubType(object context)
+ public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
- return IndexCustomeNodeHelper.GetSubType(context);
+ return IndexCustomeNodeHelper.GetSubType(smoObject);
}
}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoLoginCustomNode.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoLoginCustomNode.cs
index 524fa6fa..64a3b453 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoLoginCustomNode.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoLoginCustomNode.cs
@@ -12,9 +12,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
///
internal partial class ServerLevelLoginsChildFactory : SmoChildFactoryBase
{
- public override string GetNodeStatus(object context)
+ public override string GetNodeStatus(object smoObject, SmoQueryContext smoContext)
{
- return LoginCustomNodeHelper.GetStatus(context);
+ return LoginCustomNodeHelper.GetStatus(smoObject);
}
}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoParamterCustomNode.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoParamterCustomNode.cs
index 61671445..7c8ef0a3 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoParamterCustomNode.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoParamterCustomNode.cs
@@ -18,9 +18,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
return ParameterCustomeNodeHelper.GetCustomLabel(smoObject, smoContext);
}
- public override string GetNodeSubType(object context)
+ public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
- return ParameterCustomeNodeHelper.GetSubType(context);
+ return ParameterCustomeNodeHelper.GetSubType(smoObject);
}
}
@@ -33,9 +33,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
return ParameterCustomeNodeHelper.GetCustomLabel(smoObject, smoContext);
}
- public override string GetNodeSubType(object context)
+ public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
- return ParameterCustomeNodeHelper.GetSubType(context);
+ return ParameterCustomeNodeHelper.GetSubType(smoObject);
}
}
@@ -48,9 +48,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
return ParameterCustomeNodeHelper.GetCustomLabel(smoObject, smoContext);
}
- public override string GetNodeSubType(object context)
+ public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
- return ParameterCustomeNodeHelper.GetSubType(context);
+ return ParameterCustomeNodeHelper.GetSubType(smoObject);
}
}
@@ -63,9 +63,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
return ParameterCustomeNodeHelper.GetCustomLabel(smoObject, smoContext);
}
- public override string GetNodeSubType(object context)
+ public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
- return ParameterCustomeNodeHelper.GetSubType(context);
+ return ParameterCustomeNodeHelper.GetSubType(smoObject);
}
}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTableCustomNode.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTableCustomNode.cs
index 08710c8e..314ae07f 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTableCustomNode.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTableCustomNode.cs
@@ -17,7 +17,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
try
{
Table table = smoObject as Table;
- if (table != null && table.IsSystemVersioned)
+ if (table != null && IsPropertySupported("IsSystemVersioned", smoContext, table, CachedSmoProperties) && table.IsSystemVersioned)
{
return $"{table.Schema}.{table.Name} ({SR.SystemVersioned_LabelPart})";
}
@@ -30,12 +30,12 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
return string.Empty;
}
- public override string GetNodeSubType(object context)
+ public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
try
{
- Table table = context as Table;
- if (table != null && table.TemporalType != TableTemporalType.None)
+ Table table = smoObject as Table;
+ if (table != null && IsPropertySupported("TemporalType", smoContext, table, CachedSmoProperties) && table.TemporalType != TableTemporalType.None)
{
return "Temporal";
}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTriggerCustomNode.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTriggerCustomNode.cs
index e663ec84..48d07579 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTriggerCustomNode.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTriggerCustomNode.cs
@@ -12,25 +12,25 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
///
internal partial class TriggersChildFactory : SmoChildFactoryBase
{
- public override string GetNodeStatus(object context)
+ public override string GetNodeStatus(object smoObject, SmoQueryContext smoContext)
{
- return TriggersCustomeNodeHelper.GetStatus(context);
+ return TriggersCustomeNodeHelper.GetStatus(smoObject);
}
}
internal partial class ServerLevelServerTriggersChildFactory : SmoChildFactoryBase
{
- public override string GetNodeStatus(object context)
+ public override string GetNodeStatus(object smoObject, SmoQueryContext smoContext)
{
- return TriggersCustomeNodeHelper.GetStatus(context);
+ return TriggersCustomeNodeHelper.GetStatus(smoObject);
}
}
internal partial class DatabaseTriggersChildFactory : SmoChildFactoryBase
{
- public override string GetNodeStatus(object context)
+ public override string GetNodeStatus(object smoObject, SmoQueryContext smoContext)
{
- return TriggersCustomeNodeHelper.GetStatus(context);
+ return TriggersCustomeNodeHelper.GetStatus(smoObject);
}
}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoUserCustomNode.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoUserCustomNode.cs
index cb7593ca..9d969fd8 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoUserCustomNode.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoUserCustomNode.cs
@@ -12,9 +12,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
///
internal partial class UsersChildFactory : SmoChildFactoryBase
{
- public override string GetNodeStatus(object context)
+ public override string GetNodeStatus(object smoObject, SmoQueryContext smoContext)
{
- return UserCustomeNodeHelper.GetStatus(context);
+ return UserCustomeNodeHelper.GetStatus(smoObject);
}
}
diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/Baselines/AllSqlObjects.txt b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/Baselines/AllSqlObjects.txt
index 4a8f81a1..4ae253fd 100644
--- a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/Baselines/AllSqlObjects.txt
+++ b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/Baselines/AllSqlObjects.txt
@@ -33,8 +33,8 @@ NodeType: Column Label: SickLeaveHours (smallint, not null) SubType: Status:
NodeType: Column Label: CurrentFlag (Flag(bit), not null) SubType: Status:
NodeType: Column Label: rowguid (uniqueidentifier, not null) SubType: Status:
NodeType: Column Label: ModifiedDate (datetime, not null) SubType: Status:
-NodeType: Key Label: FK_Employee_Person_BusinessEntityID SubType:ForeignKey Status:
NodeType: Key Label: PK_Employee_BusinessEntityID SubType:PrimaryKey Status:
+NodeType: Key Label: FK_Employee_Person_BusinessEntityID SubType:ForeignKey Status:
NodeType: Constraint Label: CK_Employee_BirthDate SubType: Status:
NodeType: Constraint Label: CK_Employee_Gender SubType: Status:
NodeType: Constraint Label: CK_Employee_HireDate SubType: Status:
@@ -156,7 +156,6 @@ NodeType: DatabaseRole Label: db_securityadmin SubType: Status:
NodeType: DatabaseRole Label: public SubType: Status:
NodeType: DatabaseRole Label: SalesManagers SubType: Status:
NodeType: DatabaseRole Label: SalesPersons SubType: Status:
-NodeType: Schema Label: dbo SubType: Status:
NodeType: Schema Label: db_accessadmin SubType: Status:
NodeType: Schema Label: db_backupoperator SubType: Status:
NodeType: Schema Label: db_datareader SubType: Status:
@@ -166,6 +165,7 @@ NodeType: Schema Label: db_denydatareader SubType: Status:
NodeType: Schema Label: db_denydatawriter SubType: Status:
NodeType: Schema Label: db_owner SubType: Status:
NodeType: Schema Label: db_securityadmin SubType: Status:
+NodeType: Schema Label: dbo SubType: Status:
NodeType: Schema Label: Demo SubType: Status:
NodeType: Schema Label: guest SubType: Status:
NodeType: Schema Label: HumanResources SubType: Status: