diff --git a/.hgignore b/.gitignore
similarity index 91%
rename from .hgignore
rename to .gitignore
index d6bb857d9..745e2f88f 100644
--- a/.hgignore
+++ b/.gitignore
@@ -1,49 +1,49 @@
-# Ignore file for Visual Studio 2008
-
-# use glob syntax
-syntax: glob
-
-# Ignore Visual Studio 2008 files
-*.obj
-*.exe
-*.pdb
-*.user
-*.aps
-*.pch
-*.vspscc
-*_i.c
-*_p.c
-*.ncb
-*.suo
-*.tlb
-*.tlh
-*.bak
-*.cache
-*.ilk
-*.log
-*.lib
-*.sbr
-*.scc
-[Bb]in
-[Dd]ebug*/
-obj/
-[Rr]elease*/
-_ReSharper*/
-[Tt]est[Rr]esult*
-[Bb]uild[Ll]og.*
-*.[Pp]ublish.xml
-[Ii]nspiration/
-[Pp]ackages/
-*.user.config
-NUnit.exe.lnk
-NBi.ncrunchsolution
-[Dd]ocumentation*/
-*.orig
-*.dgml
-.JustCode/
-.nuget/[Nn]u[Gg]et.exe
-*.vsp
-*.psess
-Thumbs.db
-*.rej
+# Ignore file for Visual Studio 2008
+
+# use glob syntax
+syntax: glob
+
+# Ignore Visual Studio 2008 files
+*.obj
+*.exe
+*.pdb
+*.user
+*.aps
+*.pch
+*.vspscc
+*_i.c
+*_p.c
+*.ncb
+*.suo
+*.tlb
+*.tlh
+*.bak
+*.cache
+*.ilk
+*.log
+*.lib
+*.sbr
+*.scc
+[Bb]in
+[Dd]ebug*/
+obj/
+[Rr]elease*/
+_ReSharper*/
+[Tt]est[Rr]esult*
+[Bb]uild[Ll]og.*
+*.[Pp]ublish.xml
+[Ii]nspiration/
+[Pp]ackages/
+*.user.config
+NUnit.exe.lnk
+NBi.ncrunchsolution
+[Dd]ocumentation*/
+*.orig
+*.dgml
+.JustCode/
+.nuget/[Nn]u[Gg]et.exe
+*.vsp
+*.psess
+Thumbs.db
+*.rej
*.diff
\ No newline at end of file
diff --git a/NBi.Core/NBi.Core.csproj b/NBi.Core/NBi.Core.csproj
index 85f1ef8ac..b54d6408a 100644
--- a/NBi.Core/NBi.Core.csproj
+++ b/NBi.Core/NBi.Core.csproj
@@ -48,13 +48,10 @@
..\packages\Antlr4.StringTemplate.4.0.6.9004\lib\net35\Antlr4.StringTemplate.dll
-
- False
- ..\..\..\..\..\Program Files (x86)\Microsoft SQL Server\120\SDK\Assemblies\Microsoft.AnalysisServices.DLL
-
-
- ../../../../../../../Program%20Files/Microsoft.NET/ADOMD.NET/100/Microsoft.AnalysisServices.AdomdClient.dll
+
+ ../../../../../../../Program%20Files/Microsoft.NET/ADOMD.NET/120/Microsoft.AnalysisServices.AdomdClient.dll
False
+ True
False
diff --git a/NBi.Core/Structure/Olap/OlapStructureDiscoveryFactory.cs b/NBi.Core/Structure/Olap/OlapStructureDiscoveryFactory.cs
index a3dc8ff2f..e4b8f7fcc 100644
--- a/NBi.Core/Structure/Olap/OlapStructureDiscoveryFactory.cs
+++ b/NBi.Core/Structure/Olap/OlapStructureDiscoveryFactory.cs
@@ -35,7 +35,7 @@ public StructureDiscoveryCommand Instantiate(Target target, TargetType type, IEn
var description = new CommandDescription(target, filters);
OlapCommand command = null;
- if ((target == Target.MeasureGroups && type == TargetType.Object) || target == Target.Schemas || target == Target.Perspectives)
+ if ((target == Target.MeasureGroups && type == TargetType.Object) || target == Target.Perspectives)
command = new DistinctOlapCommand(cmd, postFilters, description);
else if (target == Target.Dimensions && type == TargetType.Object)
command = new DimensionCommand(cmd, postFilters, description);
diff --git a/NBi.Core/Structure/Relational/Builders/ColumnDiscoveryCommandBuilder.cs b/NBi.Core/Structure/Relational/Builders/ColumnDiscoveryCommandBuilder.cs
index a96ce18b2..b57463956 100644
--- a/NBi.Core/Structure/Relational/Builders/ColumnDiscoveryCommandBuilder.cs
+++ b/NBi.Core/Structure/Relational/Builders/ColumnDiscoveryCommandBuilder.cs
@@ -18,7 +18,7 @@ public ColumnDiscoveryCommandBuilder()
protected override IEnumerable BuildFilters(IEnumerable filters)
{
yield return new CommandFilter(string.Format("[table_schema]='{0}'"
- , filters.Single(f => f.Target == Target.Schemas).Caption
+ , filters.Single(f => f.Target == Target.Perspectives).Caption
));
yield return new CommandFilter(string.Format("[table_name]='{0}'"
diff --git a/NBi.Core/Structure/Relational/Builders/SchemaDiscoveryCommandBuilder.cs b/NBi.Core/Structure/Relational/Builders/SchemaDiscoveryCommandBuilder.cs
index 3ff16a43a..85802f1b7 100644
--- a/NBi.Core/Structure/Relational/Builders/SchemaDiscoveryCommandBuilder.cs
+++ b/NBi.Core/Structure/Relational/Builders/SchemaDiscoveryCommandBuilder.cs
@@ -22,7 +22,7 @@ public SchemaDiscoveryCommandBuilder()
protected override IEnumerable BuildFilters(IEnumerable filters)
{
- var filter = filters.SingleOrDefault(f => f.Target == Target.Schemas);
+ var filter = filters.SingleOrDefault(f => f.Target == Target.Perspectives);
if (filter != null)
yield return new CommandFilter(string.Format("[schema_name]='{0}'"
, filter.Caption
diff --git a/NBi.Core/Structure/Relational/Builders/TableDiscoveryCommandBuilder.cs b/NBi.Core/Structure/Relational/Builders/TableDiscoveryCommandBuilder.cs
index 27cb65b3f..2620199f2 100644
--- a/NBi.Core/Structure/Relational/Builders/TableDiscoveryCommandBuilder.cs
+++ b/NBi.Core/Structure/Relational/Builders/TableDiscoveryCommandBuilder.cs
@@ -18,7 +18,7 @@ public TableDiscoveryCommandBuilder()
protected override IEnumerable BuildFilters(IEnumerable filters)
{
yield return new CommandFilter(string.Format("[table_schema]='{0}'"
- , filters.Single(f => f.Target == Target.Schemas).Caption
+ , filters.Single(f => f.Target == Target.Perspectives).Caption
));
var filter = filters.SingleOrDefault(f => f.Target == Target.Tables);
diff --git a/NBi.Core/Structure/Relational/RelationalStructureDiscoveryFactory.cs b/NBi.Core/Structure/Relational/RelationalStructureDiscoveryFactory.cs
index 4019b964b..44ad8b57d 100644
--- a/NBi.Core/Structure/Relational/RelationalStructureDiscoveryFactory.cs
+++ b/NBi.Core/Structure/Relational/RelationalStructureDiscoveryFactory.cs
@@ -38,7 +38,7 @@ protected virtual IDiscoveryCommandBuilder InstantiateBuilder(Target target)
{
switch (target)
{
- case Target.Schemas:
+ case Target.Perspectives:
return new SchemaDiscoveryCommandBuilder();
case Target.Tables:
return new TableDiscoveryCommandBuilder();
diff --git a/NBi.Core/Structure/StructureDiscoveryFactoryProvider.cs b/NBi.Core/Structure/StructureDiscoveryFactoryProvider.cs
index 81b0ed6a2..6a187178c 100644
--- a/NBi.Core/Structure/StructureDiscoveryFactoryProvider.cs
+++ b/NBi.Core/Structure/StructureDiscoveryFactoryProvider.cs
@@ -9,9 +9,11 @@
using System.Data.Odbc;
using System.Data.OleDb;
using System.Data.SqlClient;
+using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using System.Xml;
namespace NBi.Core.Structure
{
@@ -68,23 +70,63 @@ protected virtual string InquireFurtherAnalysisService(string connectionString)
{
try
{
- var server = new Server();
- server.Connect(connectionString);
- switch (server.ServerMode)
+ var parsedMode = string.Empty;
+ using (var conn = new AdomdConnection(connectionString))
{
- case ServerMode.Default: return Olap;
- case ServerMode.Multidimensional: return Olap;
- case ServerMode.SharePoint: return Tabular;
- case ServerMode.Tabular: return Tabular;
+ conn.Open();
+ var restrictions = new AdomdRestrictionCollection();
+ restrictions.Add(new AdomdRestriction("ObjectExpansion", "ReferenceOnly"));
+ var ds = conn.GetSchemaDataSet("DISCOVER_XML_METADATA", restrictions);
+ var xml = ds.Tables[0].Rows[0].ItemArray[0].ToString();
+ var doc = new XmlDocument();
+ doc.LoadXml(xml);
+ parsedMode = ParseXmlaResponse(doc);
+ }
+
+
+ switch (parsedMode)
+ {
+ case "Default": return Olap;
+ case "Multidimensional": return Olap;
+ case "SharePoint": return Tabular;
+ case "Tabular": return Tabular;
}
}
catch (Exception ex)
{
- System.Diagnostics.Trace.WriteLineIf(NBiTraceSwitch.TraceWarning,"Can't detect server mode for SSAS, using Olap:" + ex.Message);
+ Trace.WriteLineIf(NBiTraceSwitch.TraceWarning,"Can't detect server mode for SSAS, using Olap. Initial message:" + ex.Message);
return Olap;
}
return Olap;
}
+
+ protected string ParseXmlaResponse(XmlDocument doc)
+ {
+ var root = doc.DocumentElement;
+
+ var nm = new XmlNamespaceManager(doc.NameTable);
+ nm.AddNamespace("ddl300", "http://schemas.microsoft.com/analysisservices/2011/engine/300");
+ nm.AddNamespace("default", "http://schemas.microsoft.com/analysisservices/2003/engine");
+ var serverModeNode = root.SelectSingleNode("//ddl300:ServerMode", nm);
+ if (serverModeNode == null)
+ {
+ Trace.WriteLineIf(NBiTraceSwitch.TraceVerbose, "Trying to detect the server mode for SSAS but the server doesn't return this information. Trying to get it from version.");
+ var versionNode = root.SelectSingleNode("//default:Version", nm);
+ if (versionNode != null)
+ {
+ var splitVersion = versionNode.InnerText.Split('.');
+ short releaseVersion = 0;
+ if (splitVersion.Count() >= 1)
+ if (short.TryParse(splitVersion[0], out releaseVersion))
+ if (releaseVersion < 11)
+ return "Multidimensional";
+ throw new ArgumentException(string.Format("Unable to locate the node for 'ServerMode' and can't guess based on node 'Version'. Value returned for version is '{0}'. Use AdomdClient 12.0 or higher.", versionNode.InnerText));
+ }
+ throw new ArgumentException("Unable to locate the node for 'ServerMode' or the node for 'Version'. Use AdomdClient 12.0 or higher.");
+ }
+
+ return serverModeNode.InnerText;
+ }
}
}
diff --git a/NBi.Core/Structure/Tabular/Builders/ColumnDiscoveryCommandBuilder.cs b/NBi.Core/Structure/Tabular/Builders/ColumnDiscoveryCommandBuilder.cs
index 9bc56d6ac..4e03a85db 100644
--- a/NBi.Core/Structure/Tabular/Builders/ColumnDiscoveryCommandBuilder.cs
+++ b/NBi.Core/Structure/Tabular/Builders/ColumnDiscoveryCommandBuilder.cs
@@ -19,10 +19,10 @@ protected override IEnumerable BuildFilters(IEnumerable'RowNumber'");
- var filter = filters.SingleOrDefault(f => f.Target == Target.Schemas);
+ var filter = filters.SingleOrDefault(f => f.Target == Target.Perspectives);
if (filter != null)
yield return new CommandFilter(string.Format("[table_schema]='{0}'"
- , filters.Single(f => f.Target == Target.Schemas).Caption
+ , filters.Single(f => f.Target == Target.Perspectives).Caption
));
yield return new CommandFilter(string.Format("[table_name]='${0}'"
diff --git a/NBi.Core/Structure/Tabular/Builders/SchemaDiscoveryCommandBuilder.cs b/NBi.Core/Structure/Tabular/Builders/SchemaDiscoveryCommandBuilder.cs
index 744e154c8..4a11a155c 100644
--- a/NBi.Core/Structure/Tabular/Builders/SchemaDiscoveryCommandBuilder.cs
+++ b/NBi.Core/Structure/Tabular/Builders/SchemaDiscoveryCommandBuilder.cs
@@ -20,7 +20,7 @@ protected override IEnumerable BuildFilters(IEnumerable'$'");
- var filter = filters.SingleOrDefault(f => f.Target == Target.Schemas);
+ var filter = filters.SingleOrDefault(f => f.Target == Target.Perspectives);
if (filter != null)
yield return new CommandFilter(string.Format("[table_schema]='{0}'"
, filter.Caption
diff --git a/NBi.Core/Structure/Tabular/Builders/TableDiscoveryCommandBuilder.cs b/NBi.Core/Structure/Tabular/Builders/TableDiscoveryCommandBuilder.cs
index dd9b96995..3bb1f5cc9 100644
--- a/NBi.Core/Structure/Tabular/Builders/TableDiscoveryCommandBuilder.cs
+++ b/NBi.Core/Structure/Tabular/Builders/TableDiscoveryCommandBuilder.cs
@@ -19,7 +19,7 @@ protected override IEnumerable BuildFilters(IEnumerable'$'");
- var filter = filters.SingleOrDefault(f => f.Target == Target.Schemas);
+ var filter = filters.SingleOrDefault(f => f.Target == Target.Perspectives);
if (filter != null)
yield return new CommandFilter(string.Format("[table_schema]='{0}'"
, filter.Caption
diff --git a/NBi.Core/Structure/Tabular/TabularStructureDiscoveryFactory.cs b/NBi.Core/Structure/Tabular/TabularStructureDiscoveryFactory.cs
index 7ae3b53f5..813d79254 100644
--- a/NBi.Core/Structure/Tabular/TabularStructureDiscoveryFactory.cs
+++ b/NBi.Core/Structure/Tabular/TabularStructureDiscoveryFactory.cs
@@ -47,8 +47,6 @@ protected override IDiscoveryCommandBuilder InstantiateBuilder(Target target, Ta
return new ColumnDiscoveryCommandBuilder();
case Target.Sets:
return new SetDiscoveryCommandBuilder();
- case Target.Schemas:
- return new SchemaDiscoveryCommandBuilder();
default:
throw new ArgumentOutOfRangeException();
}
diff --git a/NBi.Core/Structure/Target.cs b/NBi.Core/Structure/Target.cs
index 6b4e011af..acfc3273d 100644
--- a/NBi.Core/Structure/Target.cs
+++ b/NBi.Core/Structure/Target.cs
@@ -17,7 +17,6 @@ public enum Target
Properties,
Tables,
Columns,
- Sets,
- Schemas
+ Sets
}
}
diff --git a/NBi.Testing/Acceptance/Resources/Positive/ContainStructure.nbits b/NBi.Testing/Acceptance/Resources/Positive/ContainStructure.nbits
index 512e84eb6..758833c5d 100644
--- a/NBi.Testing/Acceptance/Resources/Positive/ContainStructure.nbits
+++ b/NBi.Testing/Acceptance/Resources/Positive/ContainStructure.nbits
@@ -4,6 +4,12 @@
Provider=MSOLAP.4;Data Source=(local)\SQL2012;Initial Catalog='Adventure Works DW 2012';localeidentifier=1033
+
+ Data Source=mhknbn2kdz.database.windows.net;Initial Catalog=AdventureWorks2012;User Id=sqlfamily;password=sqlf@m1ly
+
+
+ Provider=MSOLAP.4;Data Source=(local)\SQL2012TABULAR;Initial Catalog='AdventureWorks Tabular Model SQL 2012';localeidentifier=1033
+
@@ -44,4 +50,96 @@
+
+
+
+
+
+
+
+
+ - HumanResources
+ - Person
+
+
+
+
+
+
+
+
+
+
+
+ - Department
+ - Employee
+
+
+
+
+
+
+
+
+
+
+
+ - vJobCandidate
+ - vEmployee
+
+
+
+
+
+
+
+
+
+
+
+ - NationalIDNumber
+ - LoginID
+ - HireDate
+
+
+
+
+
+
+
+
+
+
+
+ - Internet Operation
+
+
+
+
+
+
+
+
+
+
+
+ - Currency
+ - Customer
+ - Date
+
+
+
+
+
+
+
+
+
+
+
+ - First Name
+ - Birth Date
+
+
+
diff --git a/NBi.Testing/Acceptance/Resources/Positive/Exists.nbits b/NBi.Testing/Acceptance/Resources/Positive/Exists.nbits
index 47f494d94..7ddfb2859 100644
--- a/NBi.Testing/Acceptance/Resources/Positive/Exists.nbits
+++ b/NBi.Testing/Acceptance/Resources/Positive/Exists.nbits
@@ -4,6 +4,9 @@
Provider=MSOLAP.4;Data Source=(local)\SQL2012;Initial Catalog='Adventure Works DW 2012';localeidentifier=1033
+
+ Data Source=mhknbn2kdz.database.windows.net;Initial Catalog=AdventureWorks2012;User Id=sqlfamily;password=sqlf@m1ly
+
@@ -154,4 +157,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NBi.Testing/Integration/Core/Structure/Relational/RelationalStructureDiscoveryFactoryTest.cs b/NBi.Testing/Integration/Core/Structure/Relational/RelationalStructureDiscoveryFactoryTest.cs
index 96e06ec32..2926b8a0c 100644
--- a/NBi.Testing/Integration/Core/Structure/Relational/RelationalStructureDiscoveryFactoryTest.cs
+++ b/NBi.Testing/Integration/Core/Structure/Relational/RelationalStructureDiscoveryFactoryTest.cs
@@ -17,7 +17,7 @@ public void Execute_Schema_ListStructureContainingSixElements()
{
var conn = new SqlConnection(ConnectionStringReader.GetSqlClient());
var factory = new RelationalStructureDiscoveryFactory(conn);
- var cmd = factory.Instantiate(Target.Schemas, TargetType.Object,
+ var cmd = factory.Instantiate(Target.Perspectives, TargetType.Object,
new CaptionFilter[] {
});
@@ -33,7 +33,7 @@ public void Execute_Table_ListStructureContainingFifteenElements()
var factory = new RelationalStructureDiscoveryFactory(conn);
var cmd = factory.Instantiate(Target.Tables, TargetType.Object,
new CaptionFilter[] {
- new CaptionFilter(Target.Schemas, "Sales"),
+ new CaptionFilter(Target.Perspectives, "Sales"),
});
var structs = cmd.Execute();
@@ -48,7 +48,7 @@ public void Execute_Column_ListStructureContainingSevenElements()
var factory = new RelationalStructureDiscoveryFactory(conn);
var cmd = factory.Instantiate(Target.Columns, TargetType.Object,
new CaptionFilter[] {
- new CaptionFilter(Target.Schemas,"Sales"),
+ new CaptionFilter(Target.Perspectives,"Sales"),
new CaptionFilter(Target.Tables,"Customer"),
});
diff --git a/NBi.Testing/Integration/Core/Structure/StructureDiscoveryFactoryProviderTest.cs b/NBi.Testing/Integration/Core/Structure/StructureDiscoveryFactoryProviderTest.cs
new file mode 100644
index 000000000..25256621c
--- /dev/null
+++ b/NBi.Testing/Integration/Core/Structure/StructureDiscoveryFactoryProviderTest.cs
@@ -0,0 +1,48 @@
+using NBi.Core.Structure;
+using NBi.Core.Structure.Olap;
+using NBi.Core.Structure.Relational;
+using NBi.Core.Structure.Tabular;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml;
+
+namespace NBi.Testing.Integration.Core.Structure
+{
+ public class StructureDiscoveryFactoryProviderTest
+ {
+ private class FakeStructureDiscoveryFactoryProvider : StructureDiscoveryFactoryProvider
+ {
+ public new string InquireFurtherAnalysisService(string connectionString)
+ {
+ return base.InquireFurtherAnalysisService(connectionString);
+ }
+ }
+
+ [Test]
+ [Category("Olap")]
+ public void InquireFurtherAnalysisService_Multidimensional_ReturnCorrectServerMode()
+ {
+ var connectionString = ConnectionStringReader.GetAdomd();
+
+ var provider = new FakeStructureDiscoveryFactoryProvider();
+ var serverMode = provider.InquireFurtherAnalysisService(connectionString);
+ Assert.That(serverMode, Is.EqualTo("olap"));
+ }
+
+ [Test]
+ [Category("Olap")]
+ public void InquireFurtherAnalysisService_Tabular_ReturnCorrectServerMode()
+ {
+ var connectionString = ConnectionStringReader.GetAdomdTabular();
+
+ var provider = new FakeStructureDiscoveryFactoryProvider();
+ var serverMode = provider.InquireFurtherAnalysisService(connectionString);
+ Assert.That(serverMode, Is.EqualTo("tabular"));
+ }
+ }
+}
diff --git a/NBi.Testing/Integration/Core/Structure/Tabular/TabularStructureDiscoveryFactoryTest.cs b/NBi.Testing/Integration/Core/Structure/Tabular/TabularStructureDiscoveryFactoryTest.cs
index 11c7408a3..09cdf27ac 100644
--- a/NBi.Testing/Integration/Core/Structure/Tabular/TabularStructureDiscoveryFactoryTest.cs
+++ b/NBi.Testing/Integration/Core/Structure/Tabular/TabularStructureDiscoveryFactoryTest.cs
@@ -105,7 +105,7 @@ public void Execute_TabularSchemas_FourElements()
{
var conn = new AdomdConnection(ConnectionStringReader.GetAdomdTabular());
var factory = new TabularStructureDiscoveryFactory(conn);
- var cmd = factory.Instantiate(Target.Schemas, TargetType.Object,
+ var cmd = factory.Instantiate(Target.Perspectives, TargetType.Object,
new CaptionFilter[] {
});
@@ -121,7 +121,7 @@ public void Execute_TabularTablesForInternetOperation_FifteenElements()
var factory = new TabularStructureDiscoveryFactory(conn);
var cmd = factory.Instantiate(Target.Tables, TargetType.Object,
new CaptionFilter[] {
- new CaptionFilter(Target.Schemas,"Internet Operation"),
+ new CaptionFilter(Target.Perspectives,"Internet Operation"),
});
var structs = cmd.Execute();
@@ -136,7 +136,7 @@ public void Execute_TabularColumnsForInternetSales_TwentySevenElements()
var factory = new TabularStructureDiscoveryFactory(conn);
var cmd = factory.Instantiate(Target.Columns, TargetType.Object,
new CaptionFilter[] {
- new CaptionFilter(Target.Schemas,"Internet Operation"),
+ new CaptionFilter(Target.Perspectives,"Internet Operation"),
new CaptionFilter(Target.Tables,"Internet Sales"),
});
@@ -152,7 +152,7 @@ public void Execute_OnSchemaNamedInternetOperation_ListStructureContainingTenTab
var factory = new TabularStructureDiscoveryFactory(conn);
var cmd = factory.Instantiate(Target.Tables, TargetType.Object,
new CaptionFilter[] {
- new CaptionFilter(Target.Schemas, "Internet Operation")});
+ new CaptionFilter(Target.Perspectives, "Internet Operation")});
var structs = cmd.Execute();
@@ -166,7 +166,7 @@ public void Execute_OnTableNamedCurrency_ListStructureContainingThreeColumns()
var factory = new TabularStructureDiscoveryFactory(conn);
var cmd = factory.Instantiate(Target.Columns, TargetType.Object,
new CaptionFilter[] {
- new CaptionFilter(Target.Schemas, "Internet Operation"),
+ new CaptionFilter(Target.Perspectives, "Internet Operation"),
new CaptionFilter(Target.Tables, "Currency")
});
diff --git a/NBi.Testing/NBi.Testing.csproj b/NBi.Testing/NBi.Testing.csproj
index 903ee0bf3..200e95f3d 100644
--- a/NBi.Testing/NBi.Testing.csproj
+++ b/NBi.Testing/NBi.Testing.csproj
@@ -51,8 +51,8 @@
..\packages\MarkdownLog.0.9.3\lib\portable-windows8+net45\MarkdownLog.dll
-
- ../../../../../../../Program%20Files/Microsoft.NET/ADOMD.NET/100/Microsoft.AnalysisServices.AdomdClient.dll
+
+ ../../../../../../../Program%20Files/Microsoft.NET/ADOMD.NET/120/Microsoft.AnalysisServices.AdomdClient.dll
False
@@ -108,6 +108,7 @@
+
@@ -239,6 +240,7 @@
+
@@ -558,6 +560,7 @@
+
diff --git a/NBi.Testing/Unit/Core/Structure/StructureDiscoveryFactoryProviderTest.cs b/NBi.Testing/Unit/Core/Structure/StructureDiscoveryFactoryProviderTest.cs
index 983192e2e..58d5ffe49 100644
--- a/NBi.Testing/Unit/Core/Structure/StructureDiscoveryFactoryProviderTest.cs
+++ b/NBi.Testing/Unit/Core/Structure/StructureDiscoveryFactoryProviderTest.cs
@@ -9,6 +9,7 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using System.Xml;
namespace NBi.Testing.Unit.Core.Structure
{
@@ -28,6 +29,11 @@ protected override string InquireFurtherAnalysisService(string connectionString)
{
return result;
}
+
+ public new string ParseXmlaResponse(XmlDocument doc)
+ {
+ return base.ParseXmlaResponse(doc);
+ }
}
[Test]
@@ -59,5 +65,82 @@ public void Instantiate_AdomdConnectionTabular_GetDatabaseStructureDiscoveryFact
var factory = provider.Instantiate(connectionString);
Assert.That(factory, Is.TypeOf());
}
+
+
+ [Test]
+ [TestCase("Multidimensional")]
+ [TestCase("Tabular")]
+ [TestCase("Sharepoint")]
+ [TestCase("Default")]
+ public void ParseXmlaResponse_Tabular_GetCorrectServerMode(string serverMode)
+ {
+ var xml = ""
+ + " "
+ + " XXX\\SQL2014 "
+ + " XXX\\SQL2014 "
+ + " 2015-07-02T21:56:04.076667 "
+ + " 2015-07-02T21:56:04.093333 "
+ + " 12.0.2000.8 "
+ + " Developer64 "
+ + " 2176971986 "
+ + " $value$"
+ + " OnPremise"
+ + " 1100"
+ + " ";
+ xml = xml.Replace("$value$", serverMode);
+ var doc = new XmlDocument();
+
+ doc.LoadXml(xml);
+ var provider = new FakeStructureDiscoveryFactoryProvider(null);
+ var parsedServerMode = provider.ParseXmlaResponse(doc);
+ Assert.That(parsedServerMode, Is.EqualTo(serverMode));
+ }
+
+ [Test]
+ [TestCase("10.0.200.12")]
+ [TestCase("9.1.200")]
+ public void ParseXmlaResponse_VersionBefore11_GetCorrectServerMode(string version)
+ {
+ var xml = ""
+ + " "
+ + " XXX\\SQL2014 "
+ + " XXX\\SQL2014 "
+ + " 2015-07-02T21:56:04.076667 "
+ + " 2015-07-02T21:56:04.093333 "
+ + " $value$ "
+ + " Developer64 "
+ + " 2176971986 "
+ + " ";
+ xml = xml.Replace("$value$", version);
+ var doc = new XmlDocument();
+
+ doc.LoadXml(xml);
+ var provider = new FakeStructureDiscoveryFactoryProvider(null);
+ var parsedServerMode = provider.ParseXmlaResponse(doc);
+ Assert.That(parsedServerMode, Is.EqualTo("Multidimensional"));
+ }
+
+ [Test]
+ [TestCase("12.0.200.12")]
+ [TestCase("11.1.200")]
+ public void ParseXmlaResponse_VersionAfter11_ThrowExceptionImpossibleToGuess(string version)
+ {
+ var xml = ""
+ + " "
+ + " XXX\\SQL2014 "
+ + " XXX\\SQL2014 "
+ + " 2015-07-02T21:56:04.076667 "
+ + " 2015-07-02T21:56:04.093333 "
+ + " $value$ "
+ + " Developer64 "
+ + " 2176971986 "
+ + " ";
+ xml = xml.Replace("$value$", version);
+ var doc = new XmlDocument();
+
+ doc.LoadXml(xml);
+ var provider = new FakeStructureDiscoveryFactoryProvider(null);
+ Assert.Throws(delegate { provider.ParseXmlaResponse(doc); });
+ }
}
}
diff --git a/NBi.Testing/Unit/Xml/Items/TablesXmlTest.cs b/NBi.Testing/Unit/Xml/Items/TablesXmlTest.cs
new file mode 100644
index 000000000..98499c4c8
--- /dev/null
+++ b/NBi.Testing/Unit/Xml/Items/TablesXmlTest.cs
@@ -0,0 +1,47 @@
+using System.IO;
+using System.Reflection;
+using NBi.Xml;
+using NBi.Xml.Items;
+using NBi.Xml.Systems;
+using NUnit.Framework;
+
+namespace NBi.Testing.Unit.Xml.Items
+{
+ [TestFixture]
+ public class TablesXmlTest
+ {
+ protected TestSuiteXml DeserializeSample()
+ {
+ // Declare an object variable of the type to be deserialized.
+ var manager = new XmlManager();
+
+ // A Stream is needed to read the XML document.
+ using (Stream stream = Assembly.GetExecutingAssembly()
+ .GetManifestResourceStream("NBi.Testing.Unit.Xml.Resources.TablesXmlTestSuite.xml"))
+ using (StreamReader reader = new StreamReader(stream))
+ {
+ manager.Read(reader);
+ }
+ return manager.TestSuite;
+ }
+
+ [Test]
+ public void Deserialize_SampleFile_TableAndPerspectiveLoaded()
+ {
+ int testNr = 0;
+
+ // Create an instance of the XmlSerializer specifying type and namespace.
+ TestSuiteXml ts = DeserializeSample();
+
+ // Check the properties of the object.
+ Assert.That(ts.Tests[testNr].Systems[0], Is.TypeOf());
+ Assert.That(((StructureXml)ts.Tests[testNr].Systems[0]).Item, Is.TypeOf());
+
+ TablesXml item = (TablesXml)((StructureXml)ts.Tests[testNr].Systems[0]).Item;
+ Assert.That(item.Perspective, Is.EqualTo("schema"));
+ Assert.That(item.ConnectionString, Is.EqualTo("connectionString"));
+ }
+
+
+ }
+}
diff --git a/NBi.Testing/Unit/Xml/Resources/TablesXmlTestSuite.xml b/NBi.Testing/Unit/Xml/Resources/TablesXmlTestSuite.xml
new file mode 100644
index 000000000..32327422c
--- /dev/null
+++ b/NBi.Testing/Unit/Xml/Resources/TablesXmlTestSuite.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+ - Employee
+ - JobCandidate
+
+
+
+
\ No newline at end of file
diff --git a/NBi.Xml/Items/TableXml.cs b/NBi.Xml/Items/TableXml.cs
index f55182674..95cc5ef17 100644
--- a/NBi.Xml/Items/TableXml.cs
+++ b/NBi.Xml/Items/TableXml.cs
@@ -1,11 +1,12 @@
-using System;
+using NBi.Xml.Items.Filters;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
namespace NBi.Xml.Items
{
- public class TableXml : AbstractMembersItem
+ public class TableXml : AbstractMembersItem, IPerspectiveFilter
{
[XmlAttribute("perspective")]
public string Perspective { get; set; }
diff --git a/NBi.Xml/Items/TablesXml.cs b/NBi.Xml/Items/TablesXml.cs
index 918ca14f2..66b326a96 100644
--- a/NBi.Xml/Items/TablesXml.cs
+++ b/NBi.Xml/Items/TablesXml.cs
@@ -1,11 +1,12 @@
-using System;
+using NBi.Xml.Items.Filters;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
namespace NBi.Xml.Items
{
- public class TablesXml : AbstractMembersItem
+ public class TablesXml : AbstractMembersItem, IPerspectiveFilter
{
[XmlAttribute("perspective")]
public string Perspective { get; set; }
diff --git a/NBi.Xml/Schema/BaseType.xsd b/NBi.Xml/Schema/BaseType.xsd
index fe58114b8..8d7d767e9 100644
--- a/NBi.Xml/Schema/BaseType.xsd
+++ b/NBi.Xml/Schema/BaseType.xsd
@@ -246,6 +246,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -528,6 +542,8 @@
+
+
diff --git a/NBi.Xml/Systems/StructureXml.cs b/NBi.Xml/Systems/StructureXml.cs
index c346b58fb..11735d076 100644
--- a/NBi.Xml/Systems/StructureXml.cs
+++ b/NBi.Xml/Systems/StructureXml.cs
@@ -23,6 +23,8 @@ public class StructureXml: AbstractSystemUnderTestXml
XmlElement(Type = typeof(PropertiesXml), ElementName = "properties"),
XmlElement(Type = typeof(TableXml), ElementName = "table"),
XmlElement(Type = typeof(ColumnXml), ElementName = "column"),
+ XmlElement(Type = typeof(TablesXml), ElementName = "tables"),
+ XmlElement(Type = typeof(ColumnsXml), ElementName = "columns"),
XmlElement(Type = typeof(SetXml), ElementName = "set"),
XmlElement(Type = typeof(SetsXml), ElementName = "sets")
]
diff --git a/Readme.md b/Readme.md
index 8dff8378d..4beba738f 100644
--- a/Readme.md
+++ b/Readme.md
@@ -1,23 +1,25 @@
-![Logo](https://github.com/Seddryck/nbi/raw/master/NBi-logo-white.jpg)
+![Logo](https://github.com/Seddryck/nbi/raw/gh-pages/img/logo-2x.png)
# NBi #
-NBi is a **testing framework** (add-on to NUnit) for Microsoft **Business Intelligence** platform and Data Access.
+NBi is a **testing framework** (add-on to NUnit) for Microsoft **Business Intelligence** platform (SQL Server Database engine, SSIS, SSAS, SSRS) and Data Access.
The main goal of this framework is to let users create tests with a declarative approach based on an **Xml** syntax. By the means of NBi, you don't need to develop C# code to specify your tests! Either, you don't need Visual Studio to compile your test suite. Just create an Xml file and let the framework interpret it and play your tests. The framework is designed as an add-on of NUnit but with the possibility to port it easily to other testing frameworks.
+![project status](http://stillmaintained.com/Seddryck/nbi.png)
+
## Releases ##
-Binaries for the different releases are hosted exclusively on [Codeplex](http://nbi.codeplex.com)
+Binaries for the different releases are hosted on [www.nbi.io](http://www.nbi.io/release/) or [GitHub] (https://github.com/Seddryck/NBi/releases)
## Documentation ##
-The documentation is available on-line and is hosted on [Codeplex](http://nbi.codeplex.com)
+The documentation is available on-line and is hosted on [www.nbi.io](http://www.nbi.io/docs/home/)
## Licenses ##
-NBi is available with two licenses: MS-PL and OSL. You're free to choose which one convains the best to your project. NBi is also using several OSS projects as librairies. All these projects and their licenses are available in the folder License.
+NBi is available with two licenses: MS-PL and Apache 2.0. You're free to choose which one convains the best to your project. NBi is also using several OSS projects as librairies. All these projects and their licenses are available in the folder "License".
## Bugs, issues and requests for features ##
-The list of bugs and feature's requests is hosted on [Codeplex](http://nbi.codeplex.com)
+The list of bugs and feature's requests is hosted on [GitHub](https://github.com/Seddryck/NBi/issues)
## Continuous Integration ##
-A continuous integration service is available on AppVeyor at https://ci.appveyor.com/project/CdricLCharlier/nbi/
+A continuous integration service is available on AppVeyor at [https://ci.appveyor.com/project/CdricLCharlier/nbi/]
Note that all the tests are not executed on this environment due to limitations in the availability of some components.
- Unit tests are always executed
@@ -30,7 +32,7 @@ Note that all the tests are not executed on this environment due to limitations
- Report Server: No (but planned to integrate them)
- Acceptance tests are excluded
-[![Build status](https://ci.appveyor.com/api/projects/status/td7fd7lbl3aqxi3i)](https://ci.appveyor.com/project/CdricLCharlier/nbi)
+[![Build status](https://ci.appveyor.com/api/projects/status/t5m0hr57vnsdv0v7)](https://ci.appveyor.com/project/CdricLCharlier/nbi)
Two artefacts are provided by this CI:
@@ -38,18 +40,18 @@ Two artefacts are provided by this CI:
- UI.zip contains the exe and dlls needed to run Genbi
## Code ##
-NBi is using **Mercurial** as DCVS and the code is hosted on [Codeplex](http://nbi.codeplex.com) and [Bitbucket](http://bitbucket.org/Seddryck/nbi). A mirror copy is hosted on [GitHub](http://github.com/Seddryck/nbi) with the help of the plugin HgGit and is compatible with Git.
+NBi is using **Git** as DCVS and the code is hosted on [Github](https://github.com/Seddryck/NBi). A mirror copy is hosted on [Bitbucket](http://bitbucket.org/Seddryck/nbi).
### Automated Testing ###
-NBi has around 1000 automated tests, asserting a lot of feature before each release. These tests are categorized in three folders:
+NBi has around 1300 automated tests, asserting a lot of features before each release. These tests are organized in three folders:
- Acceptance: The tests are effectively written in nbits file and played end-to-end by the framework itself. They don't use any fake, mock or stub and are effectively connected to real database and cubes and perform query on them.
- Integration: These tests are used to assert interactions with resources such as databases or cubes. The make usage of stubs to define parameters impacting the code to use.
- Unit: These tests are never contacting an external resource and tests maximum the code of one class. Usage of stubs, fakes and mocks is welcome.
-In order to be able to build the software on different machines, the database and cube used during tests must always be Adventure Works 2008R2. In order to facilitate the integration, NBi is connected by default to the online SQL database hosted on Azure (Unfortunatelly no equivalent for SSAS). If you want to overrides the connection settings for executing the tests on your own environement just create a file named ConnectionString.user.config in the folder NBi.Testing and copy the content from the file ConnectionString.config into it before adjusting for your environement.
+In order to be able to build the software on different machines, the database and cube used during tests must always be Adventure Works 2008R2. In order to facilitate the integration, NBi is connected by default to the online SQL database hosted on Azure (Unfortunatelly no equivalent for SSAS). If you want to overrides the connection settings for executing the tests on your own environement just create a file named ConnectionString.user.config in the folder "NBi.Testing" and copy the content from the file ConnectionString.config into it before adjusting for your environement.
## Tracking ##
This OSS project is tracked by [Ohloh](http://www.ohloh.net/p/NBi)
-[![Project Stats](https://www.ohloh.net/p/nbi/widgets/project_thin_badge.gif)](https://www.ohloh.net/p/YOUR_PROJECT)
\ No newline at end of file
+[![Project Stats](https://www.ohloh.net/p/nbi/widgets/project_thin_badge.gif)](https://www.ohloh.net/p/YOUR_PROJECT)