Merge remote-tracking branch 'refs/remotes/origin/master' into jodebrui

This commit is contained in:
Jos de Bruijn
2016-04-29 08:34:38 -07:00
46 changed files with 112463 additions and 6 deletions
+2 -2
View File
@@ -1,5 +1,5 @@
# SQL Server Code Samples
This GitHub repository contains code samples that demonstrate how to use SQL Server features. Each sample includes a README file that explains how to run and use the sample.
# SQL Server and Azure DB Samples
This GitHub repository contains code samples that demonstrate how to use SQL Server and Azure SQL Database features. Each sample includes a README file that explains how to run and use the sample.
## Working in GitHub
To work in GitHub, go to https://github.com/microsoft/sql-server-samples and fork the repository. Work in your own fork and when you are ready to submit to make a change or publish your sample for the first time, submit a pull request into the master branch of sql-server-samples. One of the approvers will review your request and accept or reject the pull request.
@@ -49,7 +49,7 @@ With default settings on one machine with 24 logical cores and relatively slow S
When deploying to Azure SQL Database, make sure to run the app in an Azure VM in the same region as the database.
## About the code
The code included in this sample is not intended to be a set of best practices on how to build scalable enterprise grade web applications. This is beyond the scope of this quick start sample.
The code included in this sample is not intended to be a set of best practices on how to build scalable enterprise grade applications. This is beyond the scope of this quick start sample.
## More information
- [In-Memory OLTP (In-Memory Optimization)] (https://msdn.microsoft.com/en-us/library/dn133186.aspx)
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{6F10BF17-E821-41D8-A83A-43787AC9E238}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MDSBusinessRules</RootNamespace>
<AssemblyName>BusinessRules</AssemblyName>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Reference.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
@@ -0,0 +1,22 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.40629.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BusinessRules", "BusinessRules.csproj", "{6F10BF17-E821-41D8-A83A-43787AC9E238}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6F10BF17-E821-41D8-A83A-43787AC9E238}.Debug|x86.ActiveCfg = Debug|x86
{6F10BF17-E821-41D8-A83A-43787AC9E238}.Debug|x86.Build.0 = Debug|x86
{6F10BF17-E821-41D8-A83A-43787AC9E238}.Release|x86.ActiveCfg = Release|x86
{6F10BF17-E821-41D8-A83A-43787AC9E238}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,424 @@
//==============================================================================
//
// © Microsoft corp. All rights reserved.
// This code is licensed under the Microsoft Public License.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//==============================================================================
using System;
using System.ServiceModel;
using MDSBusinessRules.MDSTestService; // For the created service reference.
namespace MDSBusinessRules
{
class Program
{
// MDS service client proxy object.
private static ServiceClient clientProxy;
// Set the MDS URL (plus /Service/Service.svc) here.
private static string mdsURL = @"http://localhost/MDS/Service/Service.svc";
static void Main(string[] args)
{
try
{
// Create a service proxy.
clientProxy = GetClientProxy(mdsURL);
}
catch (Exception ex)
{
Console.WriteLine("Error creating a service proxy: {0}", ex);
return;
}
// Create a new business rule and publish it.
// You need to specify the existing Model and Entity names.
CreateAndPublishBR("TestModel", "TestEntity", "Test Rule");
// Edits the business rule and publishes it.
EditAndPublishBR("TestModel", "TestEntity", "Test Rule");
// Creates a member that causes a validation issue, processes the validation and gets the list of validation issues.
// You need to specify the existing Model, Entity, and Version names.
GetBRValidationIssue("TestModel", "TestEntity", "Test Rule", "VERSION_1");
// Excludes the business rule and publishes it.
ExcludeAndPublishBR("TestModel", "TestEntity", "Test Rule");
// Deletes the business rule and publishes it.
DeleteAndPublishBR("TestModel", "TestEntity", "Test Rule");
}
// Creates MDS service client proxy.
private static ServiceClient GetClientProxy(string targetURL)
{
// Create an endpoint address using the URL.
EndpointAddress endptAddress = new EndpointAddress(targetURL);
// Create and configure the WS Http binding.
WSHttpBinding wsBinding = new WSHttpBinding();
// Create and return the client proxy.
return new ServiceClient(wsBinding, endptAddress);
}
// Handles operation errors.
private static void HandleOperationErrors(OperationResult result)
{
string errorMessage = string.Empty;
if (result.Errors.Count > 0)
{
foreach (Error anError in result.Errors)
{
errorMessage += "Operation Error: " + anError.Code + ":" + anError.Description + "\n";
}
// Show the error messages.
Console.WriteLine(errorMessage);
}
}
// Create a new business rule and publish the rule to enable it in the validation process.
private static void CreateAndPublishBR(string modelName, string entityName, string ruleName)
{
try
{
// Set Model and Entity objects.
Identifier modelId = new Identifier { Name = modelName };
Identifier entityId = new Identifier { Name = entityName };
// Create the request object.
MDSTestService.BusinessRulesCreateRequest ruleCreateRequest = new MDSTestService.BusinessRulesCreateRequest();
ruleCreateRequest.ReturnCreatedIdentifiers = true;
ruleCreateRequest.BusinessRuleSet = new BusinessRules();
// Create a new business rule.
BusinessRule newRule = new BusinessRule();
ruleCreateRequest.BusinessRuleSet.BusinessRulesMember = new System.Collections.ObjectModel.Collection<BusinessRule> { };
ruleCreateRequest.BusinessRuleSet.BusinessRulesMember.Add(newRule);
newRule.Identifier = new MemberTypeContextIdentifier
{
Name = ruleName,
ModelId = modelId,
EntityId = entityId,
MemberType = MemberType.Leaf
};
newRule.Priority = 10;
newRule.BRConditionTree = new BRConditionTreeNode();
newRule.BRConditionTree.LogicalOperator = LogicalOperator.And;
newRule.BRConditionTree.Sequence = 1;
// Create the rule condition "Code equals ABC".
BRCondition ruleCondition = new BRCondition();
newRule.BRConditionTree.BRConditions = new System.Collections.ObjectModel.Collection<BRCondition> { };
newRule.BRConditionTree.BRConditions.Add(ruleCondition);
ruleCondition.Sequence = 1;
// Create the condition prefix argument for Code attribute.
BRAttributeArgument conditionPrefix = new BRAttributeArgument();
ruleCondition.PrefixArgument = conditionPrefix;
conditionPrefix.PropertyName = BRPropertyName.Anchor;
conditionPrefix.AttributeId = new Identifier { Name = "Code" };
// Set the condition operator.
ruleCondition.Operator = BRItemType.IsEqual;
// Set the postfix argument "ABC".
BRFreeformArgument conditionPostfix = new BRFreeformArgument();
ruleCondition.PostfixArguments = new System.Collections.ObjectModel.Collection<object> { };
ruleCondition.PostfixArguments.Add(conditionPostfix);
conditionPostfix.PropertyName = BRPropertyName.Value;
conditionPostfix.Value = "ABC";
// Create the rule action "Name must be equal to Test".
BRAction ruleAction = new BRAction();
newRule.BRActions = new System.Collections.ObjectModel.Collection<BRAction> { };
newRule.BRActions.Add(ruleAction);
ruleAction.Sequence = 1;
// Set the action prefix argument for Name attribute.
BRAttributeArgument actionPrefix = new BRAttributeArgument();
ruleAction.PrefixArgument = actionPrefix;
actionPrefix.PropertyName = BRPropertyName.Anchor;
actionPrefix.AttributeId = new Identifier { Name = "Name" };
// Set the action operator.
ruleAction.Operator = BRItemType.MustBeEqual;
// Set the action postfix argument.
BRFreeformArgument actionPostfix = new BRFreeformArgument();
ruleAction.PostfixArguments = new System.Collections.ObjectModel.Collection<object> { };
ruleAction.PostfixArguments.Add(actionPostfix);
actionPostfix.PropertyName = BRPropertyName.Value;
actionPostfix.Value = "Test";
// Create the business rule.
MDSTestService.BusinessRulesCreateResponse ruleCreateResponse = clientProxy.BusinessRulesCreate(ruleCreateRequest);
HandleOperationErrors(ruleCreateResponse.OperationResult);
// Create the request object.
MDSTestService.BusinessRulesPublishRequest rulePublishRequest = new MDSTestService.BusinessRulesPublishRequest();
rulePublishRequest.BRPublishCriteria = new BRPublishCriteria();
rulePublishRequest.BRPublishCriteria.EntityId = entityId;
rulePublishRequest.BRPublishCriteria.ModelId = modelId;
rulePublishRequest.BRPublishCriteria.MemberType = BREntityMemberType.Leaf;
// Publish the business rule.
MDSTestService.MessageResponse rulePublishResponse = clientProxy.BusinessRulesPublish(rulePublishRequest);
HandleOperationErrors(rulePublishResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
// Edits the business rule and publish to enable the changes in the validation process.
private static void EditAndPublishBR(string modelName, string entityName, string ruleName)
{
try
{
// Set Model and Entity objects.
Identifier modelId = new Identifier { Name = modelName };
Identifier entityId = new Identifier { Name = entityName };
// Create the request object.
MDSTestService.BusinessRulesGetRequest ruleGetRequest = new MDSTestService.BusinessRulesGetRequest();
ruleGetRequest.ResultOptions = new BRResultOptions();
ruleGetRequest.ResultOptions.BusinessRules = ResultType.Details;
ruleGetRequest.GetCriteria = new BRGetCriteria();
ruleGetRequest.GetCriteria.ModelId = modelId;
ruleGetRequest.GetCriteria.EntityId = entityId;
ruleGetRequest.GetCriteria.MemberType = BREntityMemberType.Leaf;
ruleGetRequest.GetCriteria.BusinessRuleIds = new System.Collections.ObjectModel.Collection<Identifier> { };
ruleGetRequest.GetCriteria.BusinessRuleIds.Add(new Identifier { Name = ruleName });
// Get the business rules.
MDSTestService.BusinessRulesGetResponse ruleGetResponse = clientProxy.BusinessRulesGet(ruleGetRequest);
HandleOperationErrors(ruleGetResponse.OperationResult);
BusinessRule selectedBusinessRule = ruleGetResponse.BusinessRuleSet.BusinessRulesMember[0];
// Change the condition to "Code starts with Test".
BRCondition ruleCondition = selectedBusinessRule.BRConditionTree.BRConditions[0];
// Set the attribute name as "Code".
BRAttributeArgument conditionPrefix = (BRAttributeArgument)ruleCondition.PrefixArgument;
conditionPrefix.PropertyName = BRPropertyName.Anchor;
conditionPrefix.AttributeId = new Identifier { Name = "Code" };
// Set the condition operator.
ruleCondition.Operator = BRItemType.StartsWith;
// Set the postfix argument "Test".
BRFreeformArgument conditionPostfix = (BRFreeformArgument)ruleCondition.PostfixArguments[0];
conditionPostfix.PropertyName = BRPropertyName.Value;
conditionPostfix.Value = "Test";
// Create the request object.
MDSTestService.BusinessRulesUpdateRequest ruleUpdateRequest = new MDSTestService.BusinessRulesUpdateRequest();
ruleUpdateRequest.BusinessRuleSet = ruleGetResponse.BusinessRuleSet;
// Update the business rule.
MDSTestService.MessageResponse ruleUpdateResponse = clientProxy.BusinessRulesUpdate(ruleUpdateRequest);
HandleOperationErrors(ruleUpdateResponse.OperationResult);
// Create the request object.
MDSTestService.BusinessRulesPublishRequest rulePublishRequest = new MDSTestService.BusinessRulesPublishRequest();
rulePublishRequest.BRPublishCriteria = new BRPublishCriteria();
rulePublishRequest.BRPublishCriteria.EntityId = entityId;
rulePublishRequest.BRPublishCriteria.ModelId = modelId;
rulePublishRequest.BRPublishCriteria.MemberType = BREntityMemberType.Leaf;
// Publish the business rule.
MDSTestService.MessageResponse rulePublishResponse = clientProxy.BusinessRulesPublish(rulePublishRequest);
HandleOperationErrors(rulePublishResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
// Creates a member that causes a validation issue, processes the validation and gets the list of validation issues.
private static void GetBRValidationIssue(string modelName, string entityName, string ruleName, string versionName)
{
try
{
// Set Model, Entity, and Version objects.
Identifier modelId = new Identifier { Name = modelName };
Identifier entityId = new Identifier { Name = entityName };
Identifier versionId = new Identifier { Name = versionName };
// Create the request object.
MDSTestService.BusinessRulesCreateRequest ruleCreateRequest = new MDSTestService.BusinessRulesCreateRequest();
ruleCreateRequest.ReturnCreatedIdentifiers = true;
ruleCreateRequest.BusinessRuleSet = new BusinessRules();
// Create the request object.
MDSTestService.EntityMembersCreateRequest memberCreateRequest = new MDSTestService.EntityMembersCreateRequest();
memberCreateRequest.Members = new EntityMembers();
memberCreateRequest.Members.ModelId = modelId;
memberCreateRequest.Members.EntityId = entityId;
memberCreateRequest.Members.VersionId = versionId;
memberCreateRequest.Members.MemberType = MemberType.Leaf;
Member aMember = new Member();
aMember.MemberId = new MemberIdentifier();
aMember.MemberId.Code = "Test12";
aMember.MemberId.Name = "AA";
aMember.MemberId.MemberType = MemberType.Leaf;
memberCreateRequest.Members.Members = new System.Collections.ObjectModel.Collection<Member> { };
memberCreateRequest.Members.Members.Add(aMember);
// Add a member that triggers the validation error.
MDSTestService.EntityMembersCreateResponse memberCreateResponse = clientProxy.EntityMembersCreate(memberCreateRequest);
HandleOperationErrors(memberCreateResponse.OperationResult);
// Create the request object.
MDSTestService.ValidationProcessRequest validationProcessRequest = new MDSTestService.ValidationProcessRequest();
validationProcessRequest.ValidationProcessCriteria = new ValidationProcessCriteria();
validationProcessRequest.ValidationProcessCriteria.ModelId = modelId;
validationProcessRequest.ValidationProcessCriteria.EntityId = entityId;
validationProcessRequest.ValidationProcessCriteria.VersionId = versionId;
validationProcessRequest.ValidationProcessOptions = new ValidationProcessOptions();
validationProcessRequest.ValidationProcessOptions.ReturnValidationResults = true;
// Process validation and get a validation issue.
MDSTestService.ValidationProcessResponse validationProcessResponse = clientProxy.ValidationProcess(validationProcessRequest);
HandleOperationErrors(validationProcessResponse.OperationResult);
// Show the validation issue's description.
if (validationProcessResponse.ValidationIssueList.Count > 0)
{
ValidationIssue validationIssue = validationProcessResponse.ValidationIssueList[0];
Console.WriteLine("Validation issue: " + validationIssue.Description);
}
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
// Excludes the business rule and publishes it to remove the rule from the validation process.
private static void ExcludeAndPublishBR(string modelName, string entityName, string ruleName)
{
try
{
// Set Model and Entity objects.
Identifier modelId = new Identifier { Name = modelName };
Identifier entityId = new Identifier { Name = entityName };
// Create the request object.
MDSTestService.BusinessRulesGetRequest ruleGetRequest = new MDSTestService.BusinessRulesGetRequest();
ruleGetRequest.ResultOptions = new BRResultOptions();
ruleGetRequest.ResultOptions.BusinessRules = ResultType.Details;
ruleGetRequest.GetCriteria = new BRGetCriteria();
ruleGetRequest.GetCriteria.ModelId = modelId;
ruleGetRequest.GetCriteria.EntityId = entityId;
ruleGetRequest.GetCriteria.MemberType = BREntityMemberType.Leaf;
ruleGetRequest.GetCriteria.BusinessRuleIds = new System.Collections.ObjectModel.Collection<Identifier> { };
ruleGetRequest.GetCriteria.BusinessRuleIds.Add(new Identifier { Name = ruleName });
// Get the business rules.
MDSTestService.BusinessRulesGetResponse ruleGetResponse = clientProxy.BusinessRulesGet(ruleGetRequest);
HandleOperationErrors(ruleGetResponse.OperationResult);
BusinessRule selectedBusinessRule = ruleGetResponse.BusinessRuleSet.BusinessRulesMember[0];
// Set the status to pending exclusion.
selectedBusinessRule.Status = BRStatus.PendingExclusion;
// Create the request object.
MDSTestService.BusinessRulesUpdateRequest ruleUpdateRequest = new MDSTestService.BusinessRulesUpdateRequest();
ruleUpdateRequest.BusinessRuleSet = new BusinessRules();
ruleUpdateRequest.BusinessRuleSet.BusinessRulesMember = new System.Collections.ObjectModel.Collection<BusinessRule> { };
ruleUpdateRequest.BusinessRuleSet.BusinessRulesMember.Add(selectedBusinessRule);
// Update the business rule's status to pending exclusion.
MDSTestService.MessageResponse ruleUpdateResponse = clientProxy.BusinessRulesUpdate(ruleUpdateRequest);
HandleOperationErrors(ruleUpdateResponse.OperationResult);
// Create the request object.
MDSTestService.BusinessRulesPublishRequest rulePublishRequest = new MDSTestService.BusinessRulesPublishRequest();
rulePublishRequest.BRPublishCriteria = new BRPublishCriteria();
rulePublishRequest.BRPublishCriteria.EntityId = entityId;
rulePublishRequest.BRPublishCriteria.ModelId = modelId;
rulePublishRequest.BRPublishCriteria.MemberType = BREntityMemberType.Leaf;
// Publish the business rule.
MDSTestService.MessageResponse rulePublishResponse = clientProxy.BusinessRulesPublish(rulePublishRequest);
HandleOperationErrors(rulePublishResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
// Deletes the business rule and publishes to remove the rule from the validation process.
private static void DeleteAndPublishBR(string modelName, string entityName, string ruleName)
{
try
{
// Set Model and Entity objects.
Identifier modelId = new Identifier { Name = modelName };
Identifier entityId = new Identifier { Name = entityName };
// Create the request object.
MDSTestService.BusinessRulesGetRequest ruleGetRequest = new MDSTestService.BusinessRulesGetRequest();
ruleGetRequest.ResultOptions = new BRResultOptions();
ruleGetRequest.ResultOptions.BusinessRules = ResultType.Details;
ruleGetRequest.GetCriteria = new BRGetCriteria();
ruleGetRequest.GetCriteria.ModelId = modelId;
ruleGetRequest.GetCriteria.EntityId = entityId;
ruleGetRequest.GetCriteria.MemberType = BREntityMemberType.Leaf;
ruleGetRequest.GetCriteria.BusinessRuleIds = new System.Collections.ObjectModel.Collection<Identifier> { };
ruleGetRequest.GetCriteria.BusinessRuleIds.Add(new Identifier { Name = ruleName });
// Get the business rules.
MDSTestService.BusinessRulesGetResponse ruleGetResponse = clientProxy.BusinessRulesGet(ruleGetRequest);
HandleOperationErrors(ruleGetResponse.OperationResult);
BusinessRule selectedBusinessRule = ruleGetResponse.BusinessRuleSet.BusinessRulesMember[0];
// Create the request object.
MDSTestService.BusinessRulesDeleteRequest ruleDeleteRequest = new MDSTestService.BusinessRulesDeleteRequest();
ruleDeleteRequest.DeleteCriteria = new BRDeleteCriteria();
ruleDeleteRequest.DeleteCriteria.BusinessRules = new System.Collections.ObjectModel.Collection<Guid> { };
ruleDeleteRequest.DeleteCriteria.BusinessRules.Add(selectedBusinessRule.Identifier.Id);
// Delete the business rule.
MDSTestService.MessageResponse ruleDeleteResponse = clientProxy.BusinessRulesDelete(ruleDeleteRequest);
HandleOperationErrors(ruleDeleteResponse.OperationResult);
// Create the request object.
MDSTestService.BusinessRulesPublishRequest rulePublishRequest = new MDSTestService.BusinessRulesPublishRequest();
rulePublishRequest.BRPublishCriteria = new BRPublishCriteria();
rulePublishRequest.BRPublishCriteria.EntityId = entityId;
rulePublishRequest.BRPublishCriteria.ModelId = modelId;
rulePublishRequest.BRPublishCriteria.MemberType = BREntityMemberType.Leaf;
// Publish the business rule.
MDSTestService.MessageResponse rulePublishResponse = clientProxy.BusinessRulesPublish(rulePublishRequest);
HandleOperationErrors(rulePublishResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
}
}
@@ -0,0 +1,46 @@
//==============================================================================
//
// © Microsoft corp. All rights reserved.
// This code is licensed under the Microsoft Public License.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//==============================================================================
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("BusinessRules")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("BusinessRules")]
[assembly: AssemblyCopyright("Copyright © Microsoft")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("07bb8514-26ab-45db-9da4-4d52d453c763")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,38 @@
# Master Data Services Business Rule API Sample
This is a C# code sample to show how to use MDS APIs to create, edit, validate, exclude, and delete business rules. The scenario in this sample is that the system creates a business rule (when "Code equals ABC", "Name must be equal to Test") and edits the business rule (change the condition to “Code starts with Test”).
The next step creates a member that causes a business rule validation error (add a member with Code = “Test12” and Name = “AA”), processes validation, and gets the validation issue information. To complete the example, the sample excludes and deletes the business rule.
For every action that changes the business rule status (creates, edits, excludes, and deletes), the business rule must be published to finalize the change.
Please set the MDS URL (plus /Service/Service.svc) to mdsURL in Program.cs.
```C#
string mdsURL = @"http://localhost/MDS/Service/Service.svc";
```
Program.cs uses Reference.cs (the service reference class file) that was generated by using Visual Studio to access MDS Web service API. You may need to regenerate Reference.cs in case when MDS Web service API is changed.
To generate Reference.cs using Visual Studio:
You need to expose the WSDL. Exposing the WSDL is only necessary at the time when you want to generate proxy classes using a client development tool such as Visual Studio. After a proxy has been generated, the WSDL does not need to be exposed going forward for client programs to call the API.
To enable an http/https Get on the WSDL:
1. Open the MDS web.config file in a text editor (<Program Files>\Microsoft SQL Server\Master Data Services\WebApplication\web.config).
2. Search for the tag serviceMetadata and set httpGetEnabled to true (or httpsGetEnabled if using SSL).
To also enable service exception details for additional debugging (not necessary for standard, trapped errors):
1. Search for the tag serviceDebug and set includeExceptionDetailInFaults to true.
After that you need to add a Service Reference to http://ServerName/MdsSiteName/service/service.svc and set the namespace to the service to "MDSTestService" in the following steps using Visual Studio.
1. Click "Add Service Reference".
2. In Address, enter the URL to the MDS service which will be “http://ServerName/MdsSiteName/service/service.svc”.
3. Specify the namespace to the service as "MDSTestService" in the Namespace box.
4. Click the Advanced button to configure advanced settings.
5. Check Always generate message contracts.
6. Set the Collection type drop-down to System.Collections.ObjectModel.Collection.
7. Click OK to return to the Add Service Reference dialog.
8. Click OK.
Reference.cs will be generated in BusinessRules\Service References\MDSTestService folder. You can replace BusinessRules\Reference.cs with the newly generated one.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{7FA4CB6A-A741-431D-90FB-CB6D355D3CF5}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>EntityBasedStaging</RootNamespace>
<AssemblyName>EntityBasedStaging</AssemblyName>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Reference.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
@@ -0,0 +1,22 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.40629.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityBasedStaging", "EntityBasedStaging.csproj", "{7FA4CB6A-A741-431D-90FB-CB6D355D3CF5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7FA4CB6A-A741-431D-90FB-CB6D355D3CF5}.Debug|x86.ActiveCfg = Debug|x86
{7FA4CB6A-A741-431D-90FB-CB6D355D3CF5}.Debug|x86.Build.0 = Debug|x86
{7FA4CB6A-A741-431D-90FB-CB6D355D3CF5}.Release|x86.ActiveCfg = Release|x86
{7FA4CB6A-A741-431D-90FB-CB6D355D3CF5}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,358 @@
//==============================================================================
//
// © Microsoft corp. All rights reserved.
// This code is licensed under the Microsoft Public License.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//==============================================================================
using System;
using System.Threading;
using System.ServiceModel;
using EntityBasedStaging.MDSTestService; // For the created service reference.
namespace EntityBasedStaging
{
class Program
{
// MDS service client proxy object.
private static ServiceClient clientProxy;
// Set the MDS URL (plus /Service/Service.svc) here.
private static string mdsURL = @"http://localhost/MDS/Service/Service.svc";
static void Main(string[] args)
{
try
{
// Before running this sample code you need to populate the staging table for the entity that you use with a staging record.
// The staging record should have batch tag = "Test1".
// Example:
// Populate the record into stg.TestEntity_Leaf staging table with batch tag = “Test1” by running the SQL script.
// Note that the Code and Name below is set to trigger the business rule validation error (if Code is “ABC”, Name must be equal to “Test”).
// Insert into stg.TestEntity_Leaf
// (ImportType, BatchTag, Code, Name)
// values (0, N'Test1', N'ABC', N'Name2');
// ImportType = 0 means the import type is merge optimistic.
// Create a service proxy.
clientProxy = GetClientProxy(mdsURL);
// Process staging data in the staging table with the specified batch tag.
// You need to specify the existing model name, entity name, version name, and batch tag.
ProcessStagingData("TestModel", "TestEntity", "VERSION_1", "Test1", MemberType.Leaf);
// Wait till the batch process completes (wait for 60 seconds).
Thread.Sleep(60000);
// Get the staging information such as the batch status and the error information.
// In this example GetStagingInformation method returns the batch id for the specified batch tag.
// You need to specify the existing model name and batch tag.
int batchId = GetStagingInformation("TestModel", "Test1");
// Clear the batch staging data for the specified batch id.
// This is the step to set the batch status as "Cleared" and remove the staging records from the staging table for the batch id.
ClearStagingData("TestModel", batchId);
// The followings are to validate the record that is added by Entity Based Staging.
// Create a new business rule and publish the rule to enable it in the validation process.
// You need to specify the existing model and entity names.
CreateAndPublishBR("TestModel", "TestEntity", "Rule1");
// Process the validation and get the list of validation issues.
// You need to specify the existing model, entity, and version names.
GetBRValidationIssue("TestModel", "TestEntity", "Rule1", "VERSION_1");
}
catch (Exception ex)
{
Console.WriteLine("Error creating a service proxy: {0}", ex);
}
}
// Creates MDS service client proxy.
private static ServiceClient GetClientProxy(string targetURL)
{
// Create an endpoint address using the URL.
EndpointAddress endptAddress = new EndpointAddress(targetURL);
// Create and configure the WS Http binding.
WSHttpBinding wsBinding = new WSHttpBinding();
// Create and return the client proxy.
return new ServiceClient(wsBinding, endptAddress);
}
// Handles operation errors.
private static void HandleOperationErrors(MDSTestService.OperationResult result)
{
string errorMessage = string.Empty;
if (result.Errors.Count > 0)
{
foreach (MDSTestService.Error anError in result.Errors)
{
errorMessage += "Operation Error: " + anError.Code + ":" + anError.Description + "\n";
}
// Show the error messages.
Console.WriteLine(errorMessage);
}
}
// Process staging data in the staging table with the specified batch tag.
private static void ProcessStagingData(string modelName, string entityName, string versionName, string batchTag, MemberType memberType)
{
try
{
// Set model, entity, and version objects.
MDSTestService.Identifier modelId = new MDSTestService.Identifier { Name = modelName };
MDSTestService.Identifier entityId = new MDSTestService.Identifier { Name = entityName };
MDSTestService.Identifier versionId = new MDSTestService.Identifier { Name = versionName };
// Get entity MUID.
MetadataGetRequest getRequest = new MetadataGetRequest();
getRequest.SearchCriteria = new MetadataSearchCriteria();
getRequest.SearchCriteria.Models = new System.Collections.ObjectModel.Collection<Identifier> { };
getRequest.SearchCriteria.Models.Add(modelId);
getRequest.SearchCriteria.Entities = new System.Collections.ObjectModel.Collection<Identifier> { };
getRequest.SearchCriteria.Entities.Add(entityId);
getRequest.SearchCriteria.Versions = new System.Collections.ObjectModel.Collection<Identifier> { };
getRequest.SearchCriteria.Versions.Add(versionId);
getRequest.SearchCriteria.SearchOption = SearchOption.BothUserDefinedAndSystemObjects;
getRequest.ResultOptions = new MetadataResultOptions();
getRequest.ResultOptions.Entities = ResultType.Identifiers;
getRequest.ResultOptions.Versions = ResultType.Identifiers;
MetadataGetResponse getResponse = clientProxy.MetadataGet(getRequest);
HandleOperationErrors(getResponse.OperationResult);
// Set entity MUID since it cannot be specified only by name.
entityId.Id = getResponse.Metadata.Entities[0].Identifier.Id;
// Set entity MUID since it cannot be specified only by name.
versionId.Id = getResponse.Metadata.Versions[0].Identifier.Id;
// Create the request object.
MDSTestService.EntityStagingProcessRequest processRequest = new EntityStagingProcessRequest();
processRequest.BatchTag = batchTag;
processRequest.EntityId = entityId;
processRequest.VersionId = versionId;
processRequest.MemberType = MemberType.Leaf;
// Process staging data.
MDSTestService.EntityStagingProcessResponse processResponse = clientProxy.EntityStagingProcess(processRequest);
HandleOperationErrors(processResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
// Get the staging information such as batch status and the error information.
// In this example returns the batch id for the specified batch tag.
private static int GetStagingInformation(string modelName, string batchTag)
{
int batchId = -1;
try
{
// Set model object.
MDSTestService.Identifier modelId = new MDSTestService.Identifier { Name = modelName };
// Create the request object.
// Get batch information for the specified model.
MDSTestService.EntityStagingGetRequest getInfoRequest = new EntityStagingGetRequest();
EntityStagingGetCriteria getCriteria = new EntityStagingGetCriteria();
getCriteria.ModelId = modelId;
getCriteria.IncludeClearedBatches = false;
getInfoRequest.GetCriteria = getCriteria;
MDSTestService.EntityStagingGetResponse getInfoResponse = clientProxy.EntityStagingGet(getInfoRequest);
HandleOperationErrors(getInfoResponse.OperationResult);
// Find the batch id (the last one) for the specified batch tag.
foreach (EntityStagingBatch aBatch in getInfoResponse.Batches)
{
if (string.Equals(aBatch.BatchTag, batchTag, StringComparison.OrdinalIgnoreCase))
{
batchId = aBatch.BatchId.Value;
// You can also access the error information or the batch status.
// aBatch.ErrorView
// aBatch.Status
}
}
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
return batchId;
}
// Clear the batch staging data for the specified batch id.
private static void ClearStagingData(string modelName, int batchId)
{
try
{
// Set model and batch objects.
MDSTestService.Identifier modelId = new MDSTestService.Identifier { Name = modelName };
// Create the request object.
MDSTestService.EntityStagingClearRequest clearRequest = new EntityStagingClearRequest();
clearRequest.ModelId = modelId;
clearRequest.BatchId = batchId;
// Clear the batch staging data.
MDSTestService.EntityStagingClearResponse processResponse = clientProxy.EntityStagingClear(clearRequest);
HandleOperationErrors(processResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
// Create a new business rule and publish the rule to enable it in the validation process.
private static void CreateAndPublishBR(string modelName, string entityName, string ruleName)
{
try
{
// Set Model and Entity objects.
Identifier modelId = new Identifier { Name = modelName };
Identifier entityId = new Identifier { Name = entityName };
// Create the request object.
MDSTestService.BusinessRulesCreateRequest ruleCreateRequest = new MDSTestService.BusinessRulesCreateRequest();
ruleCreateRequest.ReturnCreatedIdentifiers = true;
ruleCreateRequest.BusinessRuleSet = new MDSTestService.BusinessRules();
// Create a new business rule.
BusinessRule newRule = new BusinessRule();
ruleCreateRequest.BusinessRuleSet.BusinessRulesMember = new System.Collections.ObjectModel.Collection<BusinessRule> { };
ruleCreateRequest.BusinessRuleSet.BusinessRulesMember.Add(newRule);
newRule.Identifier = new MemberTypeContextIdentifier
{
Name = ruleName,
ModelId = modelId,
EntityId = entityId,
MemberType = MemberType.Leaf
};
newRule.Priority = 10;
newRule.BRConditionTree = new BRConditionTreeNode();
newRule.BRConditionTree.LogicalOperator = LogicalOperator.And;
newRule.BRConditionTree.Sequence = 1;
// Create the rule condition "Code equals ABC".
BRCondition ruleCondition = new BRCondition();
newRule.BRConditionTree.BRConditions = new System.Collections.ObjectModel.Collection<BRCondition> { };
newRule.BRConditionTree.BRConditions.Add(ruleCondition);
ruleCondition.Sequence = 1;
// Create the condition prefix argument for Code attribute.
BRAttributeArgument conditionPrefix = new BRAttributeArgument();
ruleCondition.PrefixArgument = conditionPrefix;
conditionPrefix.PropertyName = BRPropertyName.Anchor;
conditionPrefix.AttributeId = new Identifier { Name = "Code" };
// Set the condition operator.
ruleCondition.Operator = BRItemType.IsEqual;
// Set the postfix argument "ABC".
BRFreeformArgument conditionPostfix = new BRFreeformArgument();
ruleCondition.PostfixArguments = new System.Collections.ObjectModel.Collection<object> { };
ruleCondition.PostfixArguments.Add(conditionPostfix);
conditionPostfix.PropertyName = BRPropertyName.Value;
conditionPostfix.Value = "ABC";
// Create the rule action "Name must be equal to Test".
BRAction ruleAction = new BRAction();
newRule.BRActions = new System.Collections.ObjectModel.Collection<BRAction> { };
newRule.BRActions.Add(ruleAction);
ruleAction.Sequence = 1;
// Set the action prefix argument for Name attribute.
BRAttributeArgument actionPrefix = new BRAttributeArgument();
ruleAction.PrefixArgument = actionPrefix;
actionPrefix.PropertyName = BRPropertyName.Anchor;
actionPrefix.AttributeId = new Identifier { Name = "Name" };
// Set the action operator.
ruleAction.Operator = BRItemType.MustBeEqual;
// Set the action postfix argument.
BRFreeformArgument actionPostfix = new BRFreeformArgument();
ruleAction.PostfixArguments = new System.Collections.ObjectModel.Collection<object> { };
ruleAction.PostfixArguments.Add(actionPostfix);
actionPostfix.PropertyName = BRPropertyName.Value;
actionPostfix.Value = "Test";
// Create the business rule.
MDSTestService.BusinessRulesCreateResponse ruleCreateResponse = clientProxy.BusinessRulesCreate(ruleCreateRequest);
HandleOperationErrors(ruleCreateResponse.OperationResult);
// Create the request object.
MDSTestService.BusinessRulesPublishRequest rulePublishRequest = new MDSTestService.BusinessRulesPublishRequest();
rulePublishRequest.BRPublishCriteria = new BRPublishCriteria();
rulePublishRequest.BRPublishCriteria.EntityId = entityId;
rulePublishRequest.BRPublishCriteria.ModelId = modelId;
rulePublishRequest.BRPublishCriteria.MemberType = BREntityMemberType.Leaf;
// Publish the business rule.
MDSTestService.MessageResponse rulePublishResponse = clientProxy.BusinessRulesPublish(rulePublishRequest);
HandleOperationErrors(rulePublishResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
// Process the validation and get the list of validation issues.
private static void GetBRValidationIssue(string modelName, string entityName, string ruleName, string versionName)
{
try
{
// Set Model, Entity, and Version objects.
Identifier modelId = new Identifier { Name = modelName };
Identifier entityId = new Identifier { Name = entityName };
Identifier versionId = new Identifier { Name = versionName };
// Create the request object.
MDSTestService.ValidationProcessRequest validationProcessRequest = new MDSTestService.ValidationProcessRequest();
validationProcessRequest.ValidationProcessCriteria = new ValidationProcessCriteria();
validationProcessRequest.ValidationProcessCriteria.ModelId = modelId;
validationProcessRequest.ValidationProcessCriteria.EntityId = entityId;
validationProcessRequest.ValidationProcessCriteria.VersionId = versionId;
validationProcessRequest.ValidationProcessOptions = new ValidationProcessOptions();
validationProcessRequest.ValidationProcessOptions.ReturnValidationResults = true;
// Process validation and get a validation issue.
MDSTestService.ValidationProcessResponse validationProcessResponse = clientProxy.ValidationProcess(validationProcessRequest);
HandleOperationErrors(validationProcessResponse.OperationResult);
// Show the validation issue's description.
if (validationProcessResponse.ValidationIssueList.Count > 0)
{
ValidationIssue validationIssue = validationProcessResponse.ValidationIssueList[0];
Console.WriteLine("Validation issue: " + validationIssue.Description);
}
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
}
}
@@ -0,0 +1,46 @@
//==============================================================================
//
// © Microsoft corp. All rights reserved.
// This code is licensed under the Microsoft Public License.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//==============================================================================
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("EntityBasedStaging")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("EntityBasedStaging")]
[assembly: AssemblyCopyright("Copyright © Microsoft")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("c4e13b74-8e35-4aab-a7cb-c53046b5c20d")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,61 @@
# Master Data Services Entity Based Staging API Sample
This is a C# code sample to show how to process, clear, and get information about entity based staging data by using MDS APIs. This sample has the following scenarios.
1. Process the staging data in the staging table that has the specified batch tag (“Test1”). After calling the API to process the staging data wait untill the batch process completes (wait for 60 seconds).
2. Get the staging information such as the batch status and the error information. In this example, GetStagingInformation method returns the batch id for the specified batch tag.
3. Clear the batch staging data for the specified batch id.
4. Create a new business rule to validate the record that is added by Entity Based Staging and get the validation error.
Before running this sample code you need to populate the staging table for the entity that you use with a staging record.
The staging record should have batch tag = "Test1".
Example:
Populate the record into stg.TestEntity_Leaf staging table with batch tag = “Test1” by running the SQL script.
Note that the Code and Name below is set to trigger the business rule validation error (if Code is “ABC”, Name must be equal to “Test”).
```SQL
Insert into stg.TestEntity_Leaf
(ImportType, BatchTag, Code, Name)
values (0, N'Test1', N'ABC', N'Name2');
```
ImportType = 0 means the import type is merge optimistic.
Please set the MDS URL (plus /Service/Service.svc) to mdsURL in Program.cs.
```C#
string mdsURL = @"http://localhost/MDS/Service/Service.svc";
```
Program.cs uses Reference.cs (the service reference class file) that was generated by using Visual Studio to access MDS Web service API. You may need to regenerate Reference.cs in case when MDS Web service API is changed.
To generate Reference.cs using Visual Studio:
You need to expose the WSDL. Exposing the WSDL is only necessary at the time when you want to generate proxy classes using a client development tool such as Visual Studio. After a proxy has been generated, the WSDL does not need to be exposed going forward for client programs to call the API.
To enable an http/https Get on the WSDL:
1. Open the MDS web.config file in a text editor (<Program Files>\Microsoft SQL Server\Master Data Services\WebApplication\web.config).
2. Search for the tag serviceMetadata and set httpGetEnabled to true (or httpsGetEnabled if using SSL).
To also enable service exception details for additional debugging (not necessary for standard, trapped errors):
1. Search for the tag serviceDebug and set includeExceptionDetailInFaults to true.
After that you need to add a Service Reference to http://ServerName/MdsSiteName/service/service.svc and set the namespace to the service to "MDSTestService" in the following steps using Visual Studio.
1. Click "Add Service Reference".
2. In Address, enter the URL to the MDS service which will be “http://ServerName/MdsSiteName/service/service.svc”.
3. Specify the namespace to the service as "MDSTestService" in the Namespace box.
4. Click the Advanced button to configure advanced settings.
5. Check Always generate message contracts.
6. Set the Collection type drop-down to System.Collections.ObjectModel.Collection.
7. Click OK to return to the Add Service Reference dialog.
8. Click OK.
Reference.cs will be generated in EntityBasedStaging\Service References\MDSTestService folder. You can replace EntityBasedStaging\Reference.cs with the newly generated one.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{BCEB2125-EA3D-4F38-952E-6B409AADFC00}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MasterData</RootNamespace>
<AssemblyName>MasterDataSample</AssemblyName>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Reference.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
@@ -0,0 +1,22 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.40629.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MasterData", "MasterData.csproj", "{BCEB2125-EA3D-4F38-952E-6B409AADFC00}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BCEB2125-EA3D-4F38-952E-6B409AADFC00}.Debug|x86.ActiveCfg = Debug|x86
{BCEB2125-EA3D-4F38-952E-6B409AADFC00}.Debug|x86.Build.0 = Debug|x86
{BCEB2125-EA3D-4F38-952E-6B409AADFC00}.Release|x86.ActiveCfg = Release|x86
{BCEB2125-EA3D-4F38-952E-6B409AADFC00}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,601 @@
//==============================================================================
//
// © Microsoft corp. All rights reserved.
// This code is licensed under the Microsoft Public License.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//==============================================================================
using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel;
using MasterData.MDSTestService; // For the created service reference.
namespace MasterData
{
static class Program
{
// MDS service client proxy object.
private static ServiceClient clientProxy;
// Set the MDS URL (plus /Service/Service.svc) here.
private static string mdsURL = @"http://localhost/MDS/Service/Service.svc";
static void Main()
{
Identifier modelId = null;
try
{
// Create a service proxy.
clientProxy = GetClientProxy(mdsURL);
string model = "TestModel" + Guid.NewGuid().ToString("N");
string entity = "TestEntity";
string explicitHierarchy = "TestEH";
// "VERSION_1" is a default version name for a new model.
string version = "VERSION_1";
modelId = CreateModel(model, entity, explicitHierarchy);
// Create an entity member (leaf member) with a specified name, code, and member type.
string leafMemberCode = "Code" + Guid.NewGuid().ToString("N");
string leafMemberName = "Name" + Guid.NewGuid().ToString("N");
CreateEntityMember(model, version, entity, leafMemberName, leafMemberCode, MemberType.Leaf);
// Get the entity member identifier with specified model name, version name, entity name, member type, and entity member code.
GetEntityMemberByCode(model, version, entity, MemberType.Leaf, leafMemberCode);
// Update an entity member (change name) with the member code.
leafMemberName = "Name" + Guid.NewGuid().ToString("N");
UpdateEntityMember(model, version, entity, leafMemberCode, MemberType.Leaf, leafMemberName);
// Create a consolidated memeber with specified name, code, member type, and hierarchy name.
// HierarchyName is used only when the member type is Consolidated.
string consolidatedMemberCode = "Code" + Guid.NewGuid().ToString("N");
string consolidatedMemberName = "Name" + Guid.NewGuid().ToString("N");
CreateEntityMember(model, version, entity, consolidatedMemberName, consolidatedMemberCode,
MemberType.Consolidated, explicitHierarchy);
// Get the entity member identifier with specified model name, version name, entity name, member type, and entity member name.
GetEntityMemberByName(model, version, entity, MemberType.Consolidated, consolidatedMemberName);
// Update an entity member relationship.
// You need to specify the existing hierachy name, parent member code, and child member code.
UpdateEntityMemberRelationship(model, version, entity, explicitHierarchy, consolidatedMemberCode,
leafMemberCode);
// Delete the leaf member with the member code.
DeleteEntityMember(model, version, entity, leafMemberCode, MemberType.Leaf);
// Delete the consolidated member with the member code.
DeleteEntityMember(model, version, entity, consolidatedMemberCode, MemberType.Consolidated);
string updateLeafMemberCode = "Code" + Guid.NewGuid().ToString("N");
string updateLeafMemberName = "Name" + Guid.NewGuid().ToString("N");
CreateEntityMember(model, version, entity, updateLeafMemberName, updateLeafMemberCode, MemberType.Leaf, "");
string deleteLeafMemberCode = "Code" + Guid.NewGuid().ToString("N");
string deleteLeafMemberName = "Name" + Guid.NewGuid().ToString("N");
CreateEntityMember(model, version, entity, deleteLeafMemberName, deleteLeafMemberCode, MemberType.Leaf, "");
SetApprovalRequired(model, entity, true);
Debug.Assert( GetApprovalRequired(model, entity));
string changesetName = "Changeset" + Guid.NewGuid().ToString("N");
var changesetId = ChangesetSave(model, version, entity, new Identifier { Name = changesetName },
ChangesetStatus.Open);
string newLeafMemberCode = "Code" + Guid.NewGuid().ToString("N");
string newLeafMemberName = "Name" + Guid.NewGuid().ToString("N");
CreateEntityMember(model, version, entity, newLeafMemberName, newLeafMemberCode, MemberType.Leaf, null, changesetName);
updateLeafMemberName = "Name" + Guid.NewGuid().ToString("N");
UpdateEntityMember(model, version, entity, updateLeafMemberCode, MemberType.Leaf, updateLeafMemberName, changesetName);
DeleteEntityMember(model, version, entity, deleteLeafMemberCode, MemberType.Leaf, changesetName);
var members = GetEntityMembers(model, version, entity, MemberType.Leaf, changesetName);
Debug.Assert(members.Count == 3);
// Submit to approve
ChangesetSave(model, version, entity, changesetId, ChangesetStatus.Pending);
// Approve require a different admin
// ChangesetSave(model, version, entity, changesetId, ChangesetStatus.Approved);
// Recall
ChangesetSave(model, version, entity, changesetId, ChangesetStatus.Open);
// Delete
ChangesetDelete(model, version, changesetName);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
finally
{
if (modelId != null)
{
DeleteModel(modelId);
}
}
}
// Creates MDS service client proxy.
private static ServiceClient GetClientProxy(string targetURL)
{
// Create an endpoint address using the URL.
EndpointAddress endptAddress = new EndpointAddress(targetURL);
// Create and configure the WS Http binding.
WSHttpBinding wsBinding = new WSHttpBinding();
// Create and return the client proxy.
return new ServiceClient(wsBinding, endptAddress);
}
// Handles operation errors.
private static void HandleOperationErrors(OperationResult result)
{
string errorMessage = string.Empty;
if (result.Errors.Count > 0)
{
foreach (Error anError in result.Errors)
{
errorMessage += "Operation Error: " + anError.Code + ":" + anError.Description + "\n";
}
// Show the error messages.
Console.WriteLine(errorMessage);
// Throw an exception.
throw new Exception(errorMessage);
}
}
private static Identifier CreateModel(string modelName, string entityName, string explicitHierarchyName)
{
MetadataCreateRequest createRequest =
new MetadataCreateRequest
{
Metadata = new Metadata
{
Models = new Collection<Model>
{
new Model
{
Identifier = new Identifier {Name = modelName},
Entities = new Collection<Entity>
{
new Entity
{
Identifier = new ModelContextIdentifier
{
Name = entityName,
ModelId = new Identifier {Name = modelName}
},
ExplicitHierarchies = new Collection<ExplicitHierarchy>
{
new ExplicitHierarchy
{
Identifier = new EntityContextIdentifier
{
Name = explicitHierarchyName,
ModelId = new Identifier {Name = modelName},
EntityId = new Identifier {Name = entityName}
}
}
}
}
}
}
}
},
ReturnCreatedIdentifiers = true
};
MetadataCreateResponse createResponse = clientProxy.MetadataCreate(createRequest);
HandleOperationErrors(createResponse.OperationResult);
return createResponse.MetadataCreated.Models[0].Identifier;
}
private static void DeleteModel(Identifier modelId)
{
MetadataDeleteRequest deleteRequest =
new MetadataDeleteRequest
{
Metadata = new Metadata
{
Models = new Collection<Model>
{
new Model
{
Identifier = modelId
}
}
}
};
MetadataDeleteResponse deleteResponse = clientProxy.MetadataDelete(deleteRequest);
HandleOperationErrors(deleteResponse.OperationResult);
}
// Create an entity member with a specified name, code, and member type.
// HierarchyName is used only when the member type is Consolidated.
private static void CreateEntityMember(string modelName, string versionName, string entityName, string aNewMemberName, string aNewCode, MemberType memberType, string hierarchyName = null, string changesetName = null)
{
// Create the request object for entity creation.
EntityMembersCreateRequest createRequest = new EntityMembersCreateRequest();
createRequest.Members = new EntityMembers();
createRequest.ReturnCreatedIdentifiers = true;
// Set the modelId, versionId, and entityId.
createRequest.Members.ModelId = new Identifier { Name = modelName };
createRequest.Members.VersionId = new Identifier { Name = versionName };
createRequest.Members.EntityId = new Identifier { Name = entityName };
createRequest.Members.MemberType = memberType;
createRequest.Members.Members = new Collection<Member> { };
Member aNewMember = new Member();
aNewMember.MemberId = new MemberIdentifier() { Name = aNewMemberName, Code = aNewCode, MemberType = memberType };
if (memberType == MemberType.Consolidated)
{
// In case when the member type is consolidated set the parent information.
// Set the hierarchy name and the parent code ("ROOT" means the root node of the hierarchy).
aNewMember.Parents = new Collection<Parent> { };
Parent aParent = new Parent();
aParent.HierarchyId = new Identifier() { Name = hierarchyName };
aParent.ParentId = new MemberIdentifier() { Code = "ROOT" };
aNewMember.Parents.Add(aParent);
}
if (!string.IsNullOrEmpty(changesetName))
{
createRequest.Members.ChangesetId = new Identifier {Name = changesetName};
}
createRequest.Members.Members.Add(aNewMember);
// Create a new entity member
EntityMembersCreateResponse createResponse = clientProxy.EntityMembersCreate(createRequest);
HandleOperationErrors(createResponse.OperationResult);
}
// Get the entity member identifier with specified model name, version name, entity name, member type, and entity member name.
private static MemberIdentifier GetEntityMemberByName(string modelName, string versionName, string entityName, MemberType memberType, string memberName)
{
MemberIdentifier memberIdentifier = new MemberIdentifier();
// Create the request object to get the entity information.
EntityMembersGetRequest getRequest = new EntityMembersGetRequest();
getRequest.MembersGetCriteria = new EntityMembersGetCriteria();
// Set the modelId, versionId, entityId, and the member name.
getRequest.MembersGetCriteria.ModelId = new Identifier { Name = modelName };
getRequest.MembersGetCriteria.VersionId = new Identifier { Name = versionName };
getRequest.MembersGetCriteria.EntityId = new Identifier { Name = entityName };
getRequest.MembersGetCriteria.MemberType = memberType;
getRequest.MembersGetCriteria.MemberReturnOption = MemberReturnOption.Data;
getRequest.MembersGetCriteria.SearchTerm = "Name = '" + memberName + "'";
// Get the entity member information
EntityMembersGetResponse getResponse = clientProxy.EntityMembersGet(getRequest);
// Get the entity member identifier.
memberIdentifier = getResponse.EntityMembers.Members[0].MemberId;
// Show attribute information.
ShowMemberInformation(getResponse.EntityMembers.Members[0]);
HandleOperationErrors(getResponse.OperationResult);
return memberIdentifier;
}
// Get the entity member identifier with specified model name, version name, entity name, member type, and entity member code.
private static MemberIdentifier GetEntityMemberByCode(string modelName, string versionName, string entityName, MemberType memberType, string memberCode)
{
MemberIdentifier memberIdentifier = new MemberIdentifier();
// Create the request object to get the entity information.
EntityMembersGetRequest getRequest = new EntityMembersGetRequest();
getRequest.MembersGetCriteria = new EntityMembersGetCriteria();
// Set the modelId, versionId, entityId, and the member code.
getRequest.MembersGetCriteria.ModelId = new Identifier { Name = modelName };
getRequest.MembersGetCriteria.VersionId = new Identifier { Name = versionName };
getRequest.MembersGetCriteria.EntityId = new Identifier { Name = entityName };
getRequest.MembersGetCriteria.MemberType = memberType;
getRequest.MembersGetCriteria.MemberReturnOption = MemberReturnOption.Data;
getRequest.MembersGetCriteria.SearchTerm = "Code = '" + memberCode + "'";
// Get the entity member information
EntityMembersGetResponse getResponse = clientProxy.EntityMembersGet(getRequest);
// Get the entity member identifier.
memberIdentifier = getResponse.EntityMembers.Members[0].MemberId;
// Show attribute information.
ShowMemberInformation(getResponse.EntityMembers.Members[0]);
HandleOperationErrors(getResponse.OperationResult);
return memberIdentifier;
}
private static Collection<Member> GetEntityMembers(string modelName, string versionName, string entityName, MemberType memberType, string changesetName)
{
// Create the request object to get the entity information.
EntityMembersGetRequest getRequest = new EntityMembersGetRequest
{
MembersGetCriteria = new EntityMembersGetCriteria
{
ModelId = new Identifier {Name = modelName},
VersionId = new Identifier {Name = versionName},
EntityId = new Identifier {Name = entityName},
MemberType = memberType,
MemberReturnOption = MemberReturnOption.Data
}
};
if (!string.IsNullOrEmpty(changesetName))
{
getRequest.MembersGetCriteria.ChangesetId = new Identifier { Name = changesetName };
}
// Get the entity member information
EntityMembersGetResponse getResponse = clientProxy.EntityMembersGet(getRequest);
HandleOperationErrors(getResponse.OperationResult);
foreach (var member in getResponse.EntityMembers.Members)
{
// Show attribute information.
ShowMemberInformation(member);
}
return getResponse.EntityMembers.Members;
}
// Show attribute information.
private static void ShowMemberInformation(Member member)
{
Console.WriteLine("Member Name:{0} Code: {1}", member.MemberId.Name, member.MemberId.Code);
foreach (MDSTestService.Attribute anAttribute in member.Attributes)
{
string attributeType = string.Empty;
switch (anAttribute.Type)
{
case AttributeValueType.String:
attributeType = "String";
break;
case AttributeValueType.Number:
attributeType = "Number";
break;
case AttributeValueType.DateTime:
attributeType = "DateTime";
break;
case AttributeValueType.Domain:
attributeType = "Domain";
break;
case AttributeValueType.File:
attributeType = "File";
break;
default:
attributeType = "Not Specified";
break;
}
// Get the code value when the attribute is DBA.
if (anAttribute.Type == AttributeValueType.Domain)
{
MemberIdentifier dbaMemberId = (MemberIdentifier)anAttribute.Value;
Console.WriteLine("Attribute Name:{0} Attribute Type: {1} Attribute Value:{2}", anAttribute.Identifier.Name, attributeType, dbaMemberId.Code);
}
else
{
Console.WriteLine("Attribute Name:{0} Attribute Type: {1} Attribute Value:{2}", anAttribute.Identifier.Name, attributeType, anAttribute.Value);
}
}
}
// Update an entity member (change name) with the member code.
private static void UpdateEntityMember(string modelName, string versionName, string entityName, string memberCode, MemberType memberType, string newMemberName, string changesetName = null)
{
// Create the request object for entity update.
EntityMembersUpdateRequest updateRequest = new EntityMembersUpdateRequest();
updateRequest.Members = new EntityMembers();
// Set the modelName, the versionName, and the entityName.
updateRequest.Members.ModelId = new Identifier { Name = modelName };
updateRequest.Members.VersionId = new Identifier { Name = versionName };
updateRequest.Members.EntityId = new Identifier { Name = entityName };
updateRequest.Members.MemberType = MemberType.Leaf;
updateRequest.Members.Members = new Collection<Member> { };
Member aMember = new Member();
// Set the member code.
aMember.MemberId = new MemberIdentifier() {Code = memberCode, MemberType = memberType};
aMember.Attributes = new Collection<MDSTestService.Attribute> { };
// Set the new member name into the Attribute object.
MDSTestService.Attribute anAttribute = new MDSTestService.Attribute();
anAttribute.Identifier = new Identifier() { Name = "Name" };
anAttribute.Type = AttributeValueType.String;
anAttribute.Value = newMemberName;
aMember.Attributes.Add(anAttribute);
updateRequest.Members.Members.Add(aMember);
if (!string.IsNullOrEmpty(changesetName))
{
updateRequest.Members.ChangesetId = new Identifier { Name = changesetName };
}
// Update the entity member (change the name).
EntityMembersUpdateResponse createResponse = clientProxy.EntityMembersUpdate(updateRequest);
HandleOperationErrors(createResponse.OperationResult);
}
// Update an entity member relationship.
private static void UpdateEntityMemberRelationship(string modelName, string versionName, string entityName, string hierarchyName, string parentMemberCode, string childMemberCode)
{
// Create the request object for entity update.
EntityMembersUpdateRequest updateRequest = new EntityMembersUpdateRequest();
updateRequest.Members = new EntityMembers();
// Set the modelName, the versionName, and the entityName.
updateRequest.Members.ModelId = new Identifier { Name = modelName };
updateRequest.Members.VersionId = new Identifier { Name = versionName };
updateRequest.Members.EntityId = new Identifier { Name = entityName };
updateRequest.Members.MemberType = MemberType.Leaf;
updateRequest.Members.Members = new Collection<Member> { };
// Set child member information.
Member aMember = new Member();
aMember.MemberId = new MemberIdentifier() { Code = childMemberCode, MemberType = MemberType.Leaf };
aMember.Attributes = new Collection<MDSTestService.Attribute> { };
// Set parent member information.
Parent aParent = new Parent();
aParent.ParentId = new MemberIdentifier() { Code = parentMemberCode, MemberType = MemberType.Consolidated };
aParent.HierarchyId = new Identifier() { Name = hierarchyName };
aParent.RelationshipType = RelationshipType.Parent;
aMember.Parents = new Collection<Parent> { };
aMember.Parents.Add(aParent);
updateRequest.Members.Members.Add(aMember);
// Update the entity member relationship.
EntityMembersUpdateResponse createResponse = clientProxy.EntityMembersUpdate(updateRequest);
HandleOperationErrors(createResponse.OperationResult);
}
// Delete an entity member with the member code.
private static void DeleteEntityMember(string modelName, string versionName, string entityName, string memberCode, MemberType memType, string changesetName = null)
{
// Create the request object for entity member deletion.
EntityMembersDeleteRequest deleteRequest = new EntityMembersDeleteRequest();
deleteRequest.Members = new EntityMembers();
// Set the modelName, the versionName, and the entityName.
deleteRequest.Members.ModelId = new Identifier { Name = modelName };
deleteRequest.Members.VersionId = new Identifier { Name = versionName };
deleteRequest.Members.EntityId = new Identifier { Name = entityName };
deleteRequest.Members.MemberType = memType;
deleteRequest.Members.Members = new Collection<Member> { };
Member aMember = new Member();
aMember.MemberId = new MemberIdentifier() { Code = memberCode, MemberType = memType };
deleteRequest.Members.Members.Add(aMember);
if (!string.IsNullOrEmpty(changesetName))
{
deleteRequest.Members.ChangesetId = new Identifier { Name = changesetName };
}
// Delete the entity member.
EntityMembersDeleteResponse createResponse = clientProxy.EntityMembersDelete(deleteRequest);
HandleOperationErrors(createResponse.OperationResult);
}
private static Identifier ChangesetSave(string modelName, string versionName, string entityName, Identifier changesetId,
ChangesetStatus status)
{
var saveRequest = new EntityMemberChangesetSaveRequest
{
ModelId = new Identifier {Name = modelName},
VersionId = new Identifier {Name = versionName},
Changeset = new Changeset
{
Identifier = changesetId,
EntityId = new Identifier {Name = entityName},
Status = status
}
};
EntityMemberChangesetSaveResponse saveResponse = clientProxy.EntityMemberChangesetSave(saveRequest);
HandleOperationErrors(saveResponse.OperationResult);
return saveResponse.CreatedChangeset;
}
private static void ChangesetDelete(string modelName, string versionName, string name)
{
var deleteRequest = new EntityMemberChangesetDeleteRequest
{
ModelId = new Identifier { Name = modelName },
VersionId = new Identifier { Name = versionName },
ChangesetId = new Identifier { Name = name }
};
EntityMemberChangesetDeleteResponse deleteResponse = clientProxy.EntityMemberChangesetDelete(deleteRequest);
HandleOperationErrors(deleteResponse.OperationResult);
}
private static void ChangesetsGet(string modelName, string versionName, string entityName, ChangesetStatus status = ChangesetStatus.NotSpecified)
{
var getRequest = new EntityMemberChangesetsGetRequest
{
ModelId = new Identifier { Name = modelName },
VersionId = new Identifier { Name = versionName },
EntityId = new Identifier { Name = entityName },
Status = status
};
EntityMemberChangesetsGetResponse getResponse = clientProxy.EntityMemberChangesetsGet(getRequest);
HandleOperationErrors(getResponse.OperationResult);
}
private static bool GetApprovalRequired(string modelName, string entityName)
{
var getRequest = new MetadataGetRequest
{
ResultOptions = new MetadataResultOptions
{
Entities = ResultType.Identifiers
},
SearchCriteria = new MetadataSearchCriteria
{
Models = new Collection<Identifier>
{
new Identifier {Name = modelName}
},
Entities = new Collection<Identifier>
{
new ModelContextIdentifier
{
Name = entityName,
ModelId = new Identifier {Name = modelName}
}
}
}
};
return
clientProxy.MetadataGet(getRequest)
.Metadata.Entities.Single()
.RequireApproval;
}
private static void SetApprovalRequired(string modelName, string entityName, bool approvalRequired)
{
var updateRequest = new MetadataUpdateRequest
{
Metadata = new Metadata
{
Entities = new Collection<Entity>
{
new Entity
{
Identifier = new ModelContextIdentifier
{
Name = entityName,
ModelId = new Identifier {Name = modelName}
},
RequireApproval = approvalRequired
}
}
}
};
MetadataUpdateResponse updateResponse = clientProxy.MetadataUpdate(updateRequest);
HandleOperationErrors(updateResponse.OperationResult);
}
}
}
@@ -0,0 +1,46 @@
//==============================================================================
//
// © Microsoft corp. All rights reserved.
// This code is licensed under the Microsoft Public License.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//==============================================================================
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("MasterData")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("MasterData")]
[assembly: AssemblyCopyright("Copyright © Microsoft")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("bdeeb7de-62b9-49f4-bf69-787d90cbe7d2")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,46 @@
# Master Data Services Master Data API Sample
This is a C# code sample to show how to use MDS APIs to create, read, update, and delete entity members.
The sample code includes the following scenarios.
1. Create a leaf member using MDS API.
2. Get the leaf member information (the member identifier) by the member code using MDS API.
3. Update the leaf member information (change the name) using MDS API.
4. Create a consolidated member using MDS API.
5. Get the consolidated member information (the member identifier) by the member name using MDS API.
6. Update the entity member relationship (make the leaf member a child node of the consolidated member) using MDS API.
7. Delete the consolidated member using MDS API.
8. Delete the leaf member using MDS API.
Please set the MDS URL (plus /Service/Service.svc) to mdsURL in Program.cs.
string mdsURL = @"http://localhost/MDS/Service/Service.svc";
Program.cs uses Reference.cs (the service reference class file) that was generated by using Visual Studio to access MDS Web service API. You may need to regenerate Reference.cs in the case when MDS Web service API is changed.
To generate Reference.cs using Visual Studio:
You need to expose the WSDL. Exposing the WSDL is only necessary at the time when you want to generate proxy classes using a client development tool such as Visual Studio. After a proxy has been generated, the WSDL does not need to be exposed going forward for client programs to call the API.
To enable an http/https Get on the WSDL:
1. Open the MDS web.config file in a text editor (<Program Files\Microsoft SQL Server\Master Data Services\WebApplication\web.config).
2. Search for the tag serviceMetadata and set httpGetEnabled to true (or httpsGetEnabled if using SSL).
To also enable service exception details for additional debugging (not necessary for standard, trapped errors):
1. Search for the tag serviceDebug and set includeExceptionDetailInFaults to true.
After that you need to add a Service Reference to http://ServerName/MdsSiteName/service/service.svc and set the namespace to the service to "MDSTestService" in the following steps using Visual Studio.
1. Click "Add Service Reference".
2. In Address, enter the URL to the MDS service which will be “http://ServerName/MdsSiteName/service/service.svc”.
3. Specify the namespace to the service as "MDSTestService" in the Namespace box.
4. Click the Advanced button to configure advanced settings.
5. Check Always generate message contracts.
6. Set the Collection type drop-down to System.Collections.ObjectModel.Collection.
7. Click OK to return to the Add Service Reference dialog.
8. Click OK.
Reference.cs will be generated in MasterData\Service References\MDSTestService folder. You can replace MasterData\Reference.cs with the newly generated one.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{BCEB2125-EA3D-4F38-952E-6B409AADFC00}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MetadataSample</RootNamespace>
<AssemblyName>MetadataSample</AssemblyName>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Reference.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
@@ -0,0 +1,22 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.40629.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Metadata", "Metadata.csproj", "{BCEB2125-EA3D-4F38-952E-6B409AADFC00}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BCEB2125-EA3D-4F38-952E-6B409AADFC00}.Debug|x86.ActiveCfg = Debug|x86
{BCEB2125-EA3D-4F38-952E-6B409AADFC00}.Debug|x86.Build.0 = Debug|x86
{BCEB2125-EA3D-4F38-952E-6B409AADFC00}.Release|x86.ActiveCfg = Release|x86
{BCEB2125-EA3D-4F38-952E-6B409AADFC00}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,574 @@
//==============================================================================
//
// © Microsoft corp. All rights reserved.
// This code is licensed under the Microsoft Public License.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//==============================================================================
using System;
using System.ServiceModel;
using MetadataSample.MDSTestService; // For the created service reference.
namespace MetadataSample
{
class Program
{
// MDS service client proxy object.
private static ServiceClient clientProxy;
// Set the MDS URL (plus /Service/Service.svc) here.
private static string mdsURL = @"http://localhost/MDS/Service/Service.svc";
static void Main(string[] args)
{
try
{
// Create a service proxy.
clientProxy = GetClientProxy(mdsURL);
}
catch (Exception ex)
{
Console.WriteLine("Error creating a service proxy: {0}", ex);
return;
}
// Create a model with a specified name.
CreateModel("TestModel");
// Get a model information with specified model and version names.
// "VERSION_1" is a default version name for a new model.
Identifier modelIdentifier = GetModel("TestModel", "VERSION_1");
// Update the model name.
UpdateModel(modelIdentifier.Id, "TestModelNew");
// Create an entity with a specified name.
CreateEntity(modelIdentifier.Id, "TestEntity");
// Get an entity information with specified entity name and model id.
ModelContextIdentifier entityIdentifier = GetEntity(modelIdentifier.Id, "TestEntity");
// Update the entity name.
UpdateEntity(modelIdentifier.Id, entityIdentifier.Id, "TestEntityNew");
// Create an attribute with a specified name.
CreateAttribute(modelIdentifier.Id, entityIdentifier.Id, "TestAttribute");
// Get an attribute information with specified attribute name, model id, and entity id.
ModelContextIdentifier attributeIdentifier = GetAttribute(modelIdentifier.Id, entityIdentifier.Id, "TestAttribute");
// Update the attribute name.
UpdateAttribute(modelIdentifier.Id, entityIdentifier.Id, attributeIdentifier.Id, "TestAttributeNew");
// Create an attribute group with a specified name.
CreateAttributeGroup(modelIdentifier.Id, entityIdentifier.Id, "TestAttributeGroup");
// Get an attribute group information with specified attribute group name, model id, and entity id.
ModelContextIdentifier attributeGroupIdentifier = GetAttributeGroup(modelIdentifier.Id, entityIdentifier.Id, "TestAttributeGroup");
// Update the attribute group name and add an attribute to it.
UpdateAttributeGroup(modelIdentifier.Id, entityIdentifier.Id, attributeGroupIdentifier.Id, "TestAttributeGroupNew", attributeIdentifier.Id);
// Delete the attribute group with the specified attribute group id.
DeleteAttributeGroup(attributeGroupIdentifier.Id);
// Delete the attribute with the specified attribute id.
DeleteAttribute(attributeIdentifier.Id);
// Delete the entity with the specified entity id.
DeleteEntity(entityIdentifier.Id);
// Delete the model with the specified model id.
DeleteModel(modelIdentifier.Id);
}
// Creates MDS service client proxy.
private static ServiceClient GetClientProxy(string targetURL)
{
// Create an endpoint address using the URL.
EndpointAddress endptAddress = new EndpointAddress(targetURL);
// Create and configure the WS Http binding.
WSHttpBinding wsBinding = new WSHttpBinding();
// Create and return the client proxy.
return new ServiceClient(wsBinding, endptAddress);
}
// Handles operation errors.
private static void HandleOperationErrors(OperationResult result)
{
string errorMessage = string.Empty;
if (result.Errors.Count > 0)
{
foreach (Error anError in result.Errors)
{
errorMessage += "Operation Error: " + anError.Code + ":" + anError.Description + "\n";
}
// Show the error messages.
Console.WriteLine(errorMessage);
}
}
// Create a model with a specified name.
private static void CreateModel(string modelName)
{
try
{
// Create the request object for model creation.
MetadataCreateRequest createRequest = new MetadataCreateRequest();
createRequest.Metadata = new Metadata();
createRequest.Metadata.Models = new System.Collections.ObjectModel.Collection<Model> { };
Model newModel = new Model();
newModel.Identifier = new Identifier { Name = modelName };
createRequest.Metadata.Models.Add(newModel);
// Create a new model.
MetadataCreateResponse createResponse = clientProxy.MetadataCreate(createRequest);
HandleOperationErrors(createResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
// Get a model information (model identifier) with specified modle and version names.
private static Identifier GetModel(string modelName, string versionName)
{
Identifier modelIdentifier = new Identifier();
try
{
// Create the request object for getting model information.
MetadataGetRequest getRequest = new MetadataGetRequest();
getRequest.SearchCriteria = new MetadataSearchCriteria();
getRequest.SearchCriteria.SearchOption = SearchOption.UserDefinedObjectsOnly;
// Set the model and version names in the search criteria.
getRequest.SearchCriteria.Models = new System.Collections.ObjectModel.Collection<Identifier> { new Identifier { Name = modelName } };
getRequest.SearchCriteria.Versions = new System.Collections.ObjectModel.Collection<Identifier> { new Identifier { Name = versionName } };
getRequest.ResultOptions = new MetadataResultOptions();
getRequest.ResultOptions.Models = ResultType.Details;
// Get a model information.
MetadataGetResponse getResponse = clientProxy.MetadataGet(getRequest);
if (getResponse.Metadata.Models.Count > 0)
{
modelIdentifier = getResponse.Metadata.Models[0].Identifier;
}
HandleOperationErrors(getResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
return modelIdentifier;
}
// Update the model name.
private static void UpdateModel(Guid modelId, string newModelName)
{
try
{
// Create the request object for updating model information.
MetadataUpdateRequest updateRequest = new MetadataUpdateRequest();
updateRequest.Metadata = new Metadata();
updateRequest.Metadata.Models = new System.Collections.ObjectModel.Collection<Model> { };
Model aModel = new Model();
aModel.Identifier = new Identifier { Id = modelId, Name = newModelName };
updateRequest.Metadata.Models.Add(aModel);
// Update the model information.
MetadataUpdateResponse updateResponse = clientProxy.MetadataUpdate(updateRequest);
HandleOperationErrors(updateResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
// Delete the model with the specified model id.
private static void DeleteModel(Guid modelId)
{
try
{
// Create the request object for model deletion.
MetadataDeleteRequest deleteRequest = new MetadataDeleteRequest();
deleteRequest.Metadata = new Metadata();
deleteRequest.Metadata.Models = new System.Collections.ObjectModel.Collection<Model> { };
Model newModel = new Model();
newModel.Identifier = new Identifier { Id = modelId };
deleteRequest.Metadata.Models.Add(newModel);
// Delete the specified model
MetadataDeleteResponse deleteResponse = clientProxy.MetadataDelete(deleteRequest);
HandleOperationErrors(deleteResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
// Create an entity with a specified name.
private static void CreateEntity(Guid modelId, string entityName)
{
try
{
// Create the request object for entity creation.
MetadataCreateRequest createRequest = new MetadataCreateRequest();
createRequest.Metadata = new Metadata();
createRequest.Metadata.Entities = new System.Collections.ObjectModel.Collection<Entity> { };
Entity newEntity = new Entity();
// Set the modelId and the entity name.
newEntity.Identifier = new ModelContextIdentifier { Name = entityName, ModelId = new Identifier { Id = modelId } };
createRequest.Metadata.Entities.Add(newEntity);
// Create a new entity
MetadataCreateResponse createResponse = clientProxy.MetadataCreate(createRequest);
HandleOperationErrors(createResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
// Get an entity information (ModelContextIdentifier for the entity) with specified entity name and model id.
private static ModelContextIdentifier GetEntity(Guid modelId, string entityName)
{
ModelContextIdentifier entityIdentifier = new ModelContextIdentifier();
try
{
// Create the request object for getting entity information.
MetadataGetRequest getRequest = new MetadataGetRequest();
getRequest.SearchCriteria = new MetadataSearchCriteria();
getRequest.SearchCriteria.SearchOption = SearchOption.UserDefinedObjectsOnly;
// Set the entity name and model id
getRequest.SearchCriteria.Entities = new System.Collections.ObjectModel.Collection<Identifier> { new Identifier { Name = entityName } };
getRequest.SearchCriteria.Models = new System.Collections.ObjectModel.Collection<Identifier> { new Identifier { Id = modelId } };
getRequest.ResultOptions = new MetadataResultOptions();
getRequest.ResultOptions.Entities = ResultType.Details;
// Get an entity information.
MetadataGetResponse getResponse = clientProxy.MetadataGet(getRequest);
if (getResponse.Metadata.Entities.Count > 0)
{
entityIdentifier = getResponse.Metadata.Entities[0].Identifier;
}
HandleOperationErrors(getResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
return entityIdentifier;
}
// Update the entity name.
private static void UpdateEntity(Guid modelId, Guid entityId, string newEntityName)
{
try
{
// Create the request object for updating entity information.
MetadataUpdateRequest updateRequest = new MetadataUpdateRequest();
updateRequest.Metadata = new Metadata();
updateRequest.Metadata.Entities = new System.Collections.ObjectModel.Collection<Entity> { };
Entity anEntity = new Entity();
// Set model id, entity id, and the new entity name.
anEntity.Identifier = new ModelContextIdentifier { Id = entityId, Name = newEntityName, ModelId = new Identifier { Id = modelId } };
updateRequest.Metadata.Entities.Add(anEntity);
// Update the entity information.
MetadataUpdateResponse updateResponse = clientProxy.MetadataUpdate(updateRequest);
HandleOperationErrors(updateResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
// Delete the entity with the specified entity id.
private static void DeleteEntity(Guid entityId)
{
try
{
// Create the request object for entity deletion.
MetadataDeleteRequest deleteRequest = new MetadataDeleteRequest();
deleteRequest.Metadata = new Metadata();
deleteRequest.Metadata.Entities = new System.Collections.ObjectModel.Collection<Entity> { };
Entity anEntity = new Entity();
anEntity.Identifier = new ModelContextIdentifier { Id = entityId };
deleteRequest.Metadata.Entities.Add(anEntity);
// Delete the specified entity
MetadataDeleteResponse deleteResponse = clientProxy.MetadataDelete(deleteRequest);
HandleOperationErrors(deleteResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
// Create an attribute with a specified name.
private static void CreateAttribute(Guid modelId, Guid entityId, string attributeName)
{
try
{
// Create the request object for attribute creation.
MetadataCreateRequest createRequest = new MetadataCreateRequest();
createRequest.Metadata = new Metadata();
createRequest.Metadata.Attributes = new System.Collections.ObjectModel.Collection<MetadataAttribute> { };
MetadataAttribute newAttribute = new MetadataAttribute();
// Set model id, entity id, and attribute name.
newAttribute.Identifier = new MemberTypeContextIdentifier { Name = attributeName, ModelId = new Identifier { Id = modelId }, EntityId = new Identifier { Id = entityId }, MemberType = MemberType.Leaf };
newAttribute.AttributeType = AttributeType.FreeForm;
newAttribute.DataType = AttributeDataType.Text;
// When the DataType is "Text", set the length (100) to DataTypeInformation.
newAttribute.DataTypeInformation = 100;
newAttribute.DisplayWidth = 100;
createRequest.Metadata.Attributes.Add(newAttribute);
// Create a new attribute
MetadataCreateResponse createResponse = clientProxy.MetadataCreate(createRequest);
HandleOperationErrors(createResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
// Get an attribute information (ModelContextIdentifier for the attribute) with specified attribute name, model id, and entity id.
private static ModelContextIdentifier GetAttribute(Guid modelId, Guid entityId, string attributeName)
{
ModelContextIdentifier AttributeIdentifier = new ModelContextIdentifier();
try
{
// Create the request object for getting attribute information.
MetadataGetRequest getRequest = new MetadataGetRequest();
getRequest.SearchCriteria = new MetadataSearchCriteria();
getRequest.SearchCriteria.SearchOption = SearchOption.UserDefinedObjectsOnly;
// Set model id, entity id, and attribute name.
getRequest.SearchCriteria.Attributes = new System.Collections.ObjectModel.Collection<Identifier> { new Identifier { Name = attributeName } };
getRequest.SearchCriteria.Entities = new System.Collections.ObjectModel.Collection<Identifier> { new Identifier { Id = entityId } };
getRequest.SearchCriteria.Models = new System.Collections.ObjectModel.Collection<Identifier> { new Identifier { Id = modelId } };
getRequest.ResultOptions = new MetadataResultOptions();
getRequest.ResultOptions.Attributes = ResultType.Details;
// Get an attribute information.
MetadataGetResponse getResponse = clientProxy.MetadataGet(getRequest);
if (getResponse.Metadata.Attributes.Count > 0)
{
AttributeIdentifier = getResponse.Metadata.Attributes[0].Identifier;
}
HandleOperationErrors(getResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
return AttributeIdentifier;
}
// Update the attribute name.
private static void UpdateAttribute(Guid modelId, Guid entityId, Guid attributeId, string newAttributeName)
{
try
{
// Create the request object for updating attribute information.
MetadataUpdateRequest updateRequest = new MetadataUpdateRequest();
updateRequest.Metadata = new Metadata();
updateRequest.Metadata.Attributes = new System.Collections.ObjectModel.Collection<MetadataAttribute> { };
// Set model id, entity id, attribute id, and new attribute name.
MetadataAttribute anAttribute = new MetadataAttribute { Identifier = new MemberTypeContextIdentifier { Name = newAttributeName, Id = attributeId, ModelId = new Identifier { Id = modelId }, EntityId = new Identifier { Id = entityId }, MemberType = MDSTestService.MemberType.Leaf } };
updateRequest.Metadata.Attributes.Add(anAttribute);
// Update the attribute information.
MetadataUpdateResponse updateResponse = clientProxy.MetadataUpdate(updateRequest);
HandleOperationErrors(updateResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
// Delete an attribute with the specified attribute id.
private static void DeleteAttribute(Guid attributeId)
{
try
{
// Create the request object for attribute deletion.
MetadataDeleteRequest deleteRequest = new MetadataDeleteRequest();
deleteRequest.Metadata = new Metadata();
deleteRequest.Metadata.Attributes = new System.Collections.ObjectModel.Collection<MetadataAttribute> { };
MetadataAttribute anAttribute = new MetadataAttribute();
// Set the attribute id.
anAttribute.Identifier = new MemberTypeContextIdentifier { Id = attributeId };
deleteRequest.Metadata.Attributes.Add(anAttribute);
// Delete a specified attribute
MetadataDeleteResponse deleteResponse = clientProxy.MetadataDelete(deleteRequest);
HandleOperationErrors(deleteResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
// Create an attribute group with a specified name.
private static void CreateAttributeGroup(Guid modelId, Guid entityId, string attributeGroupName)
{
try
{
// Create the request object for attribute group creation.
MetadataCreateRequest createRequest = new MetadataCreateRequest();
createRequest.Metadata = new Metadata();
createRequest.Metadata.AttributeGroups = new System.Collections.ObjectModel.Collection<AttributeGroup> { };
AttributeGroup newAttributeGroup = new AttributeGroup();
// Set model id, entity id, and attribute group name.
newAttributeGroup.Identifier = new MemberTypeContextIdentifier { Name = attributeGroupName, ModelId = new Identifier { Id = modelId }, EntityId = new Identifier { Id = entityId }, MemberType = MemberType.Leaf };
newAttributeGroup.FullName = attributeGroupName;
createRequest.Metadata.AttributeGroups.Add(newAttributeGroup);
// Create a new attribute group.
MetadataCreateResponse createResponse = clientProxy.MetadataCreate(createRequest);
HandleOperationErrors(createResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
// Get an attribute group information (ModelContextIdentifier for the attribute group) with specified attribute group name, model id, and entity id.
private static ModelContextIdentifier GetAttributeGroup(Guid modelId, Guid entityId, string attributeGroupName)
{
ModelContextIdentifier AttributeGroupIdentifier = new ModelContextIdentifier();
try
{
// Create the request object for getting attribute group information.
MetadataGetRequest getRequest = new MetadataGetRequest();
getRequest.SearchCriteria = new MetadataSearchCriteria();
getRequest.SearchCriteria.SearchOption = SearchOption.UserDefinedObjectsOnly;
// Set model id, entity id, and attribute group name.
getRequest.SearchCriteria.Models = new System.Collections.ObjectModel.Collection<Identifier> { new Identifier { Id = modelId } };
getRequest.SearchCriteria.Entities = new System.Collections.ObjectModel.Collection<Identifier> { new Identifier { Id = entityId } };
getRequest.SearchCriteria.AttributeGroups = new System.Collections.ObjectModel.Collection<Identifier> { new Identifier { Name = attributeGroupName } };
getRequest.ResultOptions = new MetadataResultOptions();
getRequest.ResultOptions.AttributeGroups = ResultType.Details;
// Get an attribute group information.
MetadataGetResponse getResponse = clientProxy.MetadataGet(getRequest);
if (getResponse.Metadata.AttributeGroups.Count > 0)
{
AttributeGroupIdentifier = getResponse.Metadata.AttributeGroups[0].Identifier;
}
HandleOperationErrors(getResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
return AttributeGroupIdentifier;
}
// Update the attribute group name and add an attribute to it.
private static void UpdateAttributeGroup(Guid modelId, Guid entityId, Guid attributeGroupId, string newAttributeGroupName, Guid attributeId)
{
try
{
// Create the request object for updating attribute group information.
MetadataUpdateRequest updateRequest = new MetadataUpdateRequest();
updateRequest.Metadata = new Metadata();
updateRequest.Metadata.AttributeGroups = new System.Collections.ObjectModel.Collection<AttributeGroup> { };
// Set model id, entity id, attribute group id, and new attribute group name.
AttributeGroup anAttributeGroup = new AttributeGroup { Identifier = new MemberTypeContextIdentifier { Name = newAttributeGroupName, Id = attributeGroupId, ModelId = new Identifier { Id = modelId }, EntityId = new Identifier { Id = entityId }, MemberType = MDSTestService.MemberType.Leaf } };
// Add the attribute object with the attribute id.
anAttributeGroup.Attributes = new System.Collections.ObjectModel.Collection<MetadataAttribute> { };
MetadataAttribute anAttribute = new MetadataAttribute { Identifier = new MemberTypeContextIdentifier { Id = attributeId } };
anAttributeGroup.Attributes.Add(anAttribute);
updateRequest.Metadata.AttributeGroups.Add(anAttributeGroup);
// Update the attribute group information.
MetadataUpdateResponse updateResponse = clientProxy.MetadataUpdate(updateRequest);
HandleOperationErrors(updateResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
// Delete the attribute group with the specified attribute group id.
private static void DeleteAttributeGroup(Guid attributeGroupId)
{
try
{
// Create the request object for attribute group deletion.
MetadataDeleteRequest deleteRequest = new MetadataDeleteRequest();
deleteRequest.Metadata = new Metadata();
deleteRequest.Metadata.AttributeGroups = new System.Collections.ObjectModel.Collection<AttributeGroup> { };
AttributeGroup anAttributeGroup = new AttributeGroup();
// Set attribute group id.
anAttributeGroup.Identifier = new MemberTypeContextIdentifier { Id = attributeGroupId };
deleteRequest.Metadata.AttributeGroups.Add(anAttributeGroup);
// Delete the specified attribute group.
MetadataDeleteResponse deleteResponse = clientProxy.MetadataDelete(deleteRequest);
HandleOperationErrors(deleteResponse.OperationResult);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
}
}
@@ -0,0 +1,46 @@
//==============================================================================
//
// © Microsoft corp. All rights reserved.
// This code is licensed under the Microsoft Public License.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//==============================================================================
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Metadata")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("Metadata")]
[assembly: AssemblyCopyright("Copyright © Microsoft")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("bdeeb7de-62b9-49f4-bf69-787d90cbe7d2")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,42 @@
# Master Data Services Metadata API Sample
This is a C# code sample to show how to use MDS APIs to create, read, update, and delete Metadata.
The sample code includes the following scenarios.
1. Create, get information of, update, and delete a Model using MDS API.
2. Create, get information of, update, and delete an Entity using MDS API.
3. Create, get information of, update, and delete an Attribute using MDS API.
4. Create, get information of, update, and delete an Attribute Group using MDS API.
Please set the MDS URL (plus /Service/Service.svc) to mdsURL in Program.cs.
```C#
string mdsURL = @"http://localhost/MDS/Service/Service.svc";
```
Program.cs uses Reference.cs (the service reference class file) that was generated by using Visual Studio to access MDS Web service API. You may need to regenerate Reference.cs in the case when MDS Web service API is changed.
To generate Reference.cs using Visual Studio:
You need to expose the WSDL. Exposing the WSDL is only necessary at the time when you want to generate proxy classes using a client development tool such as Visual Studio. After a proxy has been generated, the WSDL does not need to be exposed going forward for client programs to call the API.
To enable an http/https Get on the WSDL:
1. Open the MDS web.config file in a text editor (<Program Files>\Microsoft SQL Server\Master Data Services\WebApplication\web.config).
2. Search for the tag serviceMetadata and set httpGetEnabled to true (or httpsGetEnabled if using SSL).
To also enable service exception details for additional debugging (not necessary for standard, trapped errors):
1. Search for the tag serviceDebug and set includeExceptionDetailInFaults to true.
After that you need to add a Service Reference to http://ServerName/MdsSiteName/service/service.svc and set the namespace to the service to "MDSTestService" in the following steps using Visual Studio.
1. Click "Add Service Reference".
2. In Address, enter the URL to the MDS service which will be “http://ServerName/MdsSiteName/service/service.svc”.
3. Specify the namespace to the service as "MDSTestService" in the Namespace box.
4. Click the Advanced button to configure advanced settings.
5. Check Always generate message contracts.
6. Set the Collection type drop-down to System.Collections.ObjectModel.Collection.
7. Click OK to return to the Add Service Reference dialog.
8. Click OK.
Reference.cs will be generated in Metadata\Service References\MDSTestService folder. You can replace Metadata\Reference.cs with the newly generated one.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{E911D29A-5406-4224-86D1-040793262668}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ModelDUtil</RootNamespace>
<AssemblyName>ModelDUtil</AssemblyName>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<IsWebBootstrapper>false</IsWebBootstrapper>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation />
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.MasterDataServices.Deployment">
<HintPath>.\Microsoft.MasterDataServices.Deployment.dll</HintPath>
</Reference>
<Reference Include="Microsoft.MasterDataServices.Services.Contracts">
<SpecificVersion>False</SpecificVersion>
<HintPath>.\Microsoft.MasterDataServices.Services.Contracts.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Modes.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="ModelDUtil.exe.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
@@ -0,0 +1,5 @@
<configuration>
<connectionStrings>
<add name="defaultMdsConnection" connectionString="Data Source=(local);Initial Catalog=MDM_Sample;Integrated Security=True;Connect Timeout=3600"/>
</connectionStrings>
</configuration>
@@ -0,0 +1,22 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.40629.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModelDUtil", "ModelDUtil.csproj", "{E911D29A-5406-4224-86D1-040793262668}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E911D29A-5406-4224-86D1-040793262668}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E911D29A-5406-4224-86D1-040793262668}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E911D29A-5406-4224-86D1-040793262668}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E911D29A-5406-4224-86D1-040793262668}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,60 @@
//==============================================================================
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the Microsoft Public License.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//==============================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ModelDUtil
{
/// <summary>
/// The various "modes" of the utility console app. The app will run in
/// exactly one of these modes each execution.
/// </summary>
public enum Modes
{
/// <summary>
/// Used to export a model to a package file.
/// </summary>
CreatePackage,
/// <summary>
/// Used to deploy a clone of a model in a package.
/// </summary>
DeployClone,
/// <summary>
/// Used to deploy a copy of a model in a package, under a new name.
/// </summary>
DeployNew,
/// <summary>
/// Used to update an existing model from a package.
/// </summary>
DeployUpdate,
/// <summary>
/// Used to list all the models in the system.
/// </summary>
ListModels,
/// <summary>
/// Used to list all the versions for a selected model.
/// </summary>
ListVersions,
/// <summary>
/// Used to display the usage instructions.
/// </summary>
Help
}
}
@@ -0,0 +1,448 @@
//==============================================================================
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the Microsoft Public License.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//==============================================================================
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using Microsoft.MasterDataServices.Deployment;
using Microsoft.MasterDataServices.Services.DataContracts;
namespace ModelDUtil
{
/// <summary>
/// Sample Model Deployment utility.
/// </summary>
class ModelDUtil
{
#region Console app methods
/// <summary>
/// Entry point for the console app.
/// </summary>
/// <param name="args">Array of command line arguments</param>
static void Main(string[] args)
{
/// <summary>
/// Used for input or output package file name parameters.
/// </summary>
string packageFile = string.Empty;
/// <summary>
/// Used for model name parameter.
/// </summary>
string modelName = string.Empty;
/// <summary>
/// Used for version name parameter.
/// </summary>
string versionName = string.Empty;
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
try
{
// Parse the command line options.
Modes mode = ModelDUtil.ParseCommandLine(args, out packageFile, out modelName, out versionName);
switch (mode)
{
case Modes.CreatePackage:
ModelDUtil.CreatePackage(packageFile, modelName, versionName);
break;
case Modes.DeployClone:
ModelDUtil.DeployClone(packageFile);
break;
case Modes.DeployNew:
ModelDUtil.DeployNew(packageFile, modelName);
break;
case Modes.DeployUpdate:
ModelDUtil.DeployUpdate(packageFile, versionName);
break;
case Modes.ListModels:
ModelDUtil.ListModels();
break;
case Modes.ListVersions:
ModelDUtil.ListVersions(modelName);
break;
default:
ModelDUtil.DisplayHelp();
break;
}
stopwatch.Stop();
Console.WriteLine(string.Empty);
Console.WriteLine("Operation completed successfully. Elapsed time: {0}", stopwatch.Elapsed.ToString("c", CultureInfo.CurrentCulture));
}
catch (Exception e)
{
stopwatch.Stop();
Console.WriteLine(string.Empty);
Console.WriteLine("Operation aborted. Elapsed time: {0}", stopwatch.Elapsed.ToString("c", CultureInfo.CurrentCulture));
Console.WriteLine("Exception: ");
Console.WriteLine(e);
}
Console.WriteLine(string.Empty);
Console.WriteLine("Press Enter to continue...");
Console.ReadLine();
}
/// <summary>
/// Parse string args provided on the command line.
/// </summary>
/// <param name="args">Array of string arguments.</param>
/// <returns>True if command line arguments were successfully parsed, false otherwise.</returns>
private static Modes ParseCommandLine(string[] args, out string packageFile, out string modelName, out string versionName)
{
packageFile = string.Empty;
modelName = string.Empty;
versionName = string.Empty;
// The first argument must be a switch specifying the mode
Modes mode = Modes.Help;
int countArgs = args.Length;
if (countArgs > 0)
{
try
{
mode = (Modes)Enum.Parse(typeof(Modes), args[0], true);
}
catch (ArgumentException)
{
// Invalid mode argument. Display help.
return Modes.Help;
}
// Now check for additional parameters, as appropriate for the given mode.
switch (mode)
{
case Modes.CreatePackage:
// Package name, Model name, and Version name expected.
if (countArgs != 4)
{
return Modes.Help;
}
packageFile = args[1];
modelName = args[2];
versionName = args[3];
break;
case Modes.DeployClone:
// Package file name expected.
if (countArgs != 2)
{
return Modes.Help;
}
packageFile = args[1];
break;
case Modes.DeployNew:
// Package name and Model name expected.
if (countArgs != 3)
{
return Modes.Help;
}
packageFile = args[1];
modelName = args[2];
break;
case Modes.DeployUpdate:
// Package name and Version name expected.
if (countArgs != 3)
{
return Modes.Help;
}
packageFile = args[1];
versionName = args[2];
break;
case Modes.ListModels:
// No additional params expected.
if (countArgs != 1)
{
return Modes.Help;
}
break;
case Modes.ListVersions:
// Model name expected.
if (countArgs != 2)
{
return Modes.Help;
}
modelName = args[1];
break;
case Modes.Help:
// No additional params expected.
if (countArgs != 1)
{
return Modes.Help;
}
break;
default:
// Unknown enum value.
return Modes.Help;
}
}
return mode;
}
/// <summary>
/// Displays help on how to use this console app.
/// </summary>
private static void DisplayHelp()
{
Console.WriteLine("Usage:");
Console.WriteLine(" ModelDUtil <mode> [params]");
Console.WriteLine(string.Empty);
Console.WriteLine("where <mode> is one of the following:");
Console.WriteLine(string.Empty);
Console.WriteLine("ListModels -- returns a list of all the user models in the target system");
Console.WriteLine(" ModelDUtil ListModels");
Console.WriteLine(string.Empty);
Console.WriteLine("ListVersions -- returns a list of the versions for a given model");
Console.WriteLine(" ModelDUtil ListVersions <model name>");
Console.WriteLine(string.Empty);
Console.WriteLine("CreatePackage -- create a package file for a given model, including a specific version of master data");
Console.WriteLine(" ModelDUtil CreatePackage <output package file name> <model name> <version name>");
Console.WriteLine(string.Empty);
Console.WriteLine("DeployClone -- deploys a clone of a model from a given package");
Console.WriteLine(" ModelDUtil DeployClone <input package file name>");
Console.WriteLine(string.Empty);
Console.WriteLine("DeployNew -- deploys a model from a given package with the new given name");
Console.WriteLine(" ModelDUtil DeployNew <input package file name> <new model name>");
Console.WriteLine(string.Empty);
Console.WriteLine("DeployUpdate -- deploys an update to a given version of a model from a given package");
Console.WriteLine(" ModelDUtil DeployUpdate <input package file name> <version name to update>");
Console.WriteLine(string.Empty);
Console.WriteLine("Help -- displays this help");
Console.WriteLine(" ModelDUtil Help");
Console.WriteLine(string.Empty);
Console.WriteLine(string.Empty);
Console.WriteLine("Note: names that contain spaces should be wrapped with double quotation marks. For Example:");
Console.WriteLine(" ModelDUtil DeployUpdate mypackage.pkg \"Version 1\"");
}
#endregion Console app methods
#region Model Deployment Sample methods
/// <summary>
/// Creates a model deployment package file for a specified model.
/// </summary>
/// <param name="packageFile">File name for the output package.</param>
/// <param name="modelName">Name of the model to export to package.</param>
/// <param name="versionName">Name of the version of master data to include in the package.</param>
private static void CreatePackage(string packageFile, string modelName, string versionName)
{
Console.WriteLine("Creating a package for model {0}", modelName);
ModelReader reader = new ModelReader();
// Set the model ID on the reader to the passed-in model name.
Identifier modelId = new Identifier();
modelId.Name = modelName;
reader.ModelId = modelId;
// Set the version ID on the reader to the passed-in version name.
Identifier versionId = new Identifier();
versionId.Name = versionName;
reader.VersionId = versionId;
// Create a package that contains metadata, business rules, and master data.
List<Package> packages = reader.CreatePackage(true).ToList();
// Save the package
Console.WriteLine("Saving package to file {0}", packageFile);
using (var stream = new FileStream(packageFile, FileMode.CreateNew))
{
var firstPackage = packages.FirstOrDefault();
if (firstPackage != null)
firstPackage.Serialize(stream);
}
}
/// <summary>
/// Deploys a clone of a model from a specified package.
/// </summary>
/// <param name="packageFile">File name of the input package.</param>
private static void DeployClone(string packageFile)
{
Console.WriteLine("Deploying clone of package {0}", packageFile);
ModelDeployer deployer = new ModelDeployer();
// Deploy the package.
Warnings errorsAsWarnings = null;
using (var package = new PackageReader(packageFile))
{
Identifier newModelId = null;
errorsAsWarnings = deployer.DeployClone(package.GetEnumerator(), out newModelId);
}
Console.WriteLine("Package was deployed with {0} warnings", errorsAsWarnings.Count);
}
/// <summary>
/// Deploys a copy of a model from a package, with a new name.
/// </summary>
/// <param name="packageFile">File name of the input package.</param>
/// <param name="modelName">New name for the model being deployed.</param>
private static void DeployNew(string packageFile, string modelName)
{
Console.WriteLine("Deploying package {0} using new model name {1}", packageFile, modelName);
ModelDeployer deployer = new ModelDeployer();
// Deploy the package.
Warnings errorsAsWarnings = null;
using (var package = new PackageReader(packageFile))
{
Identifier newId = null;
errorsAsWarnings = deployer.DeployNew(package.GetEnumerator(), modelName, out newId);
}
Console.WriteLine("Package was deployed with {0} warnings", errorsAsWarnings.Count);
}
/// <summary>
/// Deploys an update to an existing model from a specified package.
/// </summary>
/// <param name="packageFile">File name of the input package.</param>
/// <param name="versionName">Name of the version of master data to update.</param>
private static void DeployUpdate(string packageFile, string versionName)
{
Console.WriteLine("Deploying package {0}, updating version {1} of the master data", packageFile, versionName);
ModelDeployer deployer = new ModelDeployer();
ModelReader reader = new ModelReader();
// Deploy it.
Warnings errorsAsWarnings = null;
using (var package = new PackageReader(packageFile))
{
// Get the ID for the model named in the package
var firstPackage = package.FirstOrDefault();
if (firstPackage != null)
{
Identifier modelId = GetModelIdentifier(reader, firstPackage.ModelId.Name);
// Now get the version Id for that model and the given version name.
reader.ModelId = modelId;
}
Identifier versionId = GetVersionIdentifier(reader, versionName);
errorsAsWarnings = deployer.DeployUpdate(package.GetEnumerator(), true, versionId);
}
Console.WriteLine("Package was deployed with {0} warnings", errorsAsWarnings.Count);
}
/// <summary>
/// Displays a list of the models in the system.
/// </summary>
private static void ListModels()
{
Console.WriteLine("Models:");
ModelReader reader = new ModelReader();
Collection<Identifier> models = reader.GetModels();
foreach (Identifier modelId in models)
{
Console.WriteLine(modelId.Name);
}
}
/// <summary>
/// Displays a list of the versions for a given model in the system.
/// </summary>
/// <param name="modelName">Name of model for which to list versions.</param>
private static void ListVersions(string modelName)
{
Console.WriteLine("Versions for model {0}:", modelName);
ModelReader reader = new ModelReader();
// Set the model ID on the reader to the passed-in model name.
Identifier modelId = new Identifier();
modelId.Name = modelName;
reader.ModelId = modelId;
// Get the versions (all status types) for the specified model.
Collection<Identifier> versions = reader.GetVersions(VersionStatusFlags.All);
foreach (Identifier versionId in versions)
{
Console.WriteLine(versionId.Name);
}
}
#endregion Model Deployment Sample methods
#region Reader helpers
/// <summary>
/// Get the Identifier object for the model with the given name.
/// </summary>
/// <param name="reader">The <see cref="ModelReader"/> to use to retrieve the model information.</param>
/// <param name="modelName">Name of model to look for</param>
/// <returns>The identifier if it exists, otherwise an empty Identifier</returns>
public static Identifier GetModelIdentifier(ModelReader reader, string modelName)
{
Identifier modelId = new Identifier();
Collection<Identifier> modelIdentifiers;
modelIdentifiers = reader.GetModels();
foreach (Identifier id in modelIdentifiers)
{
if (id.Name.Equals(modelName))
{
modelId = id;
break;
}
}
return modelId;
}
/// <summary>
/// Get the Identifier object for the version with the given name.
/// NOTE: ModelId property must be set on the reader first
/// </summary>
/// <param name="reader">The model reader object to use for the request.</param>
/// <param name="versionName">Name of version to look for,</param>
/// <returns>The identifier if it exists, otherwise an empty Identifier</returns>
public static Identifier GetVersionIdentifier(ModelReader reader, string versionName)
{
Identifier versionId = new Identifier();
Collection<Identifier> versionIdentifiers;
versionIdentifiers = reader.GetVersions(VersionStatusFlags.All);
foreach (Identifier id in versionIdentifiers)
{
if (id.Name.Equals(versionName, StringComparison.OrdinalIgnoreCase))
{
versionId = id;
break;
}
}
return versionId;
}
#endregion Reader helpers
}
}
@@ -0,0 +1,29 @@
//==============================================================================
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the Microsoft Public License.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//==============================================================================
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Resources;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ModelDUtil")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguageAttribute("en-US")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@@ -0,0 +1,59 @@
# Master Data Services Security Model Deployment API Sample
This is a simple console application that demonstrates usage of a few of the common methods in the Model Deployment API.
Building the Visual Studio 2013 Solution
This sample has the following external dependencies:
Microsoft.MasterDataServices.Deployment.dll
Microsoft.MasterDataServices.Services.contracts.dll
In order to build the solution, adjust the project references to point to these binaries in your Microsoft SQL Server Master Data Services deployment.
Configuring the sample project
Update the ConnectionString in ModelDUtil.config to point to your deployed database. Do not to change the name of the connection -- that should be left as "defaultMdsConnection".
ModelDUtil.config must be co-located with ModelDUtil.exe.
Using the sample executable
The following is the built-in help output, which describes the capabilities:
Usage:
ModelDUtil [mode] [params]
where [mode] is one of the following:
ListModels -- returns a list of all the user models in the target system
ModelDUtil ListModels
ListVersions -- returns a list of the versions for a given model
ModelDUtil ListVersions [model name]
CreatePackage -- create a package file for a given model
ModelDUtil CreatePackage [output package file name] [model name] [version name]
DeployClone -- deploys a clone of a model from a given package
ModelDUtil DeployClone [input package file name]
DeployNew -- deploys a model from a given package with the new given name
ModelDUtil DeployNew [input package file name] [new model name]
DeployUpdate -- deploys an update to a given version of a model from a given package
ModelDUtil DeployUpdate [input package file name] [version name to update]
Help -- displays this help
ModelDUtil Help
Note: names that contain spaces should be wrapped with double quotation marks. For Example: ModelDUtil DeployUpdate mypackage.pkg "Version 1"
+6 -3
View File
@@ -1,7 +1,10 @@
# Master Data Services
Master Data Services (MDS) is the SQL Server solution for master data management. Master data management (MDM) enables you organization to discover and define non-transactional lists of data, and compile maintainable, reliable master lists. This article briefly describe the MDS components and provides links to additional information.
Master Data Services (MDS) is the SQL Server solution for master data management. Master data management (MDM) enables you organization to discover and define non-transactional lists of data, and compile maintainable, reliable master lists.
For information about the new features in SQL Server 2016, see [What's New in Master Data Services (MDS)] (https://msdn.microsoft.com/en-us/library/ff929136.aspx).
Master Data Services (MDS) samples are C# console application samples that demonstrate how to customize the way that you and your users interact with Master Data Services.
For information about the new features in SQL Server 2016, see [What's New in Master Data Services (MDS)](https://msdn.microsoft.com/en-us/library/ff929136.aspx).
For more information about the MDS API, see [Master Data Services Developer Documentation](https://msdn.microsoft.com/en-us/library/hh230994.aspx).
This folder is a placeholder. For now, refer to [http://sqlserversamples.codeplex.com/wikipage?title=SQL%20Server%202012%20Master%20Data%20Services%20](http://sqlserversamples.codeplex.com/wikipage?title=SQL%20Server%202012%20Master%20Data%20Services%20).
@@ -0,0 +1,305 @@
//==============================================================================
//
// © Microsoft corp. All rights reserved.
// This code is licensed under the Microsoft Public License.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//==============================================================================
using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using Security.MDSTestService; // For the created service reference.
namespace Security
{
class Program
{
// MDS service client proxy object.
private static ServiceClient clientProxy;
// MDS URL.
private static string mdsURL = @"http://{0}/{1}/Service/Service.svc";
static void Main(string[] args)
{
try
{
if (args.Length < 4 || args.Length > 5)
{
Console.WriteLine("Usage: SecuritySample mode mds_host_name mds_application_name file_name [ExcludeMetadata]");
Console.WriteLine(string.Empty);
Console.WriteLine("mode: Indicates whether the code exports or imports the security information.");
Console.WriteLine(" \"mode\" value is Export or Import.");
Console.WriteLine(string.Empty);
Console.WriteLine("mds_host_name: The host name of the MDS web site.");
Console.WriteLine(string.Empty);
Console.WriteLine("mds_application_name: The MDS Application name.");
Console.WriteLine(string.Empty);
Console.WriteLine("file_name: The name of the file that stores the security information for users and groups.");
Console.WriteLine(string.Empty);
Console.WriteLine("ExcludeMetadata (optional): Indicates if Metadata Model Permissions are excluded or not.");
Console.WriteLine(" When \"ExcludeMetadata\" is specified Metadata Model Permissions are excluded.");
Console.WriteLine(string.Empty);
return;
}
string mode = args[0];
string hostName = args[1];
string applicationName = args[2];
string fileName = args[3];
mdsURL = string.Format(mdsURL, hostName, applicationName);
// Creates a service proxy.
clientProxy = GetClientProxy(mdsURL);
// Check if Exclude Metadata Model Permissions flag is set.
// When Metadata Model's GUID in the target MDS application is different from the one in the source MDS application, the import of the security information fails.
// To avoid this issue the user can exclude Metadata Model Permissions.
// The user can use Model Deployment to create other models with the same GUIDs as the source MDS application.
bool excludeMetadataPermission = false;
if (args.Length == 5)
{
if (string.Equals(args[4], "ExcludeMetadata", StringComparison.OrdinalIgnoreCase))
{
excludeMetadataPermission = true;
}
}
if (string.Equals(mode, "Export", StringComparison.OrdinalIgnoreCase))
{
// Gets the security information and exports it into the files.
ExportSecurityInformation(excludeMetadataPermission, fileName);
}
else if (string.Equals(mode, "Import", StringComparison.OrdinalIgnoreCase))
{
// Imports the security information from the files.
ImportSecurityInformation(excludeMetadataPermission, fileName);
}
}
catch (Exception ex)
{
Console.WriteLine("Error {0}", ex);
}
}
// Creates MDS service client proxy.
private static ServiceClient GetClientProxy(string targetURL)
{
// Creates an endpoint address using the URL.
System.ServiceModel.EndpointAddress endptAddress = new System.ServiceModel.EndpointAddress(targetURL);
// Creates and configures the WS Http binding.
System.ServiceModel.WSHttpBinding wsBinding = new System.ServiceModel.WSHttpBinding();
// Creates and returns the client proxy.
return new ServiceClient(wsBinding, endptAddress);
}
// Handles operation errors.
private static void HandleOperationErrors(MDSTestService.OperationResult result)
{
string errorMessage = string.Empty;
if (result.Errors.Count > 0)
{
foreach (MDSTestService.Error anError in result.Errors)
{
errorMessage += "Operation Error: " + anError.Code + ":" + anError.Description + "\n";
}
// Show the error messages.
Console.WriteLine(errorMessage);
}
}
// Gets security information and exports it into the files.
// excludeMetadataPermission indicates if model privileges for Metadata are exluded.
private static void ExportSecurityInformation(bool excludeMetadataPermission, string fileName)
{
// Gets security information.
SecurityPrincipalsGetRequest principalGetRequest = new SecurityPrincipalsGetRequest();
principalGetRequest.Criteria = new SecurityPrincipalsCriteria();
principalGetRequest.Criteria.All = true;
principalGetRequest.Criteria.Type = PrincipalType.UserAccount;
principalGetRequest.Criteria.ResultType = ResultType.Details;
principalGetRequest.Criteria.SecurityResolutionType = SecurityResolutionType.Users;
principalGetRequest.Criteria.ModelPrivilege = ResultType.Details;
principalGetRequest.Criteria.FunctionPrivilege = ResultType.Details;
principalGetRequest.Criteria.HierarchyMemberPrivilege = ResultType.Details;
// Gets the security principals for all the users.
SecurityPrincipalsGetResponse principalGetResponse = clientProxy.SecurityPrincipalsGet(principalGetRequest);
HandleOperationErrors(principalGetResponse.OperationResult);
System.Collections.ObjectModel.Collection<User> users = principalGetResponse.Principals.Users;
// Exclude model privileges for Metadata when excludeMetadataPermission is true.
if (excludeMetadataPermission)
{
foreach (User anUser in users)
{
System.Collections.ObjectModel.Collection<ModelPrivilege> tempModelPrivileges = new System.Collections.ObjectModel.Collection<ModelPrivilege>{};
// Exclude model privileges for Metadata (internal id = 1).
foreach (ModelPrivilege aPrivilege in anUser.SecurityPrivilege.ModelPrivileges)
{
if (aPrivilege.ModelId.InternalId != 1)
{
tempModelPrivileges.Add(aPrivilege);
}
}
anUser.SecurityPrivilege.ModelPrivileges = tempModelPrivileges;
}
}
principalGetRequest.Criteria.Type = PrincipalType.Group;
principalGetRequest.Criteria.SecurityResolutionType = SecurityResolutionType.UserAndGroup;
// Gets the security principals for all the groups.
SecurityPrincipalsGetResponse principalGetGroupResponse = clientProxy.SecurityPrincipalsGet(principalGetRequest);
HandleOperationErrors(principalGetGroupResponse.OperationResult);
System.Collections.ObjectModel.Collection<Group> groups = principalGetGroupResponse.Principals.Groups;
// Exclude model privileges for Metadata when excludeMetadataPermission is true.
if (excludeMetadataPermission)
{
foreach (Group aGroup in groups)
{
System.Collections.ObjectModel.Collection<ModelPrivilege> tempModelPrivileges = new System.Collections.ObjectModel.Collection<ModelPrivilege> { };
// Exclude model privileges for Metadata (internal id = 1).
foreach (ModelPrivilege aPrivilege in aGroup.SecurityPrivilege.ModelPrivileges)
{
if (aPrivilege.ModelId.InternalId != 1)
{
tempModelPrivileges.Add(aPrivilege);
}
}
aGroup.SecurityPrivilege.ModelPrivileges = tempModelPrivileges;
}
}
// Set users and groups objects to securityInformation.
SecurityInformation securityInformation = new SecurityInformation();
securityInformation.Users = users;
securityInformation.Groups = groups;
// Serialization.
XmlSerializer serializer = new XmlSerializer(typeof(SecurityInformation));
using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))
{
XmlDictionaryWriter xmlWriter = XmlDictionaryWriter.CreateBinaryWriter(fs);
// Serializes the security information.
serializer.Serialize(xmlWriter, securityInformation);
fs.Flush();
}
}
// Imports the security information from the files.
// excludeMetadataPermission indicates if model privileges for Metadata are exluded.
private static void ImportSecurityInformation(bool excludeMetadataPermission, string fileName)
{
// Deserialization.
System.Collections.ObjectModel.Collection<User> users;
System.Collections.ObjectModel.Collection<Group> groups;
SecurityInformation securityInformation = new SecurityInformation();
XmlSerializer serializer = new XmlSerializer(typeof(SecurityInformation));
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
XmlDictionaryReader xmlReader = XmlDictionaryReader.CreateBinaryReader(fs, XmlDictionaryReaderQuotas.Max);
// Derializes the security information.
securityInformation = (SecurityInformation)serializer.Deserialize(xmlReader);
}
// Gets users and groups objects from securityInformation.
users = securityInformation.Users;
groups = securityInformation.Groups;
// Exclude model privileges for Metadata when excludeMetadataPermission is true.
if (excludeMetadataPermission)
{
foreach (User anUser in users)
{
System.Collections.ObjectModel.Collection<ModelPrivilege> tempModelPrivileges = new System.Collections.ObjectModel.Collection<ModelPrivilege> { };
// Exclude model privileges for Metadata (internal id = 1).
foreach (ModelPrivilege aPrivilege in anUser.SecurityPrivilege.ModelPrivileges)
{
if (aPrivilege.ModelId.InternalId != 1)
{
tempModelPrivileges.Add(aPrivilege);
}
}
anUser.SecurityPrivilege.ModelPrivileges = tempModelPrivileges;
}
}
// Exclude model privileges for Metadata when excludeMetadataPermission is true.
if (excludeMetadataPermission)
{
foreach (Group aGroup in groups)
{
System.Collections.ObjectModel.Collection<ModelPrivilege> tempModelPrivileges = new System.Collections.ObjectModel.Collection<ModelPrivilege> { };
// Exclude model privileges for Metadata (internal id = 1).
foreach (ModelPrivilege aPrivilege in aGroup.SecurityPrivilege.ModelPrivileges)
{
if (aPrivilege.ModelId.InternalId != 1)
{
tempModelPrivileges.Add(aPrivilege);
}
}
aGroup.SecurityPrivilege.ModelPrivileges = tempModelPrivileges;
}
}
// Clones security principals for groups and users.
SecurityPrincipalsRequest principalRequest = new SecurityPrincipalsRequest();
principalRequest.Principals = new SecurityPrincipals();
principalRequest.Principals.Groups = new System.Collections.ObjectModel.Collection<Group> { };
principalRequest.Principals.Users = new System.Collections.ObjectModel.Collection<User> { };
// Sets group objects.
foreach (Group aGroup in groups)
{
principalRequest.Principals.Groups.Add(aGroup);
}
// Creates groups and their security principals.
// Create groups before users since some of the users may belong to one of the groups and reference the group object.
// Note that the security information assumes that GUIDs for objects such as Models are the same.
MessageResponse response = clientProxy.SecurityPrincipalsClone(principalRequest);
HandleOperationErrors(response.OperationResult);
principalRequest.Principals.Groups = new System.Collections.ObjectModel.Collection<Group> { };
principalRequest.Principals.Users = new System.Collections.ObjectModel.Collection<User> { };
// Sets user objects.
foreach (User aUser in users)
{
principalRequest.Principals.Users.Add(aUser);
}
// Creates users and their security principals.
response = clientProxy.SecurityPrincipalsClone(principalRequest);
HandleOperationErrors(response.OperationResult);
}
}
}
@@ -0,0 +1,46 @@
//==============================================================================
//
// © Microsoft corp. All rights reserved.
// This code is licensed under the Microsoft Public License.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//==============================================================================
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Security")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("Security")]
[assembly: AssemblyCopyright("Copyright © Microsoft")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("46523287-e46e-4b7e-a07a-e34cffbf89e4")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,53 @@
# Master Data Services Security API Sample
This is a C# sample code to show how to export security information into the specified file and import security information from the file by using MDS APIs.
Export security information method gets the security information (the security principals) from the specified MDS application and exports (serializes) it to the specified file (the file will be created in the folder where the sample application runs). Import security information method gets (deserializes) the user and group security principals from the file and clones them (creates them with the same GUIDs) in the target MDS application.
This sample code takes the following parameters.
1. Mode (the first parameter)
This parameter indicates whether the code exports or imports the security information.
Export: The code exports the security information.
Import: The code imports the security information.
2. MDS Host Name (the second parameter)
This parameter indicates the host name of the MDS web site. For example, if the MDS URL is http://mydomain.com/mds MDS Host Name is "mydomain.com".
If the mode is “Export” it is the host name from which the security information is exported. If the mode is “Import” it is the host name to which the security information is imported.
3. MDS Application Name (the third parameter)
This parameter indicates the MDS Application name. For example, if the MDS URL is http://mydomain.com/mds MDS Application Name is "mds".
4. File name (the fourth parameter)
The name of the file that stores the security information for users and groups.
5. Exclude Metadata Model Permissions (the fifth parameter)
This is an optional parameter that indicates if Metadata Model Permissions are excluded or not.
When "ExcludeMetadata" is specified here Metadata Model Permissions are excluded.
When Metadata Model's GUID in the target MDS application is different from the one in the source MDS application, the import of the security information fails. To avoid this issue the user can exclude Metadata Model Permissions.
The import of the security information creates users and user groups that were exported from the source MDS application data, so there should not be any user and user group in the target MDS application data that are the same as the source MDS application data. Before the security privileges on models and member hierarchies are imported, the target MDS application should have the same models and member hierarchies with the same GUIDs. Model Deployment can deploy models (other than Metadata) with the same GUIDs.
Program.cs uses Reference.cs (the service reference class file) that was generated by using Visual Studio to access MDS Web service API. You may need to regenerate Reference.cs in case when MDS Web service API is changed.
To generate Reference.cs using Visual Studio:
You need to expose the WSDL. Exposing the WSDL is only necessary at the time when you want to generate proxy classes using a client development tool such as Visual Studio. After a proxy has been generated, the WSDL does not need to be exposed going forward for client programs to call the API.
To enable an http/https Get on the WSDL:
1. Open the MDS web.config file in a text editor (<Program Files>\Microsoft SQL Server\Master Data Services\WebApplication\web.config).
2. Search for the tag serviceMetadata and set httpGetEnabled to true (or httpsGetEnabled if using SSL).
To also enable service exception details for additional debugging (not necessary for standard, trapped errors):
1. Search for the tag serviceDebug and set includeExceptionDetailInFaults to true.
After that you need to add a Service Reference to http://ServerName/MdsSiteName/service/service.svc and set the namespace to the service to "MDSTestService" in the following steps using Visual Studio.
1. Click "Add Service Reference".
2. In Address, enter the URL to the MDS service which will be “http://ServerName/MdsSiteName/service/service.svc”.
3. Specify the namespace to the service as "MDSTestService" in the Namespace box.
4. Click the Advanced button to configure advanced settings.
5. Check Always generate message contracts.
6. Set the Collection type drop-down to System.Collections.ObjectModel.Collection.
7. Click OK to return to the Add Service Reference dialog.
8. Click OK.
Reference.cs will be generated in Security\Service References\MDSTestService folder. You can replace Security\Reference.cs with the newly generated one.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{EE9E1B99-CA00-4810-8369-C8FF02468986}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Security</RootNamespace>
<AssemblyName>SecuritySample</AssemblyName>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Reference.cs" />
<Compile Include="SecurityInformation.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
@@ -0,0 +1,22 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.40629.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Security", "Security.csproj", "{EE9E1B99-CA00-4810-8369-C8FF02468986}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{EE9E1B99-CA00-4810-8369-C8FF02468986}.Debug|x86.ActiveCfg = Debug|x86
{EE9E1B99-CA00-4810-8369-C8FF02468986}.Debug|x86.Build.0 = Debug|x86
{EE9E1B99-CA00-4810-8369-C8FF02468986}.Release|x86.ActiveCfg = Release|x86
{EE9E1B99-CA00-4810-8369-C8FF02468986}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,45 @@
//==============================================================================
//
// © Microsoft corp. All rights reserved.
// This code is licensed under the Microsoft Public License.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//==============================================================================
using Security.MDSTestService; // For the created service reference.
namespace Security
{
// This is the class to store the security information
public class SecurityInformation
{
System.Collections.ObjectModel.Collection<User> users;
System.Collections.ObjectModel.Collection<Group> groups;
public System.Collections.ObjectModel.Collection<User> Users
{
get
{
return users;
}
set
{
users = value;
}
}
public System.Collections.ObjectModel.Collection<Group> Groups
{
get
{
return groups;
}
set
{
groups = value;
}
}
}
}
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{C51DC0C5-27A0-4210-8286-E16D639028C5}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Microsoft.MasterDataServices.SharePointWorkflow</RootNamespace>
<AssemblyName>Microsoft.MasterDataServices.SharePointWorkflow</AssemblyName>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.SharePoint">
<HintPath>..\..\..\..\..\Tools\WSSv4\Microsoft.SharePoint.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="SharePointWorkflowExtender.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\dev\WF\src\WorkflowTypeExtender\Microsoft.MasterDataServices.WorkflowTypeExtender.csproj">
<Project>{06BEA1FF-F3AC-444C-95AD-A49D91F22C15}</Project>
<Name>Microsoft.MasterDataServices.WorkflowTypeExtender</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.40629.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.MasterDataServices.SharePointWorkflow", "Microsoft.MasterDataServices.SharePointWorkflow.csproj", "{C51DC0C5-27A0-4210-8286-E16D639028C5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C51DC0C5-27A0-4210-8286-E16D639028C5}.Debug|x86.ActiveCfg = Debug|Any CPU
{C51DC0C5-27A0-4210-8286-E16D639028C5}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,47 @@
//==============================================================================
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the Microsoft Public License.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//==============================================================================
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SharePointWorkflow")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("SharePointWorkflow")]
[assembly: AssemblyCopyright("Copyright (c) Microsoft. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("98478310-d110-46d1-a04c-d86789963a04")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,12 @@
# Master Data Services Security API Sample
A sample class that demonstrates how to implement a workflow type extender for SharePoint workflows. Once built, the assembly that contains this class should be put in the same folder as the workflow listener (Microsoft.MasterDataServices.Workflow.exe), and the
listener's config file should be updated to reference this class, like this:
```XML
<code>
<setting name="WorkflowTypeExtenders" serializeAs="String">
<value>SPWF=Microsoft.MasterDataServices.SharePointWorkflow.SharePointWorkflowExtender, Microsoft.MasterDataServices.SharePointWorkflow, Version=1.0.0.0</value>
</setting>
</code>
```
@@ -0,0 +1,102 @@
//==============================================================================
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the Microsoft Public License.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//==============================================================================
using System;
using System.Collections.Generic;
using System.Xml;
using Microsoft.MasterDataServices.WorkflowTypeExtender;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;
namespace Microsoft.MasterDataServices.SharePointWorkflow
{
/// <summary>
/// A sample class that demonstrates how to implement a workflow type extender
/// for SharePoint workflows. Once built, the assembly that contains this class should be put in the
/// same folder as the workflow listener (Microsoft.MasterDataServices.Workflow.exe), and the
/// listener's config file should be updated to reference this class, like this:
/// <code>
/// <setting name="WorkflowTypeExtenders" serializeAs="String">
/// <value>SPWF=Microsoft.MasterDataServices.SharePointWorkflow.SharePointWorkflowExtender, Microsoft.MasterDataServices.SharePointWorkflow, Version=1.0.0.0</value>
/// </setting>
/// </code>
/// </summary>
public class SharePointWorkflowExtender : IWorkflowTypeExtender
{
#region Fields
/// <summary>
/// Workflow type name for SharePoint workflows.
/// </summary>
private const string WorkflowTypeSharePoint = "SPWF";
/// <summary>
/// A cache of SharePoint sites.
/// Key = serverUrl
/// Value = SharePoint site
/// </summary>
private Dictionary<string, SPSite> Sites = new Dictionary<string, SPSite>();
#endregion Fields
#region Constructor
/// <summary>
/// Constructor.
/// </summary>
public SharePointWorkflowExtender()
{
}
#endregion Constructor
#region IWorkflowTypeExtender Members
/// <summary>
/// Starts a workflow of the given type, if it is a SharePoint workflow.
/// </summary>
/// <param name="workflowType">The workflow type. The method does nothing if it is not a SharePoint workflow.</param>
/// <param name="dataElement">The data passed to the workflow.</param>
public void StartWorkflow(string workflowType, XmlElement dataElement)
{
// Ignore non-SharePoint workflows.
if (string.Equals(workflowType, SharePointWorkflowExtender.WorkflowTypeSharePoint, StringComparison.OrdinalIgnoreCase))
{
string serverUrl = dataElement["Server_URL"].InnerText;
string workflowName = dataElement["Action_ID"].InnerText;
// Look for the site in the cache.
SPSite site = null;
if (!this.Sites.TryGetValue(serverUrl, out site))
{
// Site not in cache, so add it.
site = new SPSite(serverUrl);
this.Sites[serverUrl] = site;
}
// Start the specified workflow.
SPWeb web = site.OpenWeb();
web.WorkflowAssociations.UpdateAssociationsToLatestVersion();
foreach (SPWorkflowAssociation association in web.WorkflowAssociations)
{
if (association.Name == workflowName && association.AllowManual)
{
site.WorkflowManager.StartWorkflow(null, association, dataElement.OuterXml, SPWorkflowRunOptions.Synchronous);
break;
}
}
}
}
#endregion
}
}