diff --git a/src/Microsoft.Kusto.ServiceLayer/DataSource/DataSourceBase.cs b/src/Microsoft.Kusto.ServiceLayer/DataSource/DataSourceBase.cs
index 5f11d3a4..730f952a 100644
--- a/src/Microsoft.Kusto.ServiceLayer/DataSource/DataSourceBase.cs
+++ b/src/Microsoft.Kusto.ServiceLayer/DataSource/DataSourceBase.cs
@@ -77,8 +77,9 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
///
public abstract IEnumerable GetChildObjects(DataSourceObjectMetadata parentMetadata, bool includeSizeDetails = false);
+ ///
///
- public abstract void Refresh();
+ public abstract void Refresh(bool includeDatabase);
///
public abstract void Refresh(DataSourceObjectMetadata objectMetadata);
diff --git a/src/Microsoft.Kusto.ServiceLayer/DataSource/IDataSource.cs b/src/Microsoft.Kusto.ServiceLayer/DataSource/IDataSource.cs
index 0accf989..7f8988f4 100644
--- a/src/Microsoft.Kusto.ServiceLayer/DataSource/IDataSource.cs
+++ b/src/Microsoft.Kusto.ServiceLayer/DataSource/IDataSource.cs
@@ -73,7 +73,8 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
///
/// Refresh object list for entire cluster.
///
- void Refresh();
+ ///
+ void Refresh(bool includeDatabase);
///
/// Refresh object list for given object.
diff --git a/src/Microsoft.Kusto.ServiceLayer/DataSource/KustoDataSource.cs b/src/Microsoft.Kusto.ServiceLayer/DataSource/KustoDataSource.cs
index 7c655ac5..29ef5f13 100644
--- a/src/Microsoft.Kusto.ServiceLayer/DataSource/KustoDataSource.cs
+++ b/src/Microsoft.Kusto.ServiceLayer/DataSource/KustoDataSource.cs
@@ -347,40 +347,45 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
{
if (_databaseMetadata == null)
{
- CancellationTokenSource source = new CancellationTokenSource();
- CancellationToken token = source.Token;
-
- // Getting database names when we are connected to a specific database should not happen.
- ValidationUtils.IsNotNull(DatabaseName, nameof(DatabaseName));
-
- var query = ".show databases" + (this.ClusterName.IndexOf(AriaProxyURL, StringComparison.CurrentCultureIgnoreCase) == -1 ? " | project DatabaseName, PrettyName" : "");
-
- if (includeSizeDetails == true){
- query = ".show cluster extents | summarize sum(OriginalSize) by tostring(DatabaseName)";
- }
-
- using (var reader = ExecuteQuery(query, token))
- {
- _databaseMetadata = reader.ToEnumerable()
- .Where(row => !string.IsNullOrWhiteSpace(row["DatabaseName"].ToString()))
- .Select(row => new DatabaseMetadata
- {
- ClusterName = this.ClusterName,
- MetadataType = DataSourceMetadataType.Database,
- MetadataTypeName = DataSourceMetadataType.Database.ToString(),
- SizeInMB = includeSizeDetails == true ? row["sum_OriginalSize"].ToString() : null,
- Name = row["DatabaseName"].ToString(),
- PrettyName = includeSizeDetails == true ? row["DatabaseName"].ToString(): (String.IsNullOrEmpty(row["PrettyName"]?.ToString()) ? row["DatabaseName"].ToString() : row["PrettyName"].ToString()),
- Urn = $"{this.ClusterName}.{row["DatabaseName"].ToString()}"
- })
- .Materialize()
- .OrderBy(row => row.Name, StringComparer.Ordinal); // case-sensitive
- }
+ SetDatabaseMetadata(includeSizeDetails);
}
return _databaseMetadata;
}
+ private void SetDatabaseMetadata(bool includeSizeDetails)
+ {
+ CancellationTokenSource source = new CancellationTokenSource();
+ CancellationToken token = source.Token;
+
+ // Getting database names when we are connected to a specific database should not happen.
+ ValidationUtils.IsNotNull(DatabaseName, nameof(DatabaseName));
+
+ var query = ".show databases" + (this.ClusterName.IndexOf(AriaProxyURL, StringComparison.CurrentCultureIgnoreCase) == -1 ? " | project DatabaseName, PrettyName" : "");
+
+ if (includeSizeDetails == true){
+ query = ".show cluster extents | summarize sum(OriginalSize) by tostring(DatabaseName)";
+ }
+
+ using (var reader = ExecuteQuery(query, token))
+ {
+ _databaseMetadata = reader.ToEnumerable()
+ .Where(row => !string.IsNullOrWhiteSpace(row["DatabaseName"].ToString()))
+ .Select(row => new DatabaseMetadata
+ {
+ ClusterName = this.ClusterName,
+ MetadataType = DataSourceMetadataType.Database,
+ MetadataTypeName = DataSourceMetadataType.Database.ToString(),
+ SizeInMB = includeSizeDetails == true ? row["sum_OriginalSize"].ToString() : null,
+ Name = row["DatabaseName"].ToString(),
+ PrettyName = includeSizeDetails == true ? row["DatabaseName"].ToString(): (String.IsNullOrEmpty(row["PrettyName"]?.ToString()) ? row["DatabaseName"].ToString() : row["PrettyName"].ToString()),
+ Urn = $"{this.ClusterName}.{row["DatabaseName"].ToString()}"
+ })
+ .Materialize()
+ .OrderBy(row => row.Name, StringComparer.Ordinal); // case-sensitive
+ }
+ }
+
///
public override bool Exists(DataSourceObjectMetadata objectMetadata)
{
@@ -509,11 +514,17 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
return markers.ToArray();
}
- ///
- public override void Refresh()
+ ///
+ /// Clears everything
+ ///
+ ///
+ public override void Refresh(bool includeDatabase)
{
// This class caches objects. Throw them away so that the next call will re-query the data source for the objects.
- _databaseMetadata = null;
+ if (includeDatabase)
+ {
+ _databaseMetadata = null;
+ }
_tableMetadata = new ConcurrentDictionary>();
_columnMetadata = new ConcurrentDictionary>();
_folderMetadata = new ConcurrentDictionary>();
@@ -528,49 +539,45 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
switch(objectMetadata.MetadataType)
{
case DataSourceMetadataType.Cluster:
- Refresh();
+ Refresh(true);
+ SetDatabaseMetadata(false);
break;
-
+
case DataSourceMetadataType.Database:
- _tableMetadata.TryRemove(objectMetadata.Name, out _);
+ Refresh(false);
+ LoadTableSchema(objectMetadata);
+ LoadFunctionSchema(objectMetadata);
break;
case DataSourceMetadataType.Table:
- var tm = objectMetadata as TableMetadata;
- _columnMetadata.TryRemove(GenerateMetadataKey(tm.DatabaseName, tm.Name), out _);
+ var table = objectMetadata as TableMetadata;
+ _columnMetadata.TryRemove(GenerateMetadataKey(table.DatabaseName, table.Name), out _);
+ SetTableSchema(table);
break;
- case DataSourceMetadataType.Column:
- // Remove column metadata for the whole table
- var cm = objectMetadata as ColumnMetadata;
- _columnMetadata.TryRemove(GenerateMetadataKey(cm.DatabaseName, cm.TableName), out _);
- break;
-
- case DataSourceMetadataType.Function:
- var fm = objectMetadata as FunctionMetadata;
- _functionMetadata.TryRemove(GenerateMetadataKey(fm.DatabaseName, fm.Name), out _);
- break;
-
case DataSourceMetadataType.Folder:
+ Refresh(false);
var folder = objectMetadata as FolderMetadata;
- _folderMetadata.TryRemove(GenerateMetadataKey(folder.ParentMetadata.Name, folder.Name), out _);
+ LoadTableSchema(folder.ParentMetadata);
+ LoadFunctionSchema(folder.ParentMetadata);
break;
-
+
default:
throw new ArgumentException($"Unexpected type {objectMetadata.MetadataType}.");
}
}
///
- public override IEnumerable GetChildObjects(DataSourceObjectMetadata objectMetadata, bool includeSizeDetails)
+ public override IEnumerable GetChildObjects(DataSourceObjectMetadata objectMetadata,
+ bool includeSizeDetails = false)
{
ValidationUtils.IsNotNull(objectMetadata, nameof(objectMetadata));
- switch(objectMetadata.MetadataType)
+ switch (objectMetadata.MetadataType)
{
case DataSourceMetadataType.Cluster: // show databases
return GetDatabaseMetadata(includeSizeDetails);
-
+
case DataSourceMetadataType.Database: // show folders, tables, and functions
return includeSizeDetails
? GetTablesForDashboard(objectMetadata)
@@ -589,7 +596,7 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
}
}
- public override DiagnosticsInfo GetDiagnostics(DataSourceObjectMetadata objectMetadata)
+ public override DiagnosticsInfo GetDiagnostics(DataSourceObjectMetadata objectMetadata)
{
ValidationUtils.IsNotNull(objectMetadata, nameof(objectMetadata));
@@ -765,16 +772,23 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
return _columnMetadata[key];
}
+ SetTableSchema(tableMetadata);
+
+ return _columnMetadata.ContainsKey(key)
+ ? _columnMetadata[key]
+ : Enumerable.Empty();
+ }
+
+ private void SetTableSchema(TableMetadata tableMetadata)
+ {
IEnumerable columnInfos = GetColumnInfos(tableMetadata.DatabaseName, tableMetadata.Name);
if (!columnInfos.Any())
{
- return Enumerable.Empty();
+ return;
}
SetColumnMetadata(tableMetadata.DatabaseName, tableMetadata.Name, columnInfos);
-
- return _columnMetadata[key];
}
private void SetFolderMetadataForTables(DataSourceObjectMetadata objectMetadata, IEnumerable tableInfos, string rootTableFolderKey)
diff --git a/src/Microsoft.Kusto.ServiceLayer/Microsoft.Kusto.ServiceLayer.csproj b/src/Microsoft.Kusto.ServiceLayer/Microsoft.Kusto.ServiceLayer.csproj
index 2d5d038b..fcff7eec 100644
--- a/src/Microsoft.Kusto.ServiceLayer/Microsoft.Kusto.ServiceLayer.csproj
+++ b/src/Microsoft.Kusto.ServiceLayer/Microsoft.Kusto.ServiceLayer.csproj
@@ -36,7 +36,7 @@
-
+
diff --git a/src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/SmoModel/NodePathGenerator.cs b/src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/DataSourceModel/NodePathGenerator.cs
similarity index 100%
rename from src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/SmoModel/NodePathGenerator.cs
rename to src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/DataSourceModel/NodePathGenerator.cs
diff --git a/src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/SmoModel/ServerNode.cs b/src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/DataSourceModel/ServerNode.cs
similarity index 98%
rename from src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/SmoModel/ServerNode.cs
rename to src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/DataSourceModel/ServerNode.cs
index 3b8562fb..afad6d11 100644
--- a/src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/SmoModel/ServerNode.cs
+++ b/src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/DataSourceModel/ServerNode.cs
@@ -47,7 +47,7 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.DataSourceModel
///
/// Returns the label to display to the user.
///
- internal string GetConnectionLabel()
+ private string GetConnectionLabel()
{
string userName = connectionSummary.UserName;
diff --git a/src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryContext.cs b/src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/DataSourceModel/SmoQueryContext.cs
similarity index 100%
rename from src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryContext.cs
rename to src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/DataSourceModel/SmoQueryContext.cs
diff --git a/src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/SmoModel/SmoTreeNode.cs b/src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/DataSourceModel/SmoTreeNode.cs
similarity index 100%
rename from src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/SmoModel/SmoTreeNode.cs
rename to src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/DataSourceModel/SmoTreeNode.cs
diff --git a/src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeDefinition.xml b/src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/DataSourceModel/TreeNodeDefinition.xml
similarity index 100%
rename from src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeDefinition.xml
rename to src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/DataSourceModel/TreeNodeDefinition.xml
diff --git a/src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs b/src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs
index b3be72d5..86d2a09f 100644
--- a/src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs
+++ b/src/Microsoft.Kusto.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs
@@ -30,7 +30,7 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.Nodes
private string nodePath;
private string label;
private string nodePathName;
- public const char PathPartSeperator = '/';
+ private const char PathPartSeperator = '/';
///
/// Object metadata
@@ -43,27 +43,17 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.Nodes
public IDataSource DataSource { get; set; }
///
- /// Constructor with no required inputs
+ /// Constructor with DataSource and DataSourceObjectMetadata
///
- public TreeNode(IDataSource dataSource, DataSourceObjectMetadata objectMetadata)
+ ///
+ ///
+ protected TreeNode(IDataSource dataSource, DataSourceObjectMetadata objectMetadata)
{
DataSource = dataSource;
ObjectMetadata = objectMetadata;
NodeValue = objectMetadata.Name;
}
- ///
- /// Constructor that accepts a label to identify the node
- ///
- /// Label identifying the node
- public TreeNode(string value, IDataSource dataSource, DataSourceObjectMetadata objectMetadata)
- : this(dataSource, objectMetadata)
- {
- // We intentionally do not valid this being null or empty since
- // some nodes may need to set it
- NodeValue = value;
- }
-
private object buildingMetadataLock = new object();
///
@@ -133,7 +123,7 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.Nodes
/// for many nodes such as the server, the display label will be different
/// to the value.
///
- public string Label {
+ protected string Label {
get
{
if(label == null)
@@ -290,17 +280,6 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.Nodes
return new ReadOnlyCollection(children);
}
- ///
- /// Adds a child to the list of children under this node
- ///
- ///
- public void AddChild(TreeNode newChild)
- {
- Validate.IsNotNull(nameof(newChild), newChild);
- children.Add(newChild);
- newChild.Parent = this;
- }
-
///
/// Optional context to help with lookup of children
///
@@ -326,7 +305,7 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.Nodes
return Parent as T;
}
- protected virtual void PopulateChildren(bool refresh, string name, CancellationToken cancellationToken)
+ protected void PopulateChildren(bool refresh, string name, CancellationToken cancellationToken)
{
Logger.Write(TraceEventType.Verbose, string.Format(CultureInfo.InvariantCulture, "Populating oe node :{0}", this.GetNodePath()));
Debug.Assert(IsAlwaysLeaf == false);
@@ -368,25 +347,22 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.Nodes
}
}
- protected IEnumerable ExpandChildren(TreeNode parent, bool refresh, string name, bool includeSystemObjects, CancellationToken cancellationToken)
+ protected IEnumerable ExpandChildren(TreeNode parent, bool refresh, string name,
+ bool includeSystemObjects, CancellationToken cancellationToken)
{
- List allChildren = new List();
-
try
{
- OnExpandPopulateNonFolders(allChildren, parent, refresh, name, cancellationToken);
+ return OnExpandPopulateNonFolders(parent, refresh, name, cancellationToken);
}
- catch(Exception ex)
+ catch (Exception ex)
{
- string error = string.Format(CultureInfo.InvariantCulture, "Failed expanding oe children. parent:{0} error:{1} inner:{2} stacktrace:{3}",
- parent != null ? parent.GetNodePath() : "", ex.Message, ex.InnerException != null ? ex.InnerException.Message : "", ex.StackTrace);
+ string error = string.Format(CultureInfo.InvariantCulture,
+ "Failed expanding oe children. parent:{0} error:{1} inner:{2} stacktrace:{3}",
+ parent != null ? parent.GetNodePath() : "", ex.Message,
+ ex.InnerException != null ? ex.InnerException.Message : "", ex.StackTrace);
Logger.Write(TraceEventType.Error, error);
throw ex;
}
- finally
- {
- }
- return allChildren;
}
///
@@ -394,7 +370,7 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.Nodes
///
/// List to which nodes should be added
/// Parent the nodes are being added to
- private void OnExpandPopulateNonFolders(IList allChildren, TreeNode parent, bool refresh, string name, CancellationToken cancellationToken)
+ private List OnExpandPopulateNonFolders(TreeNode parent, bool refresh, string name, CancellationToken cancellationToken)
{
Logger.Write(TraceEventType.Verbose, string.Format(CultureInfo.InvariantCulture, "child factory parent :{0}", parent.GetNodePath()));
@@ -406,9 +382,15 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.Nodes
if (parent.DataSource != null)
{
+ if (refresh)
+ {
+ parent.DataSource.Refresh(parent.ObjectMetadata);
+ }
+
objectMetadataList = parent.DataSource.GetChildObjects(parent.ObjectMetadata);
}
+ List allChildren = new List();
foreach (var objectMetadata in objectMetadataList)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -423,6 +405,7 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.Nodes
}
}
+ return allChildren;
}
catch (Exception ex)
{
@@ -436,7 +419,12 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.Nodes
///
/// The glue between the DataSource and the Object Explorer models. Creates the right tree node for each data source type
///
- protected TreeNode CreateChild(TreeNode parent, DataSourceObjectMetadata childMetadata)
+ ///
+ ///
+ ///
+ ///
+
+ private TreeNode CreateChild(TreeNode parent, DataSourceObjectMetadata childMetadata)
{
ValidationUtils.IsNotNull(parent, nameof(parent));
ValidationUtils.IsNotNull(childMetadata, nameof(childMetadata));
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Microsoft.SqlTools.ServiceLayer.csproj b/src/Microsoft.SqlTools.ServiceLayer/Microsoft.SqlTools.ServiceLayer.csproj
index 203eeaea..e878c991 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Microsoft.SqlTools.ServiceLayer.csproj
+++ b/src/Microsoft.SqlTools.ServiceLayer/Microsoft.SqlTools.ServiceLayer.csproj
@@ -33,7 +33,6 @@
-
diff --git a/test/Microsoft.Kusto.ServiceLayer.UnitTests/ObjectExplorer/DataSourceModel/ServerNodeTests.cs b/test/Microsoft.Kusto.ServiceLayer.UnitTests/ObjectExplorer/DataSourceModel/ServerNodeTests.cs
new file mode 100644
index 00000000..4407226f
--- /dev/null
+++ b/test/Microsoft.Kusto.ServiceLayer.UnitTests/ObjectExplorer/DataSourceModel/ServerNodeTests.cs
@@ -0,0 +1,160 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using Microsoft.Kusto.ServiceLayer.Connection.Contracts;
+using Microsoft.Kusto.ServiceLayer.DataSource;
+using Microsoft.Kusto.ServiceLayer.DataSource.Metadata;
+using Microsoft.Kusto.ServiceLayer.ObjectExplorer.DataSourceModel;
+using Microsoft.Kusto.ServiceLayer.ObjectExplorer.Nodes;
+using Microsoft.Kusto.ServiceLayer.Utility;
+using Microsoft.SqlTools.Extensibility;
+using Moq;
+using NUnit.Framework;
+
+namespace Microsoft.Kusto.ServiceLayer.UnitTests.ObjectExplorer.DataSourceModel
+{
+ public class ServerNodeTests
+ {
+ [Test]
+ public void ServerNode_ThrowsException_NullConnectionParam()
+ {
+ ConnectionCompleteParams param = null;
+ var serviceProviderMock = new Mock();
+
+ Assert.Throws(() => new ServerNode(param, serviceProviderMock.Object, null, new DatabaseMetadata()));
+ }
+
+ [Test]
+ public void ServerNode_ThrowsException_NullConnectionSummary()
+ {
+ var param = new ConnectionCompleteParams
+ {
+ ConnectionSummary = null
+ };
+
+ var serviceProviderMock = new Mock();
+
+ Assert.Throws(() => new ServerNode(param, serviceProviderMock.Object, null, new DatabaseMetadata()));
+ }
+
+ [Test]
+ public void ServerNode_ThrowsException_NullServiceProvider()
+ {
+ var param = new ConnectionCompleteParams
+ {
+ ConnectionSummary = new ConnectionSummary()
+ };
+
+ Assert.Throws(() => new ServerNode(param, null, null, new DatabaseMetadata()));
+ }
+
+ [TestCase(CommonConstants.MasterDatabaseName, "User1", "Server Name (SQL Server 2020 - User1)")]
+ [TestCase(CommonConstants.MasterDatabaseName, "", "Server Name (SQL Server 2020)")]
+ [TestCase(CommonConstants.MsdbDatabaseName, "User2", "Server Name (SQL Server 2020 - User2)")]
+ [TestCase(CommonConstants.MsdbDatabaseName, "", "Server Name (SQL Server 2020)")]
+ [TestCase(CommonConstants.ModelDatabaseName, "User3", "Server Name (SQL Server 2020 - User3)")]
+ [TestCase(CommonConstants.ModelDatabaseName, "", "Server Name (SQL Server 2020)")]
+ [TestCase(CommonConstants.TempDbDatabaseName, "User4", "Server Name (SQL Server 2020 - User4)")]
+ [TestCase(CommonConstants.TempDbDatabaseName, "", "Server Name (SQL Server 2020)")]
+ [TestCase("Database1", "User5", "Server Name (SQL Server 2020 - User5, Database1)")]
+ [TestCase("Database1", "", "Server Name (SQL Server 2020 - Database1)")]
+ public void GetConnectionLabel_Sets_Label_For_Params(string databaseName, string userName, string expected)
+ {
+ var connectionParams = new ConnectionCompleteParams
+ {
+ ConnectionSummary = new ConnectionSummary
+ {
+ DatabaseName = databaseName,
+ UserName = userName,
+ ServerName = "Server Name"
+ },
+ ServerInfo = new ServerInfo
+ {
+ ServerVersion = "2020"
+ }
+ };
+
+ var serviceProviderMock = new Mock();
+ var dataSourceMock = new Mock();
+ var metadata = new DataSourceObjectMetadata();
+
+ var serverNode = new ServerNode(connectionParams, serviceProviderMock.Object, dataSourceMock.Object,
+ metadata);
+
+ var nodeInfo = serverNode.ToNodeInfo();
+ Assert.AreEqual(expected, nodeInfo.Label);
+ }
+
+ [Test]
+ public void Refresh_Calls_DataSourceRefresh()
+ {
+ var connectionParams = new ConnectionCompleteParams
+ {
+ ConnectionSummary = new ConnectionSummary
+ {
+ UserName = "UserName",
+ DatabaseName = "DatabaseName",
+ ServerName = "ServerName"
+ },
+ ServerInfo = new ServerInfo
+ {
+ ServerVersion = "Version"
+ }
+ };
+
+ var serviceProviderMock = new Mock();
+ var dataSourceMock = new Mock();
+ var metadata = new DataSourceObjectMetadata();
+
+ var serverNode = new ServerNode(connectionParams, serviceProviderMock.Object, dataSourceMock.Object,
+ metadata);
+
+ serverNode.Refresh(CancellationToken.None);
+
+ dataSourceMock.Verify(x => x.Refresh(It.IsAny()), Times.Once());
+ }
+
+ [Test]
+ public void Refresh_Returns_Children()
+ {
+ var childMetadata = new DataSourceObjectMetadata
+ {
+ MetadataTypeName = DataSourceMetadataType.Database.ToString(),
+ MetadataType = DataSourceMetadataType.Database,
+ Name = "Database1"
+ };
+
+ var connectionParams = new ConnectionCompleteParams
+ {
+ ConnectionSummary = new ConnectionSummary
+ {
+ UserName = "UserName",
+ DatabaseName = "DatabaseName",
+ ServerName = "ServerName"
+ },
+ ServerInfo = new ServerInfo
+ {
+ ServerVersion = "Version"
+ }
+ };
+
+ var serviceProviderMock = new Mock();
+ var dataSourceMock = new Mock();
+ dataSourceMock.Setup(x => x.GetChildObjects(It.IsAny(), It.IsAny()))
+ .Returns(new List {childMetadata});
+
+ var parentMetadata = new DataSourceObjectMetadata();
+ var serverNode = new ServerNode(connectionParams, serviceProviderMock.Object, dataSourceMock.Object,
+ parentMetadata);
+
+ var children = serverNode.Refresh(CancellationToken.None);
+ Assert.AreEqual(1, children.Count);
+ var child = children.First();
+
+ Assert.AreEqual(childMetadata.MetadataTypeName, child.NodeType);
+ Assert.AreEqual(NodeTypes.Database, child.NodeTypeId);
+ Assert.AreEqual(childMetadata.Name, child.NodeValue);
+ }
+ }
+}
\ No newline at end of file