This commit is contained in:
Kranthi Kumar Medam 2019-01-11 15:49:12 +05:30
Родитель f7f385a847
Коммит 0f81231fd7
66 изменённых файлов: 5225 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="SourceCosmosDBSettings" type="System.Configuration.NameValueSectionHandler" />
<section name="TargetCosmosDBSettings" type="System.Configuration.NameValueSectionHandler" />
<section name="SampleCosmosDBSettings" type="System.Configuration.NameValueSectionHandler" />
</configSections>
<SourceCosmosDBSettings>
<add key="EndpointUrl" value="__EndPoint__" />
<add key="AccessKey" value="__Access__" />
<add key="DatabaseName" value="TestDB" />
<add key="CollectionName" value="TestSuperColl1" />
<add key="ReadDelaybetweenRequestsInMs" value="2000" />
</SourceCosmosDBSettings>
<TargetCosmosDBSettings>
<add key="EndpointUrl" value="__EndPoint__" />
<add key="AccessKey" value="__Access__" />
<add key="DatabaseName" value="TestDB" />
<add key="CollectionName" value="TestSuperColl1" />
<add key="OfferThroughputRUs" value="10000" />
</TargetCosmosDBSettings>
<SampleCosmosDBSettings>
<add key="EndpointUrl" value="__EndPoint__" />
<add key="AccessKey" value="__Access_" />
<add key="ConnString" value="__connString__" />
<add key="DatabaseName" value="TestDB" />
<add key="IsFixedCollection" value="true" />
<add key="CollectionName" value="Sanity1" />
<add key="OfferThroughputRUs" value="10000" />
</SampleCosmosDBSettings>
<appSettings>
<add key="CopyStoredProcedures" value="true" />
<add key="CopyUDFs" value="true" />
<add key="CopyTriggers" value="true" />
<add key="CopyDocuments" value="true" />
<add key="CopyIndexingPolicy" value="true" />
<add key="ReadBatchSize" value="3500" />
<add key="CopyPartitionKey" value="true" />
<add key="WriteBatchSize" value="9000" />
<add key="WriteBatchCount" value="10000" />
<add key="EnableTextLogging" value="true" />
<add key="PopTextFileOnEnd" value="true" />
<add key="SourceOfferThroughputRUs" value="10000" />
<add key="TargetMigrationOfferThroughputRUs" value="10000" />
<add key="TargetRestOfferThroughputRUs" value="1100" />
<add key="ClientSettingsProvider.ServiceUri" value="" />
<add key="ScrubbingRequired" value="true" />
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Azure.Documents.Client" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.22.0.0" newVersion="1.22.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

Просмотреть файл

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{1F09A007-9A2E-40D8-AD24-C469473152F4}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>CloneConsoleRun</RootNamespace>
<AssemblyName>CloneConsoleRun</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</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|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CosmosCloneCommon\CosmosCloneCommon.csproj">
<Project>{523e1cc4-0286-498c-b184-3413e10d61de}</Project>
<Name>CosmosCloneCommon</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

Просмотреть файл

@ -0,0 +1,88 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CosmosCloneCommon;
using CosmosCloneCommon.Migrator;
using CosmosCloneCommon.Model;
using CosmosCloneCommon.Sample;
using CosmosCloneCommon.Utility;
using logger = CosmosCloneCommon.Utility.CloneLogger;
using Newtonsoft.Json;
namespace CloneConsoleRun
{
class Program
{
//Use the console for test of common utils before integration with the UI
public static void Main(string[] args)
{
try
{
logger.LogInfo("Begin Clone Execution");
//Update the app.config settings in the console project to run the below directly
//var documentMigrator = new CosmosCloneCommon.Migrator.DocumentMigrator();
//documentMigrator.StartCopy().Wait();
//logger.LogInfo("Begin Code migration");
//var codeMigrator = new CosmosCloneCommon.Migrator.CodeMigrator();
//codeMigrator.StartCopy().Wait();
//var sampleMigrator = new CosmosCloneCommon.Sample.SampleDBCreator();
//sampleMigrator.Start().Wait();
//documentMigrator.StartCopy().Wait();
}
catch (Exception e)
{
//added ip address
logger.LogError(e);
Console.ReadKey();
}
finally
{
//logger.Close();
logger.LogInfo("Cosmos Collection cloning complete");
Console.ReadKey();
Console.ReadLine();
}
}
public static void TestCosmosScrubbing()
{
var tcs = new DataScrubMigrator();
// ScrubRule rule1 = new ScrubRule("c.id=\"a5e66b8b-a57c-4788-a194-58d3735a9854\"", "c.CompositeName", RuleType.Singlevalue, "Test overwritten Value xyz",1);
//ScrubRule rule2 = new ScrubRule("", "c.SuperKeys.KeyValue", RuleType.Shuffle, "",2);
//ScrubRule rule3 = new ScrubRule("", "c.EntityValue.Name", RuleType.Shuffle, "", 3);
//ScrubRule rule4 = new ScrubRule("", "c.EntityValue.Description", RuleType.Singlevalue, "OverWrite Filtered rule Description", 4);
//ScrubRule rule3 = new ScrubRule("c.id=\"1402e84d-e034-45f9-8064-3ab174119e4f\"", "c.EntityValue.Name", RuleType.Singlevalue,"Test overwritten EntityName", 3);
var scrubRules = new List<ScrubRule>();
//scrubRules.Add(rule2);
//scrubRules.Add(rule3);
//scrubRules.Add(rule4);
//ScrubRule rule5 = new ScrubRule("c.EntityType=\"External\"", "c.EmailAddress", RuleType.Singlevalue, "unknown@unknown.com", 4);
ScrubRule rule6 = new ScrubRule("c.id=\"51b6b28d-1c5f-4385-af4b-8dbb3dc45f65\"", "c.EmailAddress", RuleType.SingleValue, "unknown@unknown.com", 4);
//scrubRules.Add(rule6);
var documentMigrator = new CosmosCloneCommon.Migrator.DocumentMigrator();
documentMigrator.StartCopy(scrubRules).Wait();
//var result = tcs.StartScrub(scrubRules);
}
public static async Task TestCollections()
{
logger.LogInfo("TestConnections");
var dbhelper = new CosmosDBHelper();
var vResult = await dbhelper.TestSourceConnection();
var vResult2 = await dbhelper.TestTargetConnection();
}
}
}

Просмотреть файл

@ -0,0 +1,36 @@
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("CloneConsoleRun")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CloneConsoleRun")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[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("1f09a007-9a2e-40d8-ad24-c469473152f4")]
// 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,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net461" />
</packages>

Просмотреть файл

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="SourceCosmosDBSettings" type="System.Configuration.NameValueSectionHandler" />
<section name="TargetCosmosDBSettings" type="System.Configuration.NameValueSectionHandler" />
<section name="SampleCosmosDBSettings" type="System.Configuration.NameValueSectionHandler" />
</configSections>
<SourceCosmosDBSettings>
<add key="EndpointUrl" value="__url__" />
<add key="AccessKey" value="__key__" />
<add key="DatabaseName" value="TestDB" />
<add key="CollectionName" value="__Coll__" />
<add key="ReadDelaybetweenRequestsInMs" value="2000" />
</SourceCosmosDBSettings>
<TargetCosmosDBSettings>
<add key="EndpointUrl" value="__url__" />
<add key="AccessKey" value="__key__" />
<add key="DatabaseName" value="TestDB" />
<add key="CollectionName" value="__Coll__" />
<add key="OfferThroughputRUs" value="10000" />
</TargetCosmosDBSettings>
<SampleCosmosDBSettings>
<add key="EndpointUrl" value="__url__" />
<add key="AccessKey" value="__AccessKey__" />
<add key="ConnString" value="__connString__" />
<add key="DatabaseName" value="TestDB" />
<add key="IsFixedCollection" value="true" />
<add key="CollectionName" value="TestSuperColl1" />
<add key="OfferThroughputRUs" value="10000" />
</SampleCosmosDBSettings>
<appSettings>
<add key="CopyStoredProcedures" value="true" />
<add key="CopyUDFs" value="true" />
<add key="CopyTriggers" value="true" />
<add key="CopyDocuments" value="true" />
<add key="CopyIndexingPolicy" value="true" />
<add key="ReadBatchSize" value="3500" />
<add key="CopyPartitionKey" value="true" />
<add key="WriteBatchSize" value="9000" />
<add key="WriteBatchCount" value="10000" />
<add key="EnableTextLogging" value="true" />
<add key="PopTextFileOnEnd" value="true" />
<add key="SourceOfferThroughputRUs" value="10000" />
<add key="TargetMigrationOfferThroughputRUs" value="10000" />
<add key="TargetRestOfferThroughputRUs" value="1100" />
<add key="ClientSettingsProvider.ServiceUri" value="" />
<add key="ScrubbingRequired" value="true" />
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Azure.Documents.Client" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.web>
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
</providers>
</roleManager>
</system.web>
</configuration>

Просмотреть файл

@ -0,0 +1,9 @@
<Application x:Class="CosmicCloneUI.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CosmicCloneUI"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

Просмотреть файл

@ -0,0 +1,21 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace CosmicCloneUI
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

Просмотреть файл

@ -0,0 +1,51 @@
<Page x:Class="CosmicCloneUI.CloneOptionsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CosmicCloneUI"
mc:Ignorable="d"
d:DesignHeight="320" d:DesignWidth="800"
Title="CloneOptionsPage">
<Grid>
<StackPanel>
<Label Content="Select Options for Copying Collection" FontSize="15" />
<StackPanel Orientation="Horizontal" Margin="20,20,0,0">
<CheckBox x:Name="Documents" VerticalAlignment="Center" IsChecked="True"/>
<TextBlock Text="Documents" FontSize="15" VerticalAlignment="Center" Margin="10,0,0,0"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="20,20,0,0">
<CheckBox x:Name="SPs" VerticalAlignment="Center" IsChecked="True"/>
<TextBlock Text="Stored Procedures" FontSize="15" VerticalAlignment="Center" Margin="10,0,0,0"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="20,20,0,0">
<CheckBox x:Name="UDFs" VerticalAlignment="Center" IsChecked="True"/>
<TextBlock Text="User Defined Functions" FontSize="15" VerticalAlignment="Center" Margin="10,0,0,0"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="20,20,0,0">
<CheckBox x:Name="Triggers" VerticalAlignment="Center" IsChecked="True"/>
<TextBlock Text="Triggers" FontSize="15" VerticalAlignment="Center" Margin="10,0,0,0"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="20,20,0,0">
<CheckBox x:Name="IPs" VerticalAlignment="Center" IsChecked="True"/>
<TextBlock Text="Indexing Policies" FontSize="15" VerticalAlignment="Center" Margin="10,0,0,0"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="20,20,0,0">
<CheckBox x:Name="PKs" VerticalAlignment="Center" IsChecked="True"/>
<TextBlock Text="Partition Keys" FontSize="15" VerticalAlignment="Center" Margin="10,0,0,0"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="20,20,0,0">
<TextBlock Text="Offer Throughput" FontSize="15" VerticalAlignment="Center" Margin="10,0,0,0"/>
<TextBox x:Name="OfferThroughput" Text="10000" HorizontalContentAlignment="Right" Width="80" Margin="10,0,0,0" />
</StackPanel>
</StackPanel>
</Grid>
</Page>

Просмотреть файл

@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace CosmicCloneUI
{
/// <summary>
/// Interaction logic for CloneOptionsPage.xaml
/// </summary>
public partial class CloneOptionsPage : Page
{
public CloneOptionsPage()
{
InitializeComponent();
}
}
}

Просмотреть файл

@ -0,0 +1,40 @@
<Page x:Class="CosmicCloneUI.CopyCollectionPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CosmicCloneUI"
mc:Ignorable="d"
d:DesignHeight="320" d:DesignWidth="800"
Title="CopyCollectionPage">
<Grid>
<StackPanel Margin="15,10,5,5">
<StackPanel x:Name="CollectionReadStackPanel" Margin="0,5,0,0">
<TextBlock Text="Reading Collection"/>
<ProgressBar x:Name="ReadProgress" Height="15" Margin="0,2,10,5" Value="0"/>
</StackPanel>
<StackPanel x:Name="CollectionWriteStackPanel" Margin="0,5,0,0">
<TextBlock Text="Writing Collection"/>
<ProgressBar x:Name="WriteProgress" Height="15" Margin="0,2,10,5" Value="0"/>
</StackPanel>
<StackPanel x:Name="ScrubStackPanel" Margin="0,5,0,0">
<TextBlock Text="Anonymization progress"/>
<ProgressBar x:Name="ScrubProgress" Height="15" Margin="0,2,10,5" Value="0"/>
</StackPanel>
<StackPanel Margin="0,10,0,0">
<Button x:Name="ShowStatusButton" Content="Hide status" Margin="0,0,701,0" RenderTransformOrigin="15.969,-5.085" FontSize="9" Click="ShowStatusButton_Click"/>
<Border x:Name="StatusTextBlockBorder" BorderThickness="1" Margin="0,5,10,2">
<!--<ScrollViewer x:Name="StatusTextblockScrollViewer" HorizontalScrollBarVisibility="Auto" >-->
<!--<TextBlock x:Name="StatusTextBlock" ScrollViewer.CanContentScroll="True" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" TextWrapping="Wrap" Height="90" RenderTransformOrigin="0.498,1.559" Opacity="0.9 " FontSize="10"><Run Text="Copy Status Log"/></TextBlock>-->
<!--</ScrollViewer>-->
<TextBox x:Name="StatusTextBlock" Height="100" ScrollViewer.VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True" Focusable="True" IsReadOnly="True">
</TextBox>
</Border>
</StackPanel>
</StackPanel>
</Grid>
</Page>

Просмотреть файл

@ -0,0 +1,74 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using CosmosCloneCommon.Utility;
using logger = CosmosCloneCommon.Utility.CloneLogger;
using CosmosCloneCommon.Model;
namespace CosmicCloneUI
{
/// <summary>
/// Interaction logic for CopyCollectionPage.xaml
/// </summary>
public partial class CopyCollectionPage : Page
{
public CopyCollectionPage()
{
InitializeComponent();
}
public void SetStatus()
{
//StatusTextBlock.Text = CloneLogger.getFullLog();
}
public void setRequiredprogressBars(List<ScrubRule> scrubRules)
{
if(CloneSettings.CopyDocuments==false)
{
CollectionReadStackPanel.Visibility = Visibility.Hidden;
CollectionWriteStackPanel.Visibility = Visibility.Hidden;
}
if(CloneSettings.ScrubbingRequired)
{
if(scrubRules == null || scrubRules.Count<=0)
{
ScrubStackPanel.Visibility = Visibility.Hidden;
}
}
}
private void ShowStatusButton_Click(object sender, RoutedEventArgs e)
{
if(StatusTextBlock.Visibility == Visibility.Visible)
{
StatusTextBlock.Visibility = Visibility.Hidden;
StatusTextBlockBorder.Visibility = Visibility.Hidden;
ShowStatusButton.Content = "Show status";
}
else if(StatusTextBlock.Visibility == Visibility.Hidden)
{
StatusTextBlock.Visibility = Visibility.Visible;
StatusTextBlockBorder.Visibility = Visibility.Visible;
ShowStatusButton.Content = "Hide status";
}
}
}
}

Просмотреть файл

@ -0,0 +1,199 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{D46B0805-591E-4080-A6A1-45613067D900}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>CosmicCloneUI</RootNamespace>
<AssemblyName>CosmicCloneUI</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>C:\clonetest\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>1</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<PublishWizardCompleted>true</PublishWizardCompleted>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</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|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ManifestCertificateThumbprint>53A79A685C21BB2A5CFFF49FE76E2CE192CE3F3B</ManifestCertificateThumbprint>
</PropertyGroup>
<PropertyGroup>
<ManifestKeyFile>CosmicCloneUI_TemporaryKey.pfx</ManifestKeyFile>
</PropertyGroup>
<PropertyGroup>
<GenerateManifests>true</GenerateManifests>
</PropertyGroup>
<PropertyGroup>
<SignManifests>true</SignManifests>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="CloneOptionsPage.xaml.cs">
<DependentUpon>CloneOptionsPage.xaml</DependentUpon>
</Compile>
<Compile Include="CopyCollectionPage.xaml.cs">
<DependentUpon>CopyCollectionPage.xaml</DependentUpon>
</Compile>
<Compile Include="DataAnonymizationPage.xaml.cs">
<DependentUpon>DataAnonymizationPage.xaml</DependentUpon>
</Compile>
<Compile Include="DestinationPage.xaml.cs">
<DependentUpon>DestinationPage.xaml</DependentUpon>
</Compile>
<Compile Include="Models\CloneOptions.cs" />
<Compile Include="Models\CosmosCollection.cs" />
<Compile Include="Models\ScrubDetails.cs" />
<Compile Include="SourcePage.xaml.cs">
<DependentUpon>SourcePage.xaml</DependentUpon>
</Compile>
<Page Include="CloneOptionsPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="CopyCollectionPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="DataAnonymizationPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="DestinationPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="SourcePage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="App.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CosmosCloneCommon\CosmosCloneCommon.csproj">
<Project>{523e1cc4-0286-498c-b184-3413e10d61de}</Project>
<Name>CosmosCloneCommon</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Resource Include="Images\fail.png" />
<Resource Include="Images\success.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Images\cosmosIcon1.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Resource>
</ItemGroup>
<ItemGroup>
<Resource Include="Images\cosmicclonelogo.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Images\closeIcon.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Images\CosmosIcon2.ico" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.6.1">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.6.1 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

Просмотреть файл

@ -0,0 +1,64 @@
<Page x:Class="CosmicCloneUI.DataAnonymizationPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CosmicCloneUI"
mc:Ignorable="d"
d:DesignHeight="320" d:DesignWidth="800"
Title="DataAnonymizationPage">
<Grid>
<StackPanel>
<TextBlock FontSize="15" HorizontalAlignment="Left" Margin="20,0,0,0">
<Span>Enter</Span>
<Span FontWeight="Bold">Data Anonymization</Span>
<Span>rules</Span>
</TextBlock>
<!--<StackPanel Orientation="Horizontal" Height="30" Margin="20,20,0,0">
<TextBlock Text="Filter Condition" FontSize="15" VerticalAlignment="Center" Margin="0,0,0,0"/>
<TextBox x:Name="FilterCondition" Text="" HorizontalContentAlignment="Left" Width="430" Margin="30,0,0,0" />
</StackPanel>-->
<!--<Expander Name="ExpanderControl" Header="Rule 1" HorizontalAlignment="Left" Margin="20,20,0,0">
<StackPanel Orientation="Horizontal" Height="30" Margin="20,20,0,0">
<TextBlock Text="Attribute To Scrub" FontSize="15" VerticalAlignment="Center" Margin="0,0,0,0"/>
<TextBox x:Name="ScrubAttribute" Text="" HorizontalContentAlignment="Left" Width="150" Margin="10,0,0,0" />
<TextBlock Text="Scrub Type" FontSize="15" VerticalAlignment="Center" Margin="10,0,0,0"/>
<ComboBox x:Name="ScrubType" Width="120" Margin="20,0,0,0">
<ComboBoxItem Content="Null"></ComboBoxItem>
<ComboBoxItem Content="Constant"></ComboBoxItem>
<ComboBoxItem Content="Random"></ComboBoxItem>
<ComboBoxItem Content="Shuffle"></ComboBoxItem>
</ComboBox>
<TextBlock Text="Value" FontSize="15" VerticalAlignment="Center" Margin="10,0,0,0"/>
<TextBox x:Name="ScrubValue" Text="" HorizontalContentAlignment="Right" Width="150" Margin="10,0,0,0" />
</StackPanel>
</Expander>-->
<StackPanel Orientation="Horizontal" Height="30" Margin="20,20,0,0">
<Button x:Name="Add" Width="100" Click="BtnAddScrubRule" HorizontalAlignment="Left" Margin="0,0,0,0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Add Rule" VerticalAlignment="Center" Margin="5" />
</StackPanel>
</Button>
<Button x:Name="ValidateRuleButton" Content="Validate" Width="100" Margin="300,0,0,0" Click="ValidateRuleButton_Click"/>
<Button x:Name="SaveRuleButton" Content="Save" Width="100" Margin="20,0,0,0" Click="SaveRuleButton_Click"/>
<Button x:Name="LoadRuleButton" Content="Load" Width="100" Margin="20,0,0,0" Click="LoadRuleButton_Click"/>
</StackPanel>
<ScrollViewer Height="200" VerticalScrollBarVisibility="Visible" >
<Border BorderThickness="3">
<StackPanel x:Name="RulesStackPanel" Orientation="Horizontal">
<StackPanel x:Name="RulesStackPanelLeft" Width="390"/>
<StackPanel x:Name="RulesStackPanelRight" Width="390"/>
</StackPanel>
</Border>
</ScrollViewer>
</StackPanel>
</Grid>
</Page>

Просмотреть файл

@ -0,0 +1,532 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using CosmicCloneUI.Models;
using CosmosCloneCommon.Model;
using CosmosCloneCommon.Utility;
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Win32;
using System.Xml.Serialization;
using System.Globalization;
namespace CosmicCloneUI
{
/// <summary>
/// Interaction logic for DataAnonymizationPage.xaml
/// </summary>
public partial class DataAnonymizationPage : Page
{
int RuleIndex;
public DataAnonymizationPage()
{
InitializeComponent();
SaveRuleButton.IsEnabled = false;
RuleIndex = 1;
}
private bool Validation()
{
return true;
}
private void BtnAddScrubRule(object sender, RoutedEventArgs e)
{
CreateScrubRule();
}
private void CreateScrubRule(ScrubRule scrubRule = null)
{
StackPanel parentStackPanelLeft = (StackPanel)this.FindName("RulesStackPanelLeft");
StackPanel parentStackPanelRight = (StackPanel)this.FindName("RulesStackPanelRight");
int newRuleIndex = newIndex(scrubRule);
if (newRuleIndex % 2 == 1)
{
AddRuleWithData(parentStackPanelLeft, newRuleIndex, scrubRule);
}
else
{
AddRuleWithData(parentStackPanelRight, newRuleIndex, scrubRule);
}
}
int newIndex(ScrubRule scrubRule = null)
{
int newRuleIndex = 0;
if(scrubRule == null)
{
newRuleIndex = RuleIndex++;
}
else
{
if (scrubRule.RuleId == 0)
{
newRuleIndex = RuleIndex++;
}
else newRuleIndex = scrubRule.RuleId;
}
return newRuleIndex;
}
void AddRuleWithData(StackPanel parentStackPanel, int ruleIndex, ScrubRule scrubRule = null)
{
StackPanel RuleHeadersp = new StackPanel();
RuleHeadersp.Orientation = Orientation.Horizontal;
TextBlock HeaderTB = new TextBlock();
HeaderTB.Text = "Rule " + (ruleIndex);
Label RuleIdLabel = new Label();
RuleIdLabel.Content = ruleIndex;
RuleIdLabel.Visibility = Visibility.Hidden;
Button DeleteBtn = new Button();
DeleteBtn.Name = "btnDelete_" + ruleIndex;
DeleteBtn.HorizontalAlignment = HorizontalAlignment.Right;
//DeleteBtn.Content = "Delete";
DeleteBtn.Margin = new Thickness(265, 0, 0, 0);
DeleteBtn.Click += DeleteBtn_Click;
DeleteBtn.Content = new Image
{
Source = new BitmapImage(new Uri("/Images/closeIcon.png", UriKind.Relative)),
VerticalAlignment = VerticalAlignment.Center
};
RuleHeadersp.Children.Add(HeaderTB);
RuleHeadersp.Children.Add(DeleteBtn);
Expander exp = new Expander();
exp.Header = RuleHeadersp;
exp.HorizontalAlignment = HorizontalAlignment.Left;
exp.Margin = new Thickness(20, 30, 0, 0);
exp.BorderThickness = new Thickness(1, 1, 1, 1);
exp.Width = 350;
exp.BorderBrush = Brushes.Gray;
exp.Background = Brushes.White;
exp.IsExpanded = true;
exp.Name = "RuleExpander_" + ruleIndex;
StackPanel sp = new StackPanel();
sp.Orientation = Orientation.Vertical;
sp.Margin = new Thickness(20, 5, 0, 0);
StackPanel filterSP = new StackPanel();
filterSP.Orientation = Orientation.Horizontal;
filterSP.Margin = new Thickness(0, 5, 0, 2);
StackPanel attributeSP = new StackPanel();
attributeSP.Orientation = Orientation.Horizontal;
attributeSP.Margin = new Thickness(0, 5, 0, 2);
StackPanel scrubTypeSP = new StackPanel();
scrubTypeSP.Orientation = Orientation.Horizontal;
scrubTypeSP.Margin = new Thickness(0, 5, 0, 2);
StackPanel scrubValueSP = new StackPanel();
scrubValueSP.Orientation = Orientation.Horizontal;
scrubValueSP.Margin = new Thickness(0, 5, 0, 2);
TextBlock FilterLabel = new TextBlock();
FilterLabel.VerticalAlignment = VerticalAlignment.Center;
FilterLabel.Margin = new Thickness(10, 0, 0, 0);
//FilterLabel.MaxWidth = 150;
Run runFilterLabel = new Run();
runFilterLabel.Text = "Filter Query";
runFilterLabel.FontSize = 15;
Run runFilterLabelHint = new Run();
runFilterLabelHint.Text = " \nEx: c.Type = \"document\"";
runFilterLabelHint.FontSize = 10;
FilterLabel.Inlines.Add(runFilterLabel);
FilterLabel.Inlines.Add(runFilterLabelHint);
TextBox FilterTB = new TextBox();
FilterTB.Name = "Filter" + ruleIndex;
FilterTB.Width = 150;
FilterTB.HorizontalContentAlignment = HorizontalAlignment.Left;
FilterTB.VerticalAlignment = VerticalAlignment.Center;
FilterTB.Margin = new Thickness(20, 0, 0, 0);
TextBlock AttributeScrubLabel = new TextBlock();
AttributeScrubLabel.VerticalAlignment = VerticalAlignment.Center;
AttributeScrubLabel.Margin = new Thickness(10, 0, 0, 0);
//AttributeScrubLabel.Width = 120;
Run runAttributeScrubLabel = new Run();
runAttributeScrubLabel.Text = "Attribute To Scrub";
runAttributeScrubLabel.FontSize = 15;
Run runAttributeScrubLabelHint = new Run();
runAttributeScrubLabelHint.Text = " \nEx: c.Person.Email";
runAttributeScrubLabelHint.FontSize = 10;
AttributeScrubLabel.Inlines.Add(runAttributeScrubLabel);
AttributeScrubLabel.Inlines.Add(runAttributeScrubLabelHint);
TextBox AttributeScrubTB = new TextBox();
AttributeScrubTB.Name = "ScrubAttribute" + ruleIndex;
AttributeScrubTB.Width = 150;
AttributeScrubTB.HorizontalContentAlignment = HorizontalAlignment.Left;
AttributeScrubTB.VerticalAlignment = VerticalAlignment.Center;
AttributeScrubTB.Margin = new Thickness(20, 0, 0, 0);
TextBlock ScrubTypeLabel = new TextBlock();
ScrubTypeLabel.Text = "Scrub Type";
ScrubTypeLabel.FontSize = 15;
ScrubTypeLabel.VerticalAlignment = VerticalAlignment.Center;
ScrubTypeLabel.Margin = new Thickness(10, 0, 0, 0);
ComboBox ScrubTypeCB = new ComboBox();
ScrubTypeCB.Name = "ScrubType" + ruleIndex;
ScrubTypeCB.Width = 150;
ScrubTypeCB.Margin = new Thickness(20, 0, 0, 0);
foreach (RuleType val in Enum.GetValues(typeof(RuleType)))
{
ScrubTypeCB.Items.Add(val.ToString());
}
ScrubTypeCB.SelectionChanged += new SelectionChangedEventHandler(scrubTypeComboBox_SelectedIndexChanged);
TextBlock ScrubValueLabel = new TextBlock();
ScrubValueLabel.Text = "Replace with";
ScrubValueLabel.FontSize = 15;
ScrubValueLabel.VerticalAlignment = VerticalAlignment.Center;
ScrubValueLabel.Margin = new Thickness(10, 0, 0, 5);
TextBox ScrubValueTB = new TextBox();
ScrubValueTB.Name = "ScrubValue" + ruleIndex;
ScrubValueTB.Width = 150;
ScrubValueTB.HorizontalContentAlignment = HorizontalAlignment.Left;
ScrubValueTB.VerticalAlignment = VerticalAlignment.Center;
ScrubValueTB.Margin = new Thickness(20, 0, 0, 0);
FilterLabel.Width = 120;
FilterTB.Width = 150;
AttributeScrubLabel.Width = 120;
AttributeScrubTB.Width = 150;
ScrubTypeLabel.Width = 120;
ScrubTypeCB.Width = 150;
ScrubValueLabel.Width = 120;
filterSP.Children.Add(FilterLabel);
filterSP.Children.Add(FilterTB);
attributeSP.Children.Add(AttributeScrubLabel);
attributeSP.Children.Add(AttributeScrubTB);
scrubTypeSP.Children.Add(ScrubTypeLabel);
scrubTypeSP.Children.Add(ScrubTypeCB);
scrubValueSP.Children.Add(ScrubValueLabel);
scrubValueSP.Children.Add(ScrubValueTB);
scrubValueSP.Children.Add(RuleIdLabel);
scrubValueSP.Visibility = Visibility.Hidden;
sp.Children.Add(attributeSP);
sp.Children.Add(filterSP);
sp.Children.Add(scrubTypeSP);
sp.Children.Add(scrubValueSP);
exp.Content = sp;
if(scrubRule!=null)
{
FilterTB.Text = scrubRule.FilterCondition;
AttributeScrubTB.Text = scrubRule.PropertyName;
if(scrubRule.Type!=null) ScrubTypeCB.SelectedIndex = (int)scrubRule.Type;
ScrubValueTB.Text = scrubRule.UpdateValue;
}
parentStackPanel.Children.Add(exp);
if(!SaveRuleButton.IsEnabled)
{
SaveRuleButton.IsEnabled = true;
}
}
private void scrubTypeComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
//check comobox status based on it change visibility of scrubvalue stack panel
var cbox = (ComboBox)sender;
if (cbox.SelectedValue.ToString().Equals(RuleType.SingleValue.ToString()))
{
var parentPanel = (StackPanel)cbox.Parent;
var gpPanel = (StackPanel)parentPanel.Parent;
gpPanel.Children[3].Visibility = Visibility.Visible;
}
else
{
var parentPanel = (StackPanel)cbox.Parent;
var gpPanel = (StackPanel)parentPanel.Parent;
gpPanel.Children[3].Visibility = Visibility.Hidden;
}
}
private void DeleteBtn_Click(object sender, RoutedEventArgs e)
{
var btnDelete = (Button)sender;
string expname = "RuleExpander_" + btnDelete.Name.Substring(btnDelete.Name.IndexOf('_')+1);
StackPanel parentStackPanel = (StackPanel)this.FindName("RulesStackPanel");
UIElementCollection ChildrenSPs = parentStackPanel.Children;
foreach (UIElement LeftRightSPUI in ChildrenSPs)
{
StackPanel sp = (StackPanel)LeftRightSPUI;
UIElementCollection uiElementsLeftRight = sp.Children;
foreach (UIElement SPUI in uiElementsLeftRight)
{
Expander exp = (Expander)SPUI;
if (exp.Name == expname)
{
sp.Children.Remove(SPUI);
break;
}
}
}
var rules = getScrubRules();
//Delete all scrub rules
StackPanel parentStackPanelLeft = (StackPanel)this.FindName("RulesStackPanelLeft");
StackPanel parentStackPanelRight = (StackPanel)this.FindName("RulesStackPanelRight");
parentStackPanelLeft.Children.RemoveRange(0, parentStackPanelLeft.Children.Count);
parentStackPanelRight.Children.RemoveRange(0, parentStackPanelRight.Children.Count);
//Re initialize rule index
this.RuleIndex = 1;
foreach (var rule in rules)
{
rule.RuleId = 0;//reset Ids so they are re assigned
CreateScrubRule(rule);
}
}
public List<ScrubRule> getScrubRules()
{
//List<ScrubRule> sb = new List<ScrubRule>();
TextBox filterCondition = (TextBox)this.FindName("FilterCondition");
//sb.filterQuery = filterCondition.Text;
List<ScrubRule> srList = new List<ScrubRule>();
StackPanel parentStackPanel = (StackPanel)this.FindName("RulesStackPanel");
UIElementCollection ChildrenSPs = parentStackPanel.Children;
foreach (UIElement LeftRightSPUI in ChildrenSPs)
{
StackPanel sp = (StackPanel)LeftRightSPUI;
UIElementCollection uiElementsLeftRight = sp.Children;
foreach (UIElement SPUI in uiElementsLeftRight)
{
Expander exp = (Expander)SPUI;
StackPanel lrsp = (StackPanel)exp.Content;
UIElementCollection uiElementsSP = lrsp.Children;
ScrubRule sr = new ScrubRule();
foreach (UIElement uiElementSP in uiElementsSP)
{
StackPanel tempSP = (StackPanel)uiElementSP;
UIElementCollection uiElements = tempSP.Children;
foreach (UIElement uiElement in uiElements)
{
if (uiElement.GetType().Name == "Label")
{
var ruleIdLabel = (Label)uiElement;
int ruleId;
if (int.TryParse(ruleIdLabel.Content.ToString(), out ruleId))
{
sr.RuleId = ruleId;
}
else sr.RuleId = 0;
}
if (uiElement.GetType().Name == "TextBox")
{
TextBox tb = (TextBox)uiElement;
string name = tb.Name.Substring(0, tb.Name.Length - 1);
if (name == "Filter")
{
sr.FilterCondition = tb.Text.Trim();
}
else if (name == "ScrubAttribute")
{
sr.PropertyName = tb.Text.Trim();
}
else if (name == "ScrubValue")
{
sr.UpdateValue = tb.Text.Trim();
}
}
if (uiElement.GetType().Name == "ComboBox")
{
ComboBox cb = (ComboBox)uiElement;
string name = cb.Name.Substring(0, cb.Name.Length - 1);
if (name == "ScrubType")
{
//sr.Type = (RuleType) Enum.Parse(typeof(RuleType), cb.Text);
RuleType rType;
if (Enum.TryParse<RuleType>(cb.Text, out rType))
{
sr.Type = rType;
}
else
{
sr.Type = null;
}
}
}
}
}
srList.Add(sr);
}
}
return srList;
}
public bool validateInput()
{
var rules = getScrubRules();
var orderedRules = rules.OrderBy(o => o.RuleId).ToList();
bool isValidationSuccess;
var validationMessages = new List<string>();
foreach (var rule in orderedRules)
{
if(rule.Type == null)
{
validationMessages.Add($"Rule:{rule.RuleId} - Please select a valid anonymization type");
}
if(string.IsNullOrEmpty(rule.PropertyName))
{
validationMessages.Add($"Rule:{rule.RuleId} - Attribute name is empty");
}
else if (!rule.PropertyName.StartsWith("c."))
{
validationMessages.Add($"Rule:{rule.RuleId} - Attribute name starts improperly. Sample c.EntityType");
}
else if (rule.PropertyName.EndsWith("."))
{
validationMessages.Add($"Rule:{rule.RuleId} - Attribute name Ends improperly. Sample c.EntityType");
}
if (!string.IsNullOrEmpty(rule.FilterCondition))
{
if (!rule.FilterCondition.StartsWith("c."))
{
validationMessages.Add($"Rule:{rule.RuleId} - Filter condition starts improperly. Sample c.EntityType=\"document\" ");
}
}
}
if(validationMessages.Count > 0)
{
isValidationSuccess = false;
string message="";
foreach(var msg in validationMessages)
{
message += (msg + System.Environment.NewLine);
}
MessageBox.Show(message, "Input validation",MessageBoxButton.OK,MessageBoxImage.Error);
}
else isValidationSuccess = true;
return isValidationSuccess;
}
private void SaveRuleButton_Click(object sender, RoutedEventArgs e)
{
var rules = this.getScrubRules();
if (rules == null || rules.Count == 0)
{
MessageBox.Show("No Rules found. Please add/load anonymization rules before Save", "No rules Found", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
saveFileDialog.Filter = "XML file (*.xml)|*.xml";
saveFileDialog.Title = "CosmicClone save AnonymizationRules";
saveFileDialog.FileName = "AnonymizationRules_"+ DateTime.Now.ToString("MM-dd-yyyy-HHmmss",CultureInfo.InvariantCulture);
if (saveFileDialog.ShowDialog() == true)
{
var xmlText = CloneSerializer.XMLSerialize(rules);
File.WriteAllText(saveFileDialog.FileName, xmlText);
}
}
private void LoadRuleButton_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
openFileDialog.Filter = "XML file (*.xml)|*.xml";
openFileDialog.Title = "CosmicClone Load AnonymizationRules";
if (openFileDialog.ShowDialog() == true)
{
string xmlText = File.ReadAllText(openFileDialog.FileName);
var rules = CloneSerializer.XMLDeserialize<List<ScrubRule>>(xmlText);
if (rules == null && rules.Count == 0)
{
MessageBox.Show("No rules to Load in file : "+openFileDialog.FileName , "No rules Found", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
var orderedRules = rules.OrderBy(o => o.RuleId).ToList();
//Delete all scrub rules
StackPanel parentStackPanelLeft = (StackPanel)this.FindName("RulesStackPanelLeft");
StackPanel parentStackPanelRight = (StackPanel)this.FindName("RulesStackPanelRight");
parentStackPanelLeft.Children.RemoveRange(0, parentStackPanelLeft.Children.Count);
parentStackPanelRight.Children.RemoveRange(0, parentStackPanelRight.Children.Count);
//Re initialize rule index
this.RuleIndex = 1;
foreach (var rule in orderedRules)
{
CreateScrubRule(rule);
}
}
//txtEditor.Text = File.ReadAllText(openFileDialog.FileName);
//handle unable to load exception
}
private void ValidateRuleButton_Click(object sender, RoutedEventArgs e)
{
var rules = getScrubRules();
if (rules == null || rules.Count==0)
{
MessageBox.Show("No Rules found. Please add/load anonymization rules before Validation", "Data validation", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
bool isValidationSuccess = this.validateInput();
if (isValidationSuccess)
{
MessageBox.Show("Rules Validated Successfully", "Data validation", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
}
}

Просмотреть файл

@ -0,0 +1,45 @@
<Page x:Class="CosmicCloneUI.DestinationPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CosmicCloneUI"
mc:Ignorable="d"
d:DesignHeight="320" d:DesignWidth="800"
Title="DestinationPage">
<Grid>
<StackPanel Margin="20,20">
<!--<Label Content="Enter Target Connection Details" FontSize="15" />-->
<TextBlock FontSize="15">
<Span>Enter</Span>
<Span FontWeight="Bold">Target</Span>
<Span>connection details</Span>
</TextBlock>
<StackPanel Orientation="Horizontal" Margin="0,10,0,10">
<Label Content="Url" Width="200" FontSize="15" />
<TextBox x:Name="TargetURL" Width="400" VerticalContentAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,10">
<Label Content="Access Key" Width="200" FontSize="15" />
<TextBox x:Name="TargetKey" Width="400" VerticalContentAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,10">
<Label Content="Database" Width="200" FontSize="15" />
<TextBox x:Name="TargetDB" Width="400" VerticalContentAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,10">
<Label Content="Collection" Width="200" FontSize="15" />
<TextBox x:Name="TargetCollection" Width="400" VerticalContentAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Image x:Name="ConnectionIcon" Width="30" Height="30" Margin="0,0,10,0"/>
<Button Width="150" Height="40" Click="BtnTestTarget" HorizontalAlignment="Right" Margin="0,0,160,0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Test Connection" VerticalAlignment="Center" Margin="5" />
</StackPanel>
</Button>
</StackPanel>
</StackPanel>
</Grid>
</Page>

Просмотреть файл

@ -0,0 +1,65 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using CosmosCloneCommon.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace CosmicCloneUI
{
/// <summary>
/// Interaction logic for DestinationPage.xaml
/// </summary>
public partial class DestinationPage : Page
{
CosmosDBHelper cosmosHelper;
public DestinationPage()
{
InitializeComponent();
cosmosHelper = new CosmosDBHelper();
}
private void BtnTestTarget(object sender, RoutedEventArgs e)
{
if (TestConnection())
{
var connectionIcon = (Image)this.FindName("ConnectionIcon");
ConnectionIcon.Source = new BitmapImage(new Uri("/Images/success.png", UriKind.Relative));
}
else
{
var connectionIcon = (Image)this.FindName("ConnectionIcon");
ConnectionIcon.Source = new BitmapImage(new Uri("/Images/fail.png", UriKind.Relative));
}
}
private bool TestConnection()
{
CloneSettings.TargetSettings = new CosmosCollectionValues()
{
EndpointUrl = TargetURL.Text.ToString(),
AccessKey = TargetKey.Text.ToString(),
DatabaseName = TargetDB.Text.ToString(),
CollectionName = TargetCollection.Text.ToString()
};
var result = cosmosHelper.TestTargetConnection_v2();
if (result.IsSuccess == true)
return true;
else
return false;
}
}
}

Двоичные данные
CosmosClone/CosmicCloneUI/Images/CosmosIcon2.ico Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 102 KiB

Двоичные данные
CosmosClone/CosmicCloneUI/Images/closeIcon.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 589 B

Двоичные данные
CosmosClone/CosmicCloneUI/Images/cosmicclonelogo.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 94 KiB

Двоичные данные
CosmosClone/CosmicCloneUI/Images/cosmosIcon1.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 4.2 KiB

Двоичные данные
CosmosClone/CosmicCloneUI/Images/fail.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.6 KiB

Двоичные данные
CosmosClone/CosmicCloneUI/Images/success.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.5 KiB

Просмотреть файл

@ -0,0 +1,35 @@
<Window x:Class="CosmicCloneUI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CosmicCloneUI"
mc:Ignorable="d"
Title="CosmicClone v2.0" Height="500" Width="800" ResizeMode="NoResize" WindowStartupLocation="CenterScreen" Icon="/Images/CosmosIcon2.ico">
<Grid>
<Border BorderBrush="Black" Background="LightGray" BorderThickness="1" HorizontalAlignment="Left" Height="80" VerticalAlignment="Top" Width="790" Margin="0,0,0,0">
<!--<StackPanel>
<TextBlock Text="Cosmic Clone" FontSize="20" HorizontalAlignment="Center"/>
<TextBlock TextWrapping="Wrap" HorizontalAlignment="Center" Text="Cosmos Database Backup restore copy utility"
FontSize="15" Margin="10,0,10,0"/>
</StackPanel>-->
<StackPanel Orientation="Horizontal">
<Image x:Name="logo1" Width="75" Height="80" HorizontalAlignment="Left" Source="/Images/cosmosIcon1.png" Margin="0,0,0,0"/>
<Image x:Name="headerlogo" Width="640" Height="80" HorizontalAlignment="Left" Source="/Images/cosmicclonelogo.png" Margin="0,0,0,0"/>
<Image x:Name="logo2" Width="75" Height="80" Source="/Images/cosmosIcon1.png" Margin="0,0,0,0"/>
</StackPanel>
</Border>
<Border Background="WhiteSmoke" BorderThickness="1" HorizontalAlignment="Left" Height="390" Margin="00,80,0,0" VerticalAlignment="Top" Width="790">
<Grid HorizontalAlignment="Left" Height="390" Margin="00,00,0,0" VerticalAlignment="Top" Width="790">
<StackPanel HorizontalAlignment="Left" Height="320" Margin="00,00,0,0" VerticalAlignment="Top" Width="790">
<Frame x:Name="_mainFrame" NavigationUIVisibility="Hidden" LoadCompleted="MainFrameLoaded" />
</StackPanel>
<StackPanel Orientation="Horizontal" Height="70" Margin="0,300,0,0" Width="790">
<Button x:Name="btn_previous" Content="Previous" MinWidth="100" Height="30" Margin="450,0,0,0" Click="BtnClickPrevious" />
<Button x:Name="btn_next" Content="Next" MinWidth="100" Height="30" Margin="10,0,0,0" Click="BtnClickNext" />
<Button x:Name="btn_finish" Content="Finish" MinWidth="100" Height="30" Margin="10,0,0,0" Click="BtnClickFinish" />
</StackPanel>
</Grid>
</Border>
</Grid>
</Window>

Просмотреть файл

@ -0,0 +1,337 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using CosmicCloneUI.Models;
using CosmosCloneCommon.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using CosmosCloneCommon.Migrator;
using CosmosCloneCommon.Model;
using logger = CosmosCloneCommon.Utility.CloneLogger;
namespace CosmicCloneUI
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Page sourcePage;
Page destinationPage;
Page cloneOptionsPage;
Page dataAnonymizationPage;
Page copyCollectionPage;
Page[] pages;
CosmosDBHelper cosmosHelper;
List<ScrubRule> scrubRules;
public MainWindow()
{
InitializeComponent();
InitializePages();
cosmosHelper = new CosmosDBHelper();
this.Dispatcher.UnhandledException += OnDispatcherUnhandledException;
}
void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
string errorMessage = string.Format("An unhandled exception occurred: {0}", e.Exception.Message);
MessageBox.Show(errorMessage, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
e.Handled = true;
}
private void InitializePages()
{
sourcePage = new SourcePage();
destinationPage = new DestinationPage();
cloneOptionsPage = new CloneOptionsPage();
dataAnonymizationPage = new DataAnonymizationPage();
copyCollectionPage = new CopyCollectionPage();
//copyCollectionPage.SetStatus();
pages = new Page[10];
pages[0] = sourcePage;
pages[1] = destinationPage;
pages[2] = cloneOptionsPage;
pages[3] = dataAnonymizationPage;
pages[4] = copyCollectionPage;
_mainFrame.Content = pages[0];
}
private void BtnClickPrevious(object sender, RoutedEventArgs e)
{
Page currentPage = (Page)_mainFrame.Content;
_mainFrame.Navigate(getPreviousPage(currentPage));
}
private void BtnClickNext(object sender, RoutedEventArgs e)
{
Page currentPage = (Page)_mainFrame.Content;
if(performAction(currentPage))
{
_mainFrame.Navigate(getNextPage(currentPage));
}
}
private void BtnClickFinish(object sender, RoutedEventArgs e)
{
this.Close();
}
private void NavigationHelper()
{
Page currentPage = (Page)_mainFrame.Content;
int pagenum = getPageNumber(currentPage);
if (pagenum == 0)
{
btn_previous.IsEnabled = false;
btn_next.IsEnabled = true;
btn_finish.IsEnabled = false;
}
else if (pagenum == 4)
{
btn_previous.IsEnabled = false;
btn_next.IsEnabled = false;
btn_finish.IsEnabled = false;//is this required
}
else
{
btn_previous.IsEnabled = true;
btn_next.IsEnabled = true;
btn_finish.IsEnabled = false;
}
}
private Page getNextPage(Page currentPage)
{
return pages[getPageNumber(currentPage) + 1];
}
private Page getPreviousPage(Page currentPage)
{
return pages[getPageNumber(currentPage) - 1];
}
private int getPageNumber(Page page)
{
for(int i=0;i<pages.Length;i++)
{
if(pages[i] == page)
{
return i;
}
}
return 0;
}
private void MainFrameLoaded(object sender, EventArgs e)
{
NavigationHelper();
}
private bool performAction(Page currentPage)
{
if (getPageNumber(currentPage) == 0)
{
CloneSettings.SourceSettings = new CosmosCollectionValues()
{
EndpointUrl = ((TextBox)currentPage.FindName("SourceURL")).Text.ToString(),
AccessKey = ((TextBox)currentPage.FindName("SourceKey")).Text.ToString(),
DatabaseName = ((TextBox)currentPage.FindName("SourceDB")).Text.ToString(),
CollectionName = ((TextBox)currentPage.FindName("SourceCollection")).Text.ToString()
//OfferThroughputRUs = int.Parse(sourceConfigs["OfferThroughputRUs"])
};
var result = cosmosHelper.TestSourceConnection_v2();
if (result.IsSuccess == true)
return true;
else
return false;
}
else if (getPageNumber(currentPage) == 1)
{
CloneSettings.TargetSettings = new CosmosCollectionValues()
{
EndpointUrl = ((TextBox)currentPage.FindName("TargetURL")).Text,
AccessKey = ((TextBox)currentPage.FindName("TargetKey")).Text,
DatabaseName = ((TextBox)currentPage.FindName("TargetDB")).Text,
CollectionName = ((TextBox)currentPage.FindName("TargetCollection")).Text
//OfferThroughputRUs = int.Parse(sourceConfigs["OfferThroughputRUs"])
};
var result = cosmosHelper.TestTargetConnection_v2();
if (result.IsSuccess == true)
return true;
else
return false;
}
else if (getPageNumber(currentPage) == 2)
{
CloneSettings.CopyStoredProcedures = ((CheckBox)currentPage.FindName("SPs")).IsChecked.Value;
CloneSettings.CopyUDFs = ((CheckBox)currentPage.FindName("UDFs")).IsChecked.Value;
CloneSettings.CopyTriggers = ((CheckBox)currentPage.FindName("Triggers")).IsChecked.Value;
CloneSettings.CopyDocuments = ((CheckBox)currentPage.FindName("Documents")).IsChecked.Value;
CloneSettings.CopyIndexingPolicy = ((CheckBox)currentPage.FindName("IPs")).IsChecked.Value;
CloneSettings.CopyPartitionKey = ((CheckBox)currentPage.FindName("PKs")).IsChecked.Value;
return true;
}
else if (getPageNumber(currentPage) == 3)
{
btn_finish.IsEnabled = false;
scrubRules = ((DataAnonymizationPage)currentPage).getScrubRules();
bool isValidationSuccess = ((DataAnonymizationPage)currentPage).validateInput();
if (!isValidationSuccess) return false;
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += worker_DoWork;
worker.ProgressChanged += worker_ProgressChanged;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.RunWorkerAsync(1000);
BackgroundWorker worker2 = new BackgroundWorker();
worker2.WorkerReportsProgress = true;
worker2.DoWork += worker_DoWork2;
worker2.ProgressChanged += worker_ProgressChanged2;
worker2.RunWorkerCompleted += worker_RunWorkerCompleted2;
worker2.RunWorkerAsync(1000);
var nextPage = getNextPage(currentPage);
((CopyCollectionPage)nextPage).setRequiredprogressBars(scrubRules);
return true;
}
else if (getPageNumber(currentPage) == 4)
{
btn_finish.IsEnabled = false;
((CopyCollectionPage)currentPage).setRequiredprogressBars(scrubRules);
return true;
}
else
{
return true;
}
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
try
{
var documentMigrator = new CosmosCloneCommon.Migrator.DocumentMigrator();
documentMigrator.StartCopy(scrubRules).Wait();
}
catch(Exception ex)
{
logger.LogInfo("Main process exits with error");
logger.LogError(ex);
string excmessage = "Main process exits with error. /n" + ex.Message + "/n";
if(ex.InnerException!=null)
{
excmessage += ex.InnerException.Message;
}
MessageBox.Show(excmessage, "Error occurred. App closure", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//((ProgressBar)pages[3].FindName("ReadProgress")).Value = e.ProgressPercentage;
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//MessageBox.Show("Document Collection Copied Successfully : ");
}
void worker_DoWork2(object sender, DoWorkEventArgs e)
{
long readPercentProgress = 0;
long writePercentProgress = 0;
long scrubPercentProgress = 0;
int sendPercent = 0;
while (readPercentProgress < 100 || writePercentProgress < 100 || scrubPercentProgress < 100)
{
if (DocumentMigrator.TotalRecordsInSource == 0 && CloneSettings.CopyDocuments==true)
{
readPercentProgress = 0;
writePercentProgress = 0;
//scrubPercentProgress = 0;
}
else
{
readPercentProgress = (DocumentMigrator.TotalRecordsRetrieved * 100) / DocumentMigrator.TotalRecordsInSource;
writePercentProgress = (DocumentMigrator.TotalRecordsSent * 100) / DocumentMigrator.TotalRecordsInSource;
if(CloneSettings.ScrubbingRequired && DocumentMigrator.scrubRules!=null && DocumentMigrator.scrubRules.Count>0)
{
scrubPercentProgress = DocumentMigrator.ScrubPercentProgress;
}
else scrubPercentProgress = 100;
}
sendPercent = (int)scrubPercentProgress * 1000000 + (int)readPercentProgress * 1000 + (int)writePercentProgress ;
(sender as BackgroundWorker).ReportProgress((int)sendPercent);
Task.Delay(3000).Wait();
}
}
void worker_ProgressChanged2(object sender, ProgressChangedEventArgs e)
{
int receivePercent = e.ProgressPercentage;
int writePercent = (receivePercent % 1000);
int readPercent = (receivePercent % 1000000) / 1000;
int scrubPercent = receivePercent/1000000;
((ProgressBar)pages[4].FindName("ReadProgress")).Value = readPercent;
((ProgressBar)pages[4].FindName("WriteProgress")).Value = writePercent;
((ProgressBar)pages[4].FindName("ScrubProgress")).Value = scrubPercent;
var statustextbox = ((TextBox)pages[4].FindName("StatusTextBlock"));
statustextbox.Text = logger.FullLog;
statustextbox.ScrollToEnd();
}
void worker_RunWorkerCompleted2(object sender, RunWorkerCompletedEventArgs e)
{
while(!DocumentMigrator.IsCodeMigrationComplete)
{
Task.Delay(5000).Wait();
}
if(DocumentMigrator.IsCodeMigrationComplete)
{
string completeMessage = DocumentMigrator.TotalRecordsSent + " Documents Copied Successfully";
completeMessage += "\n" + "Code Migration Complete";
if (DocumentMigrator.scrubRules!=null && DocumentMigrator.scrubRules.Count>0)
{
completeMessage += "\n" + "Scrubbing completed for rules " + DocumentMigrator.scrubRules.Count;
}
MessageBox.Show(completeMessage, "Completed", MessageBoxButton.OK, MessageBoxImage.Information);
btn_finish.IsEnabled = true;
}
}
}
}

Просмотреть файл

@ -0,0 +1,23 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CosmicCloneUI.Models
{
class CloneOptions
{
public bool copySP { get; set; }
public bool copyUDF { get; set; }
public bool copyTrigger { get; set; }
public bool copyDocument { get; set; }
public bool copyIndexingPolicy { get; set; }
public bool copyPartitionKey { get; set; }
public long offerThroughput { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CosmicCloneUI.Models
{
class CosmosCollection
{
public string Url { get; set; }
public string AccessKey { get; set; }
public string Database { get; set; }
public string Collection { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,26 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CosmicCloneUI.Models
{
//class ScrubDetails
//{
// public List<ScrubRule> scrubRules { get; set; }
//}
//class ScrubRule
//{
// public int id { get; set; }
// public string filterQuery { get; set; }
// public string attributeName { get; set; }
// public string scrubType { get; set; }
// public string scrubValue { get; set; }
//}
}

Просмотреть файл

@ -0,0 +1,55 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// 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("CosmicCloneUI")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CosmicCloneUI")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[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)]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
// 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")]

71
CosmosClone/CosmicCloneUI/Properties/Resources.Designer.cs сгенерированный Normal file
Просмотреть файл

@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace CosmicCloneUI.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CosmicCloneUI.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

Просмотреть файл

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

30
CosmosClone/CosmicCloneUI/Properties/Settings.Designer.cs сгенерированный Normal file
Просмотреть файл

@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace CosmicCloneUI.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

Просмотреть файл

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

Просмотреть файл

@ -0,0 +1,45 @@
<Page x:Class="CosmicCloneUI.SourcePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CosmicCloneUI"
mc:Ignorable="d"
d:DesignHeight="320" d:DesignWidth="800"
Title="SourcePage">
<Grid>
<StackPanel Margin="20,20">
<!--<Label Content="Enter Source connection details" FontSize="15" />-->
<TextBlock FontSize="15">
<Span>Enter</Span>
<Span FontWeight="Bold">Source</Span>
<Span>connection details</Span>
</TextBlock>
<StackPanel Orientation="Horizontal" Margin="0,10,0,10">
<Label Content="Url" Width="200" FontSize="15" />
<TextBox x:Name="SourceURL" Width="400" VerticalContentAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,10">
<Label Content="Access Key" Width="200" FontSize="15" />
<TextBox x:Name="SourceKey" Width="400" VerticalContentAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,10">
<Label Content="Database" Width="200" FontSize="15" />
<TextBox x:Name="SourceDB" Width="400" VerticalContentAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,10">
<Label Content="Collection" Width="200" FontSize="15" />
<TextBox x:Name="SourceCollection" Width="400" VerticalContentAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Image x:Name="ConnectionIcon" Width="30" Height="30" Margin="0,0,10,0"/>
<Button x:Name="TestSrcButton" Width="150" Height="40" Click="BtnTestSource" HorizontalAlignment="Right" Margin="0,0,160,0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Test Connection" VerticalAlignment="Center" Margin="5" />
</StackPanel>
</Button>
</StackPanel>
</StackPanel>
</Grid>
</Page>

Просмотреть файл

@ -0,0 +1,62 @@
using CosmosCloneCommon.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace CosmicCloneUI
{
/// <summary>
/// Interaction logic for SourcePage.xaml
/// </summary>
public partial class SourcePage : Page
{
CosmosDBHelper cosmosHelper;
public SourcePage()
{
InitializeComponent();
cosmosHelper = new CosmosDBHelper();
}
private void BtnTestSource(object sender, RoutedEventArgs e)
{
if (TestConnection())
{
var connectionIcon = (Image)this.FindName("ConnectionIcon");
ConnectionIcon.Source = new BitmapImage(new Uri("/Images/success.png", UriKind.Relative));
}
else
{
var connectionIcon = (Image)this.FindName("ConnectionIcon");
ConnectionIcon.Source = new BitmapImage(new Uri("/Images/fail.png", UriKind.Relative));
}
}
private bool TestConnection()
{
CloneSettings.SourceSettings = new CosmosCollectionValues()
{
EndpointUrl = SourceURL.Text.ToString(),
AccessKey = SourceKey.Text.ToString(),
DatabaseName = SourceDB.Text.ToString(),
CollectionName = SourceCollection.Text.ToString()
};
var result = cosmosHelper.TestSourceConnection_v2();
if (result.IsSuccess == true)
return true;
else
return false;
}
}
}

Просмотреть файл

@ -0,0 +1,37 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27703.2035
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CloneConsoleRun", "CloneConsoleRun\CloneConsoleRun.csproj", "{1F09A007-9A2E-40D8-AD24-C469473152F4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CosmosCloneCommon", "CosmosCloneCommon\CosmosCloneCommon.csproj", "{523E1CC4-0286-498C-B184-3413E10D61DE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CosmicCloneUI", "CosmicCloneUI\CosmicCloneUI.csproj", "{D46B0805-591E-4080-A6A1-45613067D900}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1F09A007-9A2E-40D8-AD24-C469473152F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1F09A007-9A2E-40D8-AD24-C469473152F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1F09A007-9A2E-40D8-AD24-C469473152F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1F09A007-9A2E-40D8-AD24-C469473152F4}.Release|Any CPU.Build.0 = Release|Any CPU
{523E1CC4-0286-498C-B184-3413E10D61DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{523E1CC4-0286-498C-B184-3413E10D61DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{523E1CC4-0286-498C-B184-3413E10D61DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{523E1CC4-0286-498C-B184-3413E10D61DE}.Release|Any CPU.Build.0 = Release|Any CPU
{D46B0805-591E-4080-A6A1-45613067D900}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D46B0805-591E-4080-A6A1-45613067D900}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D46B0805-591E-4080-A6A1-45613067D900}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D46B0805-591E-4080-A6A1-45613067D900}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {74BA2FD9-AD35-45D5-BC7E-7555517B9CDA}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
</configuration>

Просмотреть файл

@ -0,0 +1,9 @@
<Application x:Class="CosmosClone.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CosmosClone"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

Просмотреть файл

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace CosmosClone
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

Просмотреть файл

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A9FEA8E3-D088-423D-91B1-0E205BF60970}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>CosmosClone</RootNamespace>
<AssemblyName>CosmosClone</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</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|AnyCPU' ">
<PlatformTarget>AnyCPU</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.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

Просмотреть файл

@ -0,0 +1,13 @@
<Window x:Class="CosmosClone.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CosmosClone"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Label Content="Cosmic Clone" HorizontalAlignment="Left" Margin="248,53,0,0" VerticalAlignment="Top" Width="236" FontSize="24"/>
</Grid>
</Window>

Просмотреть файл

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace CosmosClone
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}

Просмотреть файл

@ -0,0 +1,55 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// 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("CosmosClone")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CosmosClone")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[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)]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
// 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")]

71
CosmosClone/CosmosClone/Properties/Resources.Designer.cs сгенерированный Normal file
Просмотреть файл

@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace CosmosClone.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CosmosClone.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

Просмотреть файл

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

30
CosmosClone/CosmosClone/Properties/Settings.Designer.cs сгенерированный Normal file
Просмотреть файл

@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace CosmosClone.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

Просмотреть файл

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

Просмотреть файл

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{523E1CC4-0286-498C-B184-3413E10D61DE}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CosmosCloneCommon</RootNamespace>
<AssemblyName>CosmosCloneCommon</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</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.Azure.CosmosDB.BulkImport, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Azure.CosmosDB.BulkExecutor.1.2.0\lib\net451\Microsoft.Azure.CosmosDB.BulkImport.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Azure.Documents.Client, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Azure.DocumentDB.2.1.3\lib\net461\Microsoft.Azure.Documents.Client.dll</HintPath>
</Reference>
<Reference Include="MongoDB.Bson, Version=2.4.4.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MongoDB.Bson.2.4.4\lib\net45\MongoDB.Bson.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Memory, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.0\lib\netstandard2.0\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.WinHttpHandler, Version=4.0.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Net.Http.WinHttpHandler.4.5.0\lib\net461\System.Net.Http.WinHttpHandler.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Migrator\CodeMigrator.cs" />
<Compile Include="Migrator\DataScrubMigrator.cs" />
<Compile Include="Migrator\DocumentMigrator.cs" />
<Compile Include="Model\RandomNumberGenerator.cs" />
<Compile Include="Model\ScrubRule.cs" />
<Compile Include="Model\Validationresult.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Sample\EntityV2.cs" />
<Compile Include="Sample\Entity.cs" />
<Compile Include="Sample\SampleDBCreator.cs" />
<Compile Include="Utility\CloneLogger.cs" />
<Compile Include="Utility\CloneSerializer.cs" />
<Compile Include="Utility\CloneSettings.cs" />
<Compile Include="Utility\CosmosBulkImporter.cs" />
<Compile Include="Utility\CosmosDBHelper.cs" />
<Compile Include="Utility\ObjectScrubber.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config">
<SubType>Designer</SubType>
</None>
<None Include="packages.config">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Microsoft.Azure.DocumentDB.2.1.3\build\Microsoft.Azure.DocumentDB.targets" Condition="Exists('..\packages\Microsoft.Azure.DocumentDB.2.1.3\build\Microsoft.Azure.DocumentDB.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Microsoft.Azure.DocumentDB.2.1.3\build\Microsoft.Azure.DocumentDB.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Azure.DocumentDB.2.1.3\build\Microsoft.Azure.DocumentDB.targets'))" />
</Target>
</Project>

Просмотреть файл

@ -0,0 +1,209 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using logger = CosmosCloneCommon.Utility.CloneLogger;
using CosmosCloneCommon.Utility;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
namespace CosmosCloneCommon.Migrator
{
public class CodeMigrator
{
#region declare variables
private CosmosDBHelper cosmosHelper;
private CosmosBulkImporter cosmosBulkImporter;
protected DocumentClient sourceClient;
protected DocumentClient targetClient;
protected DocumentCollection sourceCollection;
protected DocumentCollection targetCollection;
private string SourceEndpointUrl;
private string SourceAccessKey;
private string sourceDatabaseName;
private string sourceCollectionName;
private string TargetEndpointUrl;
private string TargetAccessKey;
private string TargetDatabaseName;
private string TargetCollectionName;
//private EntitySummary summary;
#endregion
public CodeMigrator()
{
//initialize settings and other utilities
var SourceCosmosDBSettings = CloneSettings.GetConfigurationSection("SourceCosmosDBSettings");
SourceEndpointUrl = CloneSettings.SourceSettings.EndpointUrl; ;
SourceAccessKey = CloneSettings.SourceSettings.AccessKey;
sourceDatabaseName = CloneSettings.SourceSettings.DatabaseName;
sourceCollectionName = CloneSettings.SourceSettings.CollectionName;
//var TargetCosmosDBSettings = CloneSettings.GetConfigurationSection("TargetCosmosDBSettings");
TargetEndpointUrl = CloneSettings.TargetSettings.EndpointUrl;
TargetAccessKey = CloneSettings.TargetSettings.AccessKey;
TargetDatabaseName = CloneSettings.TargetSettings.DatabaseName;
TargetCollectionName = CloneSettings.TargetSettings.CollectionName;
cosmosHelper = new CosmosDBHelper();
cosmosBulkImporter = new CosmosBulkImporter();
//summary = new EntitySummary();
//summary.EntityType = "DBCode";
}
private async Task Initialize()
{
logger.LogInfo("-----------------------------------------------");
logger.LogInfo("Begin CosmosDBCodeMigrator");
sourceClient = cosmosHelper.GetSourceDocumentDbClient();
sourceCollection = await cosmosHelper.GetSourceDocumentCollection(sourceClient);
targetClient = cosmosHelper.GetTargetDocumentDbClient();
targetCollection = await cosmosHelper.CreateTargetDocumentCollection(targetClient, sourceCollection.IndexingPolicy, sourceCollection.PartitionKey);
}
public async Task<bool> StartCopy()
{
await Initialize();
if (CloneSettings.CopyStoredProcedures) { await CopyStoredProcedures(); }
if (CloneSettings.CopyUDFs) { await CopyUDFs(); }
if (CloneSettings.CopyTriggers) { await CopyTriggers(); }
//summary.isMigrationComplete = true;
logger.LogInfo("CosmosDBCodeMigrator End");
logger.LogInfo("-----------------------------------------------");
//return summary;
return true;
}
private async Task CopyTriggers()
{
try
{
logger.LogInfo("-----------------------------------------------");
logger.LogInfo("Begin CopyTriggers");
FeedOptions feedOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = true };
var requestOptions = new RequestOptions { OfferEnableRUPerMinuteThroughput = true };
var triggerFeedResponse = await sourceClient.ReadTriggerFeedAsync(UriFactory.CreateDocumentCollectionUri(sourceDatabaseName, sourceCollectionName), feedOptions);
var triggerList = triggerFeedResponse.ToList();
logger.LogInfo($"Triggers retrieved from source {triggerList.Count}");
//summary.totalRecordsRetrieved += triggerList.Count;
var targetResponse = await targetClient.ReadTriggerFeedAsync(UriFactory.CreateDocumentCollectionUri(TargetDatabaseName, TargetCollectionName), feedOptions);
var targetTriggerList = targetResponse.ToList();
logger.LogInfo($"Triggers already in target {targetTriggerList.Count}");
var targetTriggerIds = new HashSet<string>();
targetTriggerList.ForEach(sp => targetTriggerIds.Add(sp.Id));
foreach (var trigger in triggerList)
{
if (targetTriggerIds.Contains(trigger.Id))
{
logger.LogInfo($"Trigger {trigger.Id} already Exists in destination DB");
continue;
}
logger.LogInfo($"Create Trigger {trigger.Id} start");
await targetClient.CreateTriggerAsync(UriFactory.CreateDocumentCollectionUri(TargetDatabaseName, TargetCollectionName), trigger, requestOptions);
logger.LogInfo($"Create Trigger {trigger.Id} complete");
//summary.totalRecordsSent++;
}
logger.LogInfo("Copy Triggers end.");
logger.LogInfo("");
}
catch (Exception ex)
{
logger.LogInfo("Exception while CopyTriggers");
logger.LogError(ex);
}
}
private async Task CopyUDFs()
{
try
{
logger.LogInfo("-----------------------------------------------");
logger.LogInfo("Begin CopyUDFs");
FeedOptions feedOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = true };
var udfFeedResponse = await sourceClient.ReadUserDefinedFunctionFeedAsync(UriFactory.CreateDocumentCollectionUri(sourceDatabaseName, sourceCollectionName), feedOptions);
var udfList = udfFeedResponse.ToList<UserDefinedFunction>();
logger.LogInfo($"UDFs retrieved from source {udfList.Count}");
//summary.totalRecordsRetrieved += udfList.Count;
var targetResponse = await targetClient.ReadUserDefinedFunctionFeedAsync(UriFactory.CreateDocumentCollectionUri(TargetDatabaseName, TargetCollectionName), feedOptions);
var targetUdfList = targetResponse.ToList();
logger.LogInfo($"Triggers already in target {targetUdfList.Count}");
var targetUDFIds = new HashSet<string>();
targetUdfList.ForEach(sp => targetUDFIds.Add(sp.Id));
var requestOptions = new RequestOptions { OfferEnableRUPerMinuteThroughput = true };
foreach (var udf in udfList)
{
if (targetUDFIds.Contains(udf.Id))
{
logger.LogInfo($"UDF {udf.Id} already Exists in destination DB");
continue;
}
logger.LogInfo($"Create Trigger {udf.Id} start");
await targetClient.CreateUserDefinedFunctionAsync(UriFactory.CreateDocumentCollectionUri(TargetDatabaseName, TargetCollectionName), udf, requestOptions);
logger.LogInfo($"Create Trigger {udf.Id} complete");
//summary.totalRecordsSent++;
}
logger.LogInfo("CopyUDFs end.");
logger.LogInfo("");
}
catch (Exception ex)
{
logger.LogInfo("Exception while CopyUDFs");
logger.LogError(ex);
}
}
private async Task CopyStoredProcedures()
{
try
{
logger.LogInfo("-----------------------------------------------");
logger.LogInfo("Begin CopyStoredProcedures");
FeedOptions feedOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = true };
var requestOptions = new RequestOptions { OfferEnableRUPerMinuteThroughput = true };
var sourceResponse = await sourceClient.ReadStoredProcedureFeedAsync(UriFactory.CreateDocumentCollectionUri(sourceDatabaseName, sourceCollectionName), feedOptions);
var splist = sourceResponse.ToList<StoredProcedure>();
logger.LogInfo($"StoredProcedures retrieved from source {splist.Count}");
//summary.totalRecordsRetrieved += splist.Count;
var targetResponse = await targetClient.ReadStoredProcedureFeedAsync(UriFactory.CreateDocumentCollectionUri(TargetDatabaseName, TargetCollectionName), feedOptions);
var targetSPList = targetResponse.ToList();
logger.LogInfo($"StoredProcedures already retrieved in target {targetSPList.Count}");
var targetSPIds = new HashSet<string>();
targetSPList.ForEach(sp => targetSPIds.Add(sp.Id));
foreach (var sp in splist)
{
if (targetSPIds.Contains(sp.Id))
{
logger.LogInfo($"StoredProcedure {sp.Id} already Exists in destination DB");
continue;
}
logger.LogInfo($"Create StoredProcedure {sp.Id} start");
await targetClient.CreateStoredProcedureAsync(UriFactory.CreateDocumentCollectionUri(TargetDatabaseName, TargetCollectionName), sp, requestOptions);
logger.LogInfo($"Create StoredProcedure {sp.Id} complete");
//summary.totalRecordsSent++;
}
logger.LogInfo("CopyStoredProcedures end.");
}
catch (Exception ex)
{
logger.LogInfo("Exception while CopyStoredProcedures");
logger.LogError(ex);
logger.LogInfo("");
}
}
}
}

Просмотреть файл

@ -0,0 +1,176 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using System.Diagnostics;
using Microsoft.Azure.CosmosDB.BulkExecutor.BulkImport;
using Microsoft.Azure.Documents.Linq;
using CosmosCloneCommon.Utility;
using CosmosCloneCommon.Model;
using logger = CosmosCloneCommon.Utility.CloneLogger;
using Newtonsoft.Json.Linq;
namespace CosmosCloneCommon.Migrator
{
public class DataScrubMigrator
{
#region declare variables
protected int ReadDelaybetweenRequestsInMs = 2000;
protected CosmosDBHelper cosmosHelper;
protected CosmosBulkImporter cosmosBulkImporter;
protected DocumentClient targetClient;
protected DocumentCollection targetCollection;
//protected ScrubRule scrubRule;
protected IQueryable<string> ScrubDataFetchQuery;
public static List<ScrubRule> scrubRules;
public long TotalRecordsRetrieved { get; set; }
public long TotalRecordsScrubbed { get; set; }
public long TotalRecordsToScrub { get; set; }
#endregion
public DataScrubMigrator()
{
cosmosHelper = new CosmosDBHelper();
cosmosBulkImporter = new CosmosBulkImporter();
}
public async Task<bool> StartScrub(List<ScrubRule> scrubRules)
{
DataScrubMigrator.scrubRules = scrubRules;
if (!CloneSettings.ScrubbingRequired)
{
logger.LogInfo("No Scrubbing required");
return false;
}
await InitializeMigration();
//group by filtered Rules
var distinctFilters = scrubRules.Select(o => o.FilterCondition).Distinct();
//get distinct filterConditions
//foreach filterCondition obtain set of rules and send at once
foreach (var filterCondition in distinctFilters)
{
logger.LogInfo($"Initialize process for scrub rule on filter {filterCondition}");
var sRules = scrubRules.Where(o => o.FilterCondition.Equals(filterCondition)).ToList();
logger.LogInfo($"Scrub rules found {sRules.Count}");
ScrubDataFetchQuery = cosmosHelper.GetScrubDataDocumentQuery<string>(targetClient, filterCondition, CloneSettings.ReadBatchSize);
await ReadUploadInbatches((IDocumentQuery<string>)ScrubDataFetchQuery, sRules);
foreach(var srule in DataScrubMigrator.scrubRules)
{
if(srule.FilterCondition.Equals(filterCondition))
{
srule.IsComplete = true;
}
}
}
return true;
}
public async Task InitializeMigration()
{
logger.LogInfo("Initialize data scrubbing");
targetClient = cosmosHelper.GetTargetDocumentDbClient();
targetCollection = await cosmosHelper.GetTargetDocumentCollection(targetClient);
await cosmosBulkImporter.InitializeBulkExecutor(targetClient, targetCollection);
}
public async Task ReadUploadInbatches(IDocumentQuery<string> query, List<ScrubRule> scrubRules)
{
#region batchVariables
//initialize Batch Process variables
int batchCount = 0;
TotalRecordsRetrieved = 0;
TotalRecordsScrubbed = 0;
var badEntities = new List<Object>();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var objScrubber = new ObjectScrubber();
#endregion
while (query.HasMoreResults)
{
batchCount++;
logger.LogInfo($"BatchNumber : {batchCount} begins ");
List<string> entities = await GetCommonStringEntitiesinBatch(query);
TotalRecordsRetrieved += entities.Count();
BulkImportResponse uploadResponse = new BulkImportResponse();
var scrubbedEntities = entities;
if (entities.Any())
{
var jEntities = new List<JToken>();
foreach (var scrubRule in scrubRules)
{
jEntities = objScrubber.ScrubObjectList(scrubbedEntities, scrubRule);
var nentities = new List<string>();
foreach (var jobj in jEntities)
{
nentities.Add(JsonConvert.SerializeObject(jobj));
}
scrubbedEntities = nentities;
}
var objEntities = jEntities.Cast<Object>().ToList();
try
{
uploadResponse = await cosmosBulkImporter.BulkSendToNewCollection<dynamic>(objEntities);
}
catch(Exception ex)
{
logger.LogError(ex);
throw (ex);
}
}
badEntities = uploadResponse.BadInputDocuments;
TotalRecordsScrubbed += uploadResponse.NumberOfDocumentsImported;
logger.LogInfo($"Summary of Batch {batchCount} records retrieved {entities.Count()}. Records Uploaded: {uploadResponse.NumberOfDocumentsImported}");
logger.LogInfo($"Total records retrieved {TotalRecordsRetrieved}. Total records uploaded {TotalRecordsScrubbed}");
logger.LogInfo($"Time elapsed : {stopwatch.Elapsed} ");
}
stopwatch.Stop();
logger.LogInfo("Document Scrubbing completed");
}
protected async Task<List<string>> GetCommonStringEntitiesinBatch(IDocumentQuery<string> query)
{
List<string> entities = new List<string>();
List<object> objEntities = new List<object>();
int attempts = 0;
try
{
while (query.HasMoreResults && objEntities.Count < CloneSettings.WriteBatchSize)
{
attempts++;
var prevRecordCount = entities.Count;
var res = await query.ExecuteNextAsync();
objEntities.AddRange((IEnumerable<object>)res);
logger.LogInfo($"Records retrieved from source: {objEntities.Count - prevRecordCount}");
}
foreach(var obj in objEntities)
{
entities.Add(JsonConvert.SerializeObject(obj));
}
logger.LogInfo($"Total Records retrieved from Source {entities.Count}");
return entities;
}
catch (Exception ex)
{
logger.LogInfo("Exception while fetching Entities from source. Will Increase delay time and continue");
logger.LogError(ex);
ReadDelaybetweenRequestsInMs += 2000;
System.Threading.Thread.Sleep(ReadDelaybetweenRequestsInMs);
return entities;
}
}
}
}

Просмотреть файл

@ -0,0 +1,398 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using System.Diagnostics;
using Microsoft.Azure.CosmosDB.BulkExecutor;
using Microsoft.Azure.CosmosDB.BulkExecutor.BulkImport;
using Microsoft.Azure.Documents.Linq;
using CosmosCloneCommon.Utility;
using CosmosCloneCommon.Model;
using Newtonsoft.Json;
using logger = CosmosCloneCommon.Utility.CloneLogger;
using Newtonsoft.Json.Linq;
namespace CosmosCloneCommon.Migrator
{
public class DocumentMigrator
{
#region declare variables
protected int ReadDelaybetweenRequestsInMs = 2000;
protected CosmosDBHelper cosmosHelper;
protected CosmosBulkImporter cosmosBulkImporter;
protected DocumentClient sourceClient;
protected DocumentClient targetClient;
protected DocumentCollection sourceCollection;
protected DocumentCollection targetCollection;
protected ObjectScrubber objectScrubber;
//protected static List<ScrubRule> scrubRules;
protected List<ScrubRule> noFilterScrubRules;
protected List<ScrubRule> filteredScrubRules;
protected IQueryable<dynamic> SourceCommonDataFetchQuery;
public static List<ScrubRule> scrubRules;
public static long TotalRecordsRetrieved { get; set; }
public static long TotalRecordsSent { get; set; }
public static long TotalRecordsInSource { get; set; }
public static bool IsCodeMigrationComplete { get; set; }
public static int ScrubPercentProgress
{
get
{
if (scrubRules != null && scrubRules.Count > 0)
{
int totalRules = scrubRules.Count();
int noFilterRuleCompleteCount = scrubRules.Where(x => x.IsComplete == true && string.IsNullOrEmpty(x.FilterCondition) ).ToList().Count();
int filterRuleCompleteCount = 0;
if(DataScrubMigrator.scrubRules!=null && DataScrubMigrator.scrubRules.Count>0)
{
filterRuleCompleteCount = DataScrubMigrator.scrubRules.Where(x => x.IsComplete == true).ToList().Count();
}
var completedRules = scrubRules.Where(x => x.IsComplete == true).ToList().Count();
int percent = (int)((noFilterRuleCompleteCount + filterRuleCompleteCount) * 100 / scrubRules.Count());
return percent;
}
else return 100;
}
}
#endregion
public DocumentMigrator()
{
cosmosHelper = new CosmosDBHelper();
cosmosBulkImporter = new CosmosBulkImporter();
objectScrubber = new ObjectScrubber();
}
public async Task<bool> StartCopy(List<ScrubRule> scrubRules = null)
{
DocumentMigrator.scrubRules = scrubRules;
await InitializeMigration();
if (CloneSettings.CopyDocuments)
{
await ReadUploadInbatches((IDocumentQuery<dynamic>)SourceCommonDataFetchQuery);
}
IsCodeMigrationComplete = false;
if (CloneSettings.CopyStoredProcedures) { await CopyStoredProcedures(); }
if (CloneSettings.CopyUDFs) { await CopyUDFs(); }
if (CloneSettings.CopyTriggers) { await CopyTriggers(); }
IsCodeMigrationComplete = true;
if (CloneSettings.ScrubbingRequired && filteredScrubRules != null && filteredScrubRules.Count > 0)
{
var dcs = new DataScrubMigrator();
var result = dcs.StartScrub(filteredScrubRules);
}
return true;
}
public async Task InitializeMigration()
{
logger.LogInfo("Begin Document Migration.");
logger.LogInfo($"Source Database: {CloneSettings.SourceSettings.DatabaseName} Source Collection: {CloneSettings.SourceSettings.CollectionName}");
logger.LogInfo($"Target Database: {CloneSettings.TargetSettings.DatabaseName} Target Collection: {CloneSettings.TargetSettings.CollectionName}");
sourceClient = cosmosHelper.GetSourceDocumentDbClient();
sourceCollection = await cosmosHelper.GetSourceDocumentCollection(sourceClient);
targetClient = cosmosHelper.GetTargetDocumentDbClient();
var indexPolicy = (CloneSettings.CopyIndexingPolicy)? sourceCollection.IndexingPolicy : new IndexingPolicy();
targetCollection = await cosmosHelper.CreateTargetDocumentCollection(targetClient, indexPolicy, sourceCollection.PartitionKey);
if (CloneSettings.CopyDocuments)
{
TotalRecordsInSource = cosmosHelper.GetSourceRecordCount();
logger.LogInfo($"Total records in Source: {TotalRecordsInSource} ");
SourceCommonDataFetchQuery = cosmosHelper.GetSourceEntityDocumentQuery<dynamic>(sourceClient, CloneSettings.ReadBatchSize);
await cosmosBulkImporter.InitializeBulkExecutor(targetClient, targetCollection);
}
else
{
logger.LogInfo("Document Migration is disabled through configuration. ");
}
if (CloneSettings.ScrubbingRequired && scrubRules != null && scrubRules.Count > 0)
{
noFilterScrubRules = new List<ScrubRule>();
filteredScrubRules = new List<ScrubRule>();
foreach (var sRule in scrubRules)
{
if(string.IsNullOrEmpty(sRule.FilterCondition))
{
noFilterScrubRules.Add(sRule);
}
else
{
filteredScrubRules.Add(sRule);
//DataScrubMigrator.scrubRules.Add(sRule);
}
}
}
}
public async Task ReadUploadInbatches(IDocumentQuery<dynamic> query)
{
#region batchVariables
//initialize Batch Process variables
int batchCount = 0;
TotalRecordsRetrieved = 0;
TotalRecordsSent = 0;
var badEntities = new List<Object>();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
#endregion
while (query.HasMoreResults)
{
batchCount++;
logger.LogInfo($"BatchNumber : {batchCount} begins ");
List<dynamic> entities = await GetCommonEntitiesinBatch(query);
TotalRecordsRetrieved += entities.Count();
List<object> objEntities = new List<object>();
objEntities.AddRange((IEnumerable<object>)entities);
List<string> strEntities = new List<string>();
foreach (var obj in objEntities)
{
strEntities.Add(JsonConvert.SerializeObject(obj));
}
BulkImportResponse uploadResponse = new BulkImportResponse();
var scrubbedEntities = strEntities;
if (entities.Any())
{
if( noFilterScrubRules == null || noFilterScrubRules.Count==0)
{
uploadResponse = await cosmosBulkImporter.BulkSendToNewCollection<dynamic>(entities);
}
else
{
var jEntities = new List<JToken>();
foreach (var sRule in noFilterScrubRules)
{
jEntities = objectScrubber.ScrubObjectList(scrubbedEntities, sRule);
var nentities = new List<string>();
foreach (var jobj in jEntities)
{
nentities.Add(JsonConvert.SerializeObject(jobj));
}
scrubbedEntities = nentities;
}
var objDocuments = jEntities.Cast<Object>().ToList();
uploadResponse = await cosmosBulkImporter.BulkSendToNewCollection<dynamic>(objDocuments);
}
}
else
{
logger.LogInfo("No Entities retrieved from query");
continue;
}
badEntities = uploadResponse.BadInputDocuments;
TotalRecordsSent += uploadResponse.NumberOfDocumentsImported;
logger.LogInfo($"Summary of Batch {batchCount} records retrieved {entities.Count()}. Records Uploaded: {uploadResponse.NumberOfDocumentsImported}");
logger.LogInfo($"Total records retrieved {TotalRecordsRetrieved}. Total records uploaded {TotalRecordsSent}");
logger.LogInfo($"Time elapsed : {stopwatch.Elapsed} ");
}
setCompleteOnNoFilterRules();
stopwatch.Stop();
logger.LogInfo("Document Migration completed");
}
public async Task TestOffers()
{
//sourceClient = cosmosHelper.GetSourceDocumentDbClient();
//sourceCollection = await cosmosHelper.GetSourceDocumentCollection(sourceClient);
var setCorrect = await cosmosHelper.SetTargetRestOfferThroughPut();
}
public bool setCompleteOnNoFilterRules()
{
if (scrubRules != null && scrubRules.Count > 0)
{
foreach (var sRule in scrubRules)
{
if (string.IsNullOrEmpty(sRule.FilterCondition))
{
sRule.IsComplete = true;
}
}
}
if (this.noFilterScrubRules != null && this.noFilterScrubRules.Count > 0)
{
foreach (var sRule in this.noFilterScrubRules)
{
if (string.IsNullOrEmpty(sRule.FilterCondition))
{
sRule.IsComplete = true;
}
}
}
return true;
}
protected async Task<List<dynamic>> GetCommonEntitiesinBatch(IDocumentQuery<dynamic> query)
{
List<dynamic> entities = new List<dynamic>();
int attempts = 0;
try
{
while (query.HasMoreResults && entities.Count < CloneSettings.WriteBatchSize)
{
attempts++;
var prevRecordCount = entities.Count;
var res = await query.ExecuteNextAsync();
entities.AddRange((IEnumerable<dynamic>)res);
logger.LogInfo($"Records retrieved from source: {entities.Count - prevRecordCount}");
}
logger.LogInfo($"Total Records retrieved from Source {entities.Count}");
return entities;
}
catch (Exception ex)
{
logger.LogInfo("Exception while fetching Entities from source. Will Increase delay time and continue");
logger.LogError(ex);
ReadDelaybetweenRequestsInMs += 2000;//increased delay
System.Threading.Thread.Sleep(ReadDelaybetweenRequestsInMs);
return entities;
}
}
private async Task CopyTriggers()
{
try
{
logger.LogInfo("-----------------------------------------------");
logger.LogInfo("Begin CopyTriggers");
FeedOptions feedOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = true };
var requestOptions = new RequestOptions { OfferEnableRUPerMinuteThroughput = true };
var triggerFeedResponse = await sourceClient.ReadTriggerFeedAsync(UriFactory.CreateDocumentCollectionUri(CloneSettings.SourceSettings.DatabaseName, CloneSettings.SourceSettings.CollectionName), feedOptions);
var triggerList = triggerFeedResponse.ToList();
logger.LogInfo($"Triggers retrieved from source {triggerList.Count}");
//summary.totalRecordsRetrieved += triggerList.Count;
var targetResponse = await targetClient.ReadTriggerFeedAsync(UriFactory.CreateDocumentCollectionUri(CloneSettings.TargetSettings.DatabaseName, CloneSettings.TargetSettings.CollectionName), feedOptions);
var targetTriggerList = targetResponse.ToList();
logger.LogInfo($"Triggers already in target {targetTriggerList.Count}");
var targetTriggerIds = new HashSet<string>();
targetTriggerList.ForEach(sp => targetTriggerIds.Add(sp.Id));
foreach (var trigger in triggerList)
{
if (targetTriggerIds.Contains(trigger.Id))
{
logger.LogInfo($"Trigger {trigger.Id} already Exists in destination DB");
continue;
}
logger.LogInfo($"Create Trigger {trigger.Id} start");
await targetClient.CreateTriggerAsync(UriFactory.CreateDocumentCollectionUri(CloneSettings.TargetSettings.DatabaseName, CloneSettings.TargetSettings.CollectionName), trigger, requestOptions);
logger.LogInfo($"Create Trigger {trigger.Id} complete");
//summary.totalRecordsSent++;
}
logger.LogInfo("Copy Triggers end.");
logger.LogInfo("");
}
catch (Exception ex)
{
logger.LogInfo("Exception while CopyTriggers");
logger.LogError(ex);
}
}
private async Task CopyUDFs()
{
try
{
logger.LogInfo("-----------------------------------------------");
logger.LogInfo("Begin CopyUDFs");
FeedOptions feedOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = true };
var udfFeedResponse = await sourceClient.ReadUserDefinedFunctionFeedAsync(UriFactory.CreateDocumentCollectionUri(CloneSettings.SourceSettings.DatabaseName, CloneSettings.SourceSettings.CollectionName), feedOptions);
var udfList = udfFeedResponse.ToList<UserDefinedFunction>();
logger.LogInfo($"UDFs retrieved from source {udfList.Count}");
//summary.totalRecordsRetrieved += udfList.Count;
var targetResponse = await targetClient.ReadUserDefinedFunctionFeedAsync(UriFactory.CreateDocumentCollectionUri(CloneSettings.TargetSettings.DatabaseName, CloneSettings.TargetSettings.CollectionName), feedOptions);
var targetUdfList = targetResponse.ToList();
logger.LogInfo($"Triggers already in target {targetUdfList.Count}");
var targetUDFIds = new HashSet<string>();
targetUdfList.ForEach(sp => targetUDFIds.Add(sp.Id));
var requestOptions = new RequestOptions { OfferEnableRUPerMinuteThroughput = true };
foreach (var udf in udfList)
{
if (targetUDFIds.Contains(udf.Id))
{
logger.LogInfo($"UDF {udf.Id} already Exists in destination DB");
continue;
}
logger.LogInfo($"Create Trigger {udf.Id} start");
await targetClient.CreateUserDefinedFunctionAsync(UriFactory.CreateDocumentCollectionUri(CloneSettings.TargetSettings.DatabaseName, CloneSettings.TargetSettings.CollectionName), udf, requestOptions);
logger.LogInfo($"Create Trigger {udf.Id} complete");
//summary.totalRecordsSent++;
}
logger.LogInfo("CopyUDFs end.");
logger.LogInfo("");
}
catch (Exception ex)
{
logger.LogInfo("Exception while CopyUDFs");
logger.LogError(ex);
}
}
private async Task CopyStoredProcedures()
{
try
{
logger.LogInfo("-----------------------------------------------");
logger.LogInfo("Begin CopyStoredProcedures");
FeedOptions feedOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = true };
var requestOptions = new RequestOptions { OfferEnableRUPerMinuteThroughput = true };
var sourceResponse = await sourceClient.ReadStoredProcedureFeedAsync(UriFactory.CreateDocumentCollectionUri(CloneSettings.SourceSettings.DatabaseName, CloneSettings.SourceSettings.CollectionName), feedOptions);
var splist = sourceResponse.ToList<StoredProcedure>();
logger.LogInfo($"StoredProcedures retrieved from source {splist.Count}");
//summary.totalRecordsRetrieved += splist.Count;
var targetResponse = await targetClient.ReadStoredProcedureFeedAsync(UriFactory.CreateDocumentCollectionUri(CloneSettings.TargetSettings.DatabaseName, CloneSettings.TargetSettings.CollectionName), feedOptions);
var targetSPList = targetResponse.ToList();
logger.LogInfo($"StoredProcedures already retrieved in target {targetSPList.Count}");
var targetSPIds = new HashSet<string>();
targetSPList.ForEach(sp => targetSPIds.Add(sp.Id));
foreach (var sp in splist)
{
if (targetSPIds.Contains(sp.Id))
{
logger.LogInfo($"StoredProcedure {sp.Id} already Exists in destination DB");
continue;
}
logger.LogInfo($"Create StoredProcedure {sp.Id} start");
await targetClient.CreateStoredProcedureAsync(UriFactory.CreateDocumentCollectionUri(CloneSettings.TargetSettings.DatabaseName, CloneSettings.TargetSettings.CollectionName), sp, requestOptions);
logger.LogInfo($"Create StoredProcedure {sp.Id} complete");
//summary.totalRecordsSent++;
}
logger.LogInfo("CopyStoredProcedures end.");
}
catch (Exception ex)
{
logger.LogInfo("Exception while CopyStoredProcedures");
logger.LogError(ex);
logger.LogInfo("");
}
}
}
}

Просмотреть файл

@ -0,0 +1,68 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace CosmosCloneCommon.Model
{
public static class RandomNumberGenerator
{
private static Random _random;
static RandomNumberGenerator()
{
_random = new Random(unchecked(Environment.TickCount * 31 + Thread.CurrentThread.ManagedThreadId));
_random.Next();
}
public static int getNext(int maxValue)
{
_random.Next();
_random.Next(0, maxValue);
return _random.Next(0,maxValue);
}
public static int getNext()
{
return _random.Next(1, 99999999);
}
public static string GetRandomEntityType()
{
string returnvalue;
switch (RandomNumberGenerator.getNext() % 5)
{
case 1:
returnvalue = "Individual"; break;
case 2:
returnvalue = "Organization"; break;
case 3:
returnvalue = "Supplier"; break;
case 4:
returnvalue = "Partner"; break;
case 0:
returnvalue = "External"; break;
default:
returnvalue = "External"; break;
}
return returnvalue;
}
//A simple implementation of Fisher yates algorithm for shuffling
public static List<T> Shuffle<T>(List<T> list)
{
int n = list.Count-1;
while (n > 1)
{
n--;
int k = RandomNumberGenerator.getNext(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
return list;
}
}
}

Просмотреть файл

@ -0,0 +1,42 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CosmosCloneCommon.Model
{
public class ScrubRule
{
public int RuleId { get; set; }
public string FilterCondition { get; set; }
public string PropertyName { get; set; }
public string UpdateValue { get; set; }
public RuleType? Type { get; set; }
private int RecordsByFilter { get; set; }
private int RecordsUpdated { get; set; }
private int CountNullAttributes { get; set; }
public bool IsComplete { get; set; }
public ScrubRule() { }
public ScrubRule(string filterCondition, string propertyName, RuleType type, string updateValue, int ruleId)
{
this.FilterCondition = filterCondition;
this.PropertyName = propertyName;
this.UpdateValue = updateValue;
this.Type = type;
this.RuleId = ruleId;
this.IsComplete = false;
}
}
public enum RuleType { SingleValue, NullValue, Shuffle };//Can add random later if required.
}

Просмотреть файл

@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CosmosCloneCommon.Model
{
public class ValidationResult
{
public string Message { get; set; }
public bool IsSuccess { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,36 @@
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("CosmosCloneCommon")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CosmosCloneCommon")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[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("523e1cc4-0286-498c-b184-3413e10d61de")]
// 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,112 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using CosmosCloneCommon.Model;
namespace CosmosCloneCommon.Sample
{
public class Entity
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public Boolean IsActive { get; set; }
public DateTime ModifiedTime { get; set; }
public List<EntityKey> BaseKeys { get; set; }
public static Entity getRandomEntity()
{
var entity = new Entity();
entity.Id = RandomNumberGenerator.getNext();
entity.Name = "Test Sample Name " + entity.Id.ToString();
entity.Description = "Test Sample Description " + entity.Id.ToString();
entity.IsActive = true;
entity.ModifiedTime = DateTime.UtcNow;
entity.BaseKeys = new List<EntityKey>();
entity.BaseKeys.Add(EntityKey.getRandomEntityKey());
entity.BaseKeys.Add(EntityKey.getRandomEntityKey());
entity.BaseKeys.Add(EntityKey.getRandomEntityKey());
entity.BaseKeys.Add(EntityKey.getRandomEntityKey());
entity.BaseKeys.Add(EntityKey.getRandomEntityKey());
return entity;
}
}
public class CompositeEntity
{
public string id { get; set; }
public string _etag { get; set; }
public string CompositeName { get; set; }
public string EmployeeId { get; set; }
public string EmailAddress { get; set; }
public string EntityType { get; set; }
public Entity EntityValue { get; set; }
public List<EntityKey> SuperKeys { get; set; }
public static CompositeEntity getRandomCompositeEntity()
{
var compositeEntity = new CompositeEntity();
compositeEntity.id = Guid.NewGuid().ToString();
compositeEntity.EmployeeId = RandomNumberGenerator.getNext().ToString();
compositeEntity.EntityType = RandomNumberGenerator.GetRandomEntityType();
compositeEntity.CompositeName = "Test Sample CompositeName " + RandomNumberGenerator.getNext();
compositeEntity.EmailAddress = "test" + RandomNumberGenerator.getNext() + "@microsoft.com";
compositeEntity.EntityValue = Entity.getRandomEntity();
compositeEntity.SuperKeys = new List<EntityKey>();
compositeEntity.SuperKeys.Add(EntityKey.getRandomEntityKey());
compositeEntity.SuperKeys.Add(EntityKey.getRandomEntityKey());
compositeEntity.SuperKeys.Add(EntityKey.getRandomEntityKey());
compositeEntity.SuperKeys.Add(EntityKey.getRandomEntityKey());
compositeEntity.SuperKeys.Add(EntityKey.getRandomEntityKey());
return compositeEntity;
}
}
public class EntityKey
{
public string KeyName { get; set; }
public string KeyValue { get; set; }
public string KeyId { get; set; }
public static EntityKey getRandomEntityKey()
{
var entityKey = new EntityKey();
entityKey.KeyId = RandomNumberGenerator.getNext().ToString();
entityKey.KeyName = "TestKeyName-" + entityKey.KeyId.ToString();
entityKey.KeyValue = "TestKeyValue-" + entityKey.KeyId.ToString();
return entityKey;
}
}
public class Entitytest
{
public Entity EntityValue { get; set; }
public List<string> Words { get; set; }
public static Entitytest getRandomTestEntity()
{
var testEntity = new Entitytest();
testEntity.EntityValue = Entity.getRandomEntity();
testEntity.Words = new List<string>();
testEntity.Words.Add("test123");
testEntity.Words.Add("value123");
testEntity.Words.Add("rex123");
return testEntity;
}
}
}

Просмотреть файл

@ -0,0 +1,57 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using CosmosCloneCommon.Model;
namespace CosmosCloneCommon.Sample
{
public class EntityV2
{
public string FullName { get; set; }
public string Description { get; set; }
public Boolean IsActive { get; set; }
public DateTime ModifiedTime { get; set; }
public string EmployeeId { get; set; }
public string EmailAddress { get; set; }
public string PhoneNumber { get; set; }
public List<EntityKey> BaseKeys { get; set; }
public string _etag { get; set; }
public int SuperId { get; set; }
public string id { get; set; }
public string EntityType { get; set; }
public static EntityV2 getRandomEntity()
{
var entity = new EntityV2();
entity.SuperId = RandomNumberGenerator.getNext();
entity.id = Guid.NewGuid().ToString();
entity.FullName = "Test Sample Name " + entity.SuperId.ToString();
entity.Description = "Test Sample Description " + entity.SuperId.ToString();
entity.EntityType = RandomNumberGenerator.GetRandomEntityType();
var employeeid = RandomNumberGenerator.getNext();
entity.EmailAddress = "intialTest"+ employeeid .ToString()+ "@test.com";
entity.PhoneNumber = RandomNumberGenerator.getNext().ToString();
entity.IsActive = true;
entity.ModifiedTime = DateTime.UtcNow;
entity.BaseKeys = new List<EntityKey>();
entity.BaseKeys.Add(EntityKey.getRandomEntityKey());
entity.BaseKeys.Add(EntityKey.getRandomEntityKey());
entity.BaseKeys.Add(EntityKey.getRandomEntityKey());
entity.BaseKeys.Add(EntityKey.getRandomEntityKey());
entity.BaseKeys.Add(EntityKey.getRandomEntityKey());
return entity;
}
}
}

Просмотреть файл

@ -0,0 +1,99 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using CosmosCloneCommon.Utility;
//using CollectionMigrator.Model;
using System.Diagnostics;
using Microsoft.Azure.CosmosDB.BulkExecutor;
using Microsoft.Azure.CosmosDB.BulkExecutor.BulkImport;
using Microsoft.Azure.Documents.Linq;
using logger = CosmosCloneCommon.Utility.CloneLogger;
namespace CosmosCloneCommon.Sample
{
public class SampleDBCreator
{
#region declare variables
protected int WriteBatchSize = 10000;
protected int ReadDelaybetweenRequestsInMs = 2000;
protected int maxtestDocumentCount = 50000;
protected bool IsFixedCollection = true;
protected CosmosDBHelper cosmosHelper;
protected CosmosBulkImporter cosmosBulkImporter;
protected DocumentClient sampleClient;
protected DocumentCollection sampleCollection;
#endregion
public SampleDBCreator()
{
cosmosHelper = new CosmosDBHelper();
cosmosBulkImporter = new CosmosBulkImporter();
}
public async Task InitializeMigration()
{
logger.LogInfo("Inside Initialize migration for SampleDBCreator. ");
sampleClient = cosmosHelper.GetSampleDocumentDbClient();
sampleCollection = await cosmosHelper.CreateSampleDocumentCollection(sampleClient, this.IsFixedCollection);
await cosmosBulkImporter.InitializeBulkExecutor(sampleClient, sampleCollection);
}
public async Task<bool> Start()
{
await InitializeMigration();
await CreateUploadTestDataInbatches();
return true;
}
protected List<dynamic> GetCommonEntitiesinBatch()
{
List<dynamic> entities = new List<dynamic>();
for(int i=0; i<this.WriteBatchSize; i++)
{
entities.Add(EntityV2.getRandomEntity());
}
return entities;
}
public async Task<bool> CreateUploadTestDataInbatches()
{
#region batchVariables
//initialize Batch Process variables
int batchCount = 0;
int totalUploaded = 0;
var badEntities = new List<Object>();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
#endregion
while (totalUploaded < maxtestDocumentCount)
{
batchCount++;
logger.LogInfo("Begin Sample Db creation");
List<dynamic> entities = GetCommonEntitiesinBatch();
BulkImportResponse uploadResponse = new BulkImportResponse();
if (entities.Any())
{
uploadResponse = await cosmosBulkImporter.BulkSendToNewCollection<dynamic>(entities);
}
badEntities = uploadResponse.BadInputDocuments;
//summary.totalRecordsSent += uploadResponse.NumberOfDocumentsImported;
totalUploaded += entities.Count();
logger.LogInfo($"Summary of Batch {batchCount} records retrieved {entities.Count()}. Records Uploaded: {uploadResponse.NumberOfDocumentsImported}");
//logger.LogInfo($"Total records retrieved {summary.totalRecordsRetrieved}. Total records uploaded {summary.totalRecordsSent}");
logger.LogInfo($"Time elapsed : {stopwatch.Elapsed} ");
}
stopwatch.Stop();
logger.LogInfo("Completed Sample DB creation.");
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,51 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
namespace CosmosCloneCommon.Utility
{
public static class CloneLogger
{
static CloneLogger()
{
_logBuilder = new StringBuilder("Collection Copy log");
}
static StringBuilder _logBuilder;
public static string FullLog
{
get
{
return _logBuilder.ToString();
}
}
public static string getFullLog()
{
return _logBuilder.ToString();
}
public static void LogInfo(string info)
{
Console.WriteLine(info);
_logBuilder.Append("\n"+info);
}
public static void LogError(string s)
{
LogInfo("Error Occurred");
LogInfo(s);
}
public static void LogError(Exception e)
{
LogInfo("LogError");
Exception baseException = e.GetBaseException();
LogInfo($"Error: {e.Message}, Message: {baseException.Message}");
}
}
}

Просмотреть файл

@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace CosmosCloneCommon.Utility
{
public class CloneSerializer
{
public static string XMLSerialize<T>(T dataToSerialize)
{
try
{
var stringwriter = new System.IO.StringWriter();
var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(stringwriter, dataToSerialize);
return stringwriter.ToString();
}
catch
{
throw;
}
}
public static T XMLDeserialize<T>(string xmlText)
{
try
{
var stringReader = new System.IO.StringReader(xmlText);
var serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(stringReader);
}
catch
{
throw;
}
}
}
}

Просмотреть файл

@ -0,0 +1,100 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
using System.Collections.Specialized;
using logger = CosmosCloneCommon.Utility.CloneLogger;
namespace CosmosCloneCommon.Utility
{
public static class CloneSettings
{
public static bool CopyStoredProcedures { get; set; }
public static bool CopyUDFs { get; set; }
public static bool CopyTriggers { get; set; }
public static bool CopyDocuments { get; set; }
public static bool CopyIndexingPolicy { get; set; }
public static bool CopyPartitionKey { get; set; }
public static int ReadBatchSize { get; set; }
public static int WriteBatchSize { get; private set; }
public static bool EnableTextLogging { get; set; }
public static bool ScrubbingRequired { get; set; }
public static int SourceOfferThroughputRUs { get; set; }
public static int TargetMigrationOfferThroughputRUs { get; set; }
public static int TargetRestOfferThroughputRUs { get; set; }
public static CosmosCollectionValues SourceSettings { get; set; }
public static CosmosCollectionValues TargetSettings { get; set; }
static CloneSettings()
{
ConfigurationManager.RefreshSection("appSettings");
CopyStoredProcedures = bool.Parse(ConfigurationManager.AppSettings["CopyStoredProcedures"]);
CopyUDFs = bool.Parse(ConfigurationManager.AppSettings["CopyUDFs"]);
CopyTriggers = bool.Parse(ConfigurationManager.AppSettings["CopyTriggers"]);
CopyDocuments = bool.Parse(ConfigurationManager.AppSettings["CopyDocuments"]);
CopyIndexingPolicy = bool.Parse(ConfigurationManager.AppSettings["CopyIndexingPolicy"]);
CopyPartitionKey = bool.Parse(ConfigurationManager.AppSettings["CopyPartitionKey"]);
var value = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
ReadBatchSize = int.Parse(ConfigurationManager.AppSettings["ReadBatchSize"].ToString());
WriteBatchSize = int.Parse(ConfigurationManager.AppSettings["WriteBatchCount"]);
EnableTextLogging = bool.Parse(ConfigurationManager.AppSettings["EnableTextLogging"]);
SourceOfferThroughputRUs = int.Parse(ConfigurationManager.AppSettings["SourceOfferThroughputRUs"]);
TargetMigrationOfferThroughputRUs = int.Parse(ConfigurationManager.AppSettings["TargetMigrationOfferThroughputRUs"]);
TargetRestOfferThroughputRUs = int.Parse(ConfigurationManager.AppSettings["TargetRestOfferThroughputRUs"]);
ScrubbingRequired = bool.Parse(ConfigurationManager.AppSettings["ScrubbingRequired"]);
var sourceConfigs = GetConfigurationSection("SourceCosmosDBSettings");
SourceSettings = new CosmosCollectionValues()
{
EndpointUrl = sourceConfigs["EndpointUrl"],
AccessKey = sourceConfigs["AccessKey"],
DatabaseName = sourceConfigs["DatabaseName"],
CollectionName = sourceConfigs["CollectionName"]
//OfferThroughputRUs = int.Parse(sourceConfigs["OfferThroughputRUs"])
};
var targetConfigs = GetConfigurationSection("TargetCosmosDBSettings");
TargetSettings = new CosmosCollectionValues()
{
EndpointUrl = targetConfigs["EndpointUrl"],
AccessKey = targetConfigs["AccessKey"],
DatabaseName = targetConfigs["DatabaseName"],
CollectionName = targetConfigs["CollectionName"]
// OfferThroughputRUs = int.Parse(sourceConfigs["OfferThroughputRUs"])
};
}
public static NameValueCollection GetConfigurationSection(string sectionName)
{
var appSettings = ConfigurationManager.GetSection(sectionName) as NameValueCollection;
if (appSettings.Count == 0)
{
logger.LogInfo($"Application Settings are not defined for {sectionName}");
}
return appSettings;
}
public static string AppSettings(string key)
{
return ConfigurationManager.AppSettings[key];
}
}
public class CosmosCollectionValues
{
public string EndpointUrl { get; set; }
public string AccessKey { get; set; }
public string DatabaseName { get; set; }
public string CollectionName { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,92 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using Microsoft.Azure.CosmosDB.BulkExecutor;
using Microsoft.Azure.CosmosDB.BulkExecutor.BulkImport;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using logger = CosmosCloneCommon.Utility.CloneLogger;
namespace CosmosCloneCommon.Utility
{
public class CosmosBulkImporter
{
private IBulkExecutor bulkExecutor;
private static readonly ConnectionPolicy ConnectionPolicy = new ConnectionPolicy
{
ConnectionMode = ConnectionMode.Direct,
ConnectionProtocol = Protocol.Tcp
};
public CosmosBulkImporter()
{
//var TargetCosmosDBSettings = CloneSettings.GetConfigurationSection("TargetCosmosDBSettings");
var TargetEndpointUrl = CloneSettings.TargetSettings.EndpointUrl;
var TargetAccessKey = CloneSettings.TargetSettings.AccessKey;
var TargetDatabaseName = CloneSettings.TargetSettings.DatabaseName;
var TargetCollectionName = CloneSettings.TargetSettings.CollectionName;
}
public async Task InitializeBulkExecutor(DocumentClient targetClient, DocumentCollection targetCollection)
{
logger.LogInfo("Inside InitializeBulkExecutor ");
// Set retry options high for initialization (default values).
targetClient.ConnectionPolicy.RetryOptions.MaxRetryWaitTimeInSeconds = 30;
targetClient.ConnectionPolicy.RetryOptions.MaxRetryAttemptsOnThrottledRequests = 9;
bulkExecutor = new BulkExecutor(targetClient, targetCollection);
await bulkExecutor.InitializeAsync();
// Set retries to 0 to pass control to bulk executor.
targetClient.ConnectionPolicy.RetryOptions.MaxRetryWaitTimeInSeconds = 0;
targetClient.ConnectionPolicy.RetryOptions.MaxRetryAttemptsOnThrottledRequests = 0;
}
public async Task<BulkImportResponse> BulkSendToNewCollection<T>(List<T> entityList)
{
BulkImportResponse bulkImportResponse = null;
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
int attempts = 0;
var objList = entityList.Cast<Object>();
do
{
bulkImportResponse = await bulkExecutor.BulkImportAsync(
documents: objList,
enableUpsert: true,
disableAutomaticIdGeneration: true,
maxConcurrencyPerPartitionKeyRange: null,
maxInMemorySortingBatchSize: null,
cancellationToken: token);
attempts++;
} while (bulkImportResponse.NumberOfDocumentsImported < entityList.Count() && attempts <= 5);
var badDocumentList = bulkImportResponse.BadInputDocuments;
#region log bulk Summary
logger.LogInfo(String.Format("\n Batch Upload completed "));
logger.LogInfo("--------------------------------------------------------------------- ");
logger.LogInfo(String.Format("Inserted {0} docs @ {1} writes/s, {2} RU/s in {3} sec",
bulkImportResponse.NumberOfDocumentsImported,
Math.Round(bulkImportResponse.NumberOfDocumentsImported / bulkImportResponse.TotalTimeTaken.TotalSeconds, 2),
Math.Round(bulkImportResponse.TotalRequestUnitsConsumed / bulkImportResponse.TotalTimeTaken.TotalSeconds, 2),
bulkImportResponse.TotalTimeTaken.TotalSeconds));
logger.LogInfo(String.Format("Average RU consumption per document: {0}",
Math.Round(bulkImportResponse.TotalRequestUnitsConsumed / bulkImportResponse.NumberOfDocumentsImported, 2)));
if (badDocumentList != null && badDocumentList.Count > 0)
{
logger.LogInfo($"bad Documents detected {badDocumentList.Count}");
}
logger.LogInfo("---------------------------------------------------------------------\n ");
#endregion
return bulkImportResponse;
}
}
}

Просмотреть файл

@ -0,0 +1,504 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents;
using CosmosCloneCommon.Model;
using logger = CosmosCloneCommon.Utility.CloneLogger;
namespace CosmosCloneCommon.Utility
{
public class CosmosDBHelper
{
private int OfferThroughput = 1000;
private ConnectionPolicy ConnectionPolicy;
public CosmosDBHelper()
{
ConnectionPolicy = new ConnectionPolicy
{
ConnectionMode = ConnectionMode.Direct,
ConnectionProtocol = Protocol.Tcp,
RetryOptions = new RetryOptions()
};
this.ConnectionPolicy.RetryOptions.MaxRetryAttemptsOnThrottledRequests = 20;
this.ConnectionPolicy.RetryOptions.MaxRetryWaitTimeInSeconds = 600;
}
public async Task<ValidationResult> TestSourceConnection()
{
var result = new ValidationResult();
DocumentClient sourceDocumentClient;
try
{
sourceDocumentClient = new DocumentClient(new Uri(CloneSettings.SourceSettings.EndpointUrl), CloneSettings.SourceSettings.AccessKey, ConnectionPolicy);
}
catch (Exception ex)
{
logger.LogError(ex);
result.IsSuccess = false;
result.Message = "Unable to connect to Source. Check your input url and key are accurate. If Firewall security is enabled for your database please add the ip address of the current machine.";
return result;
}
try
{
var cosmosDBURI = UriFactory.CreateDocumentCollectionUri(CloneSettings.SourceSettings.DatabaseName, CloneSettings.SourceSettings.CollectionName);
//var sourceDatabase = await sourceDocumentClient.ReadDatabaseAsync(Database);
var sourceCollection = await sourceDocumentClient.ReadDocumentCollectionAsync(cosmosDBURI);
}
catch (Exception ex)
{
logger.LogError(ex);
result.IsSuccess = false;
result.Message = "Incorrect DatabaseName or Collection. Check your input DatabaseName and Collection are accurate.";
return result;
}
result.IsSuccess = true;
result.Message = "OK";
return result;
}
public ValidationResult TestSourceConnection_v2()
{
var result = new ValidationResult();
DocumentClient sourceDocumentClient;
try
{
sourceDocumentClient = new DocumentClient(new Uri(CloneSettings.SourceSettings.EndpointUrl), CloneSettings.SourceSettings.AccessKey, ConnectionPolicy);
}
catch (Exception ex)
{
logger.LogError(ex);
result.IsSuccess = false;
result.Message = "Unable to connect to Source. Check your input url and key are accurate. If Firewall security is enabled for your database please add the ip address of the current machine.";
return result;
}
try
{
var cosmosDBURI = UriFactory.CreateDocumentCollectionUri(CloneSettings.SourceSettings.DatabaseName, CloneSettings.SourceSettings.CollectionName);
//var sourceDatabase = await sourceDocumentClient.ReadDatabaseAsync(Database);
var sourceCollection = sourceDocumentClient.ReadDocumentCollectionAsync(cosmosDBURI);
}
catch (Exception ex)
{
logger.LogError(ex);
result.IsSuccess = false;
result.Message = "Incorrect DatabaseName or Collection. Check your input DatabaseName and Collection are accurate.";
return result;
}
result.IsSuccess = true;
result.Message = "OK";
return result;
}
public async Task<ValidationResult> TestTargetConnection()
{
var result = new ValidationResult();
DocumentClient targetDocumentClient;
try
{
targetDocumentClient = new DocumentClient(new Uri(CloneSettings.TargetSettings.EndpointUrl), CloneSettings.TargetSettings.AccessKey, ConnectionPolicy);
}
catch (Exception ex)
{
logger.LogError(ex);
result.IsSuccess = false;
result.Message = "Unable to connect to Target. Check your input url and key are accurate. If Firewall security is enabled for your database please add the ip address of the current machine.";
return result;
}
try
{
var cosmosDBURI = UriFactory.CreateDatabaseUri(CloneSettings.TargetSettings.DatabaseName);
var sourceDatabase = await targetDocumentClient.ReadDatabaseAsync(cosmosDBURI);
}
catch (Exception ex)
{
logger.LogError(ex);
result.IsSuccess = false;
result.Message = "Incorrect DatabaseName .Check whether the input DatabaseName is accurate.";
return result;
}
result.IsSuccess = true;
result.Message = "OK";
return result;
}
public ValidationResult TestTargetConnection_v2()
{
var result = new ValidationResult();
DocumentClient targetDocumentClient;
try
{
targetDocumentClient = new DocumentClient(new Uri(CloneSettings.TargetSettings.EndpointUrl), CloneSettings.TargetSettings.AccessKey, ConnectionPolicy);
}
catch (Exception ex)
{
logger.LogError(ex);
result.IsSuccess = false;
result.Message = "Unable to connect to Target. Check your input url and key are accurate. If Firewall security is enabled for your database please add the ip address of the current machine.";
return result;
}
try
{
var cosmosDBURI = UriFactory.CreateDatabaseUri(CloneSettings.TargetSettings.DatabaseName);
var sourceDatabase = targetDocumentClient.ReadDatabaseAsync(cosmosDBURI);
}
catch (Exception ex)
{
logger.LogError(ex);
result.IsSuccess = false;
result.Message = "Incorrect DatabaseName .Check whether the input DatabaseName is accurate.";
return result;
}
result.IsSuccess = true;
result.Message = "OK";
return result;
}
public DocumentClient GetSourceDocumentDbClient()
{
try
{
string SourceEndpointUrl = CloneSettings.SourceSettings.EndpointUrl;
string SourceAccessKey = CloneSettings.SourceSettings.AccessKey;
var sourceDocumentClient = new DocumentClient(new Uri(SourceEndpointUrl), SourceAccessKey, ConnectionPolicy);
return sourceDocumentClient;
}
catch (Exception ex)
{
logger.LogError(ex);
throw;
}
}
public DocumentClient GetTargetDocumentDbClient()
{
try
{
string targetEndpointUrl = CloneSettings.TargetSettings.EndpointUrl;
string targetAccessKey = CloneSettings.TargetSettings.AccessKey;
OfferThroughput = CloneSettings.TargetMigrationOfferThroughputRUs;
var targetDocumentClient = new DocumentClient(new Uri(targetEndpointUrl), targetAccessKey, ConnectionPolicy);
return targetDocumentClient;
}
catch (Exception ex)
{
logger.LogError(ex);
throw;
}
}
public DocumentClient GetSampleDocumentDbClient()
{
try
{
var SourceCosmosDBSettings = CloneSettings.GetConfigurationSection("SampleCosmosDBSettings");
string SourceEndpointUrl = SourceCosmosDBSettings["EndpointUrl"];
string SourceAccessKey = SourceCosmosDBSettings["AccessKey"];
var sourceDocumentClient = new DocumentClient(new Uri(SourceEndpointUrl), SourceAccessKey, ConnectionPolicy);
return sourceDocumentClient;
}
catch (Exception ex)
{
logger.LogError(ex);
throw;
}
}
public async Task<DocumentCollection> GetTargetDocumentCollection(DocumentClient targetClient)
{
try
{
//var SourceCosmosDBSettings = CloneSettings.GetConfigurationSection("SourceCosmosDBSettings");
string DatabaseName = CloneSettings.TargetSettings.DatabaseName;
string CollectionName = CloneSettings.TargetSettings.CollectionName;
var cosmosDBURI = UriFactory.CreateDocumentCollectionUri(DatabaseName, CollectionName);
//sourceClient.ReadDocumentCollectionAsync
var targetCollection = (DocumentCollection)await targetClient.ReadDocumentCollectionAsync(UriFactory.CreateDocumentCollectionUri(DatabaseName, CollectionName), new RequestOptions { OfferEnableRUPerMinuteThroughput = true, OfferThroughput = CloneSettings.TargetMigrationOfferThroughputRUs });
//targetClient.ReadDocumentCollectionAsync()
//var sourceCollection = (DocumentCollection)await sourceClient.CreateDocumentCollectionIfNotExistsAsync(UriFactory.CreateDatabaseUri(sourceDatabaseName), new DocumentCollection { Id = sourceCollectionName });
return targetCollection;
}
catch (Exception ex)
{
logger.LogError(ex);
throw;
}
}
public async Task<DocumentCollection> GetTargetDocumentCollection_v2(DocumentClient targetClient)
{
try
{
//var SourceCosmosDBSettings = CloneSettings.GetConfigurationSection("SourceCosmosDBSettings");
string DatabaseName = CloneSettings.TargetSettings.DatabaseName;
string CollectionName = CloneSettings.TargetSettings.CollectionName;
var cosmosDBURI = UriFactory.CreateDocumentCollectionUri(DatabaseName, CollectionName);
//sourceClient.ReadDocumentCollectionAsync
var targetCollection = (DocumentCollection)await targetClient.ReadDocumentCollectionAsync(UriFactory.CreateDocumentCollectionUri(DatabaseName, CollectionName), new RequestOptions { OfferEnableRUPerMinuteThroughput = true, OfferThroughput = CloneSettings.TargetMigrationOfferThroughputRUs });
//targetClient.ReadDocumentCollectionAsync()
//var sourceCollection = (DocumentCollection)await sourceClient.CreateDocumentCollectionIfNotExistsAsync(UriFactory.CreateDatabaseUri(sourceDatabaseName), new DocumentCollection { Id = sourceCollectionName });
return targetCollection;
}
catch (Exception ex)
{
logger.LogError(ex);
throw;
}
}
public async Task<DocumentCollection> GetSourceDocumentCollection(DocumentClient sourceClient)
{
try
{
//var SourceCosmosDBSettings = CloneSettings.GetConfigurationSection("SourceCosmosDBSettings");
string sourceDatabaseName = CloneSettings.SourceSettings.DatabaseName;
string sourceCollectionName = CloneSettings.SourceSettings.CollectionName;
var cosmosDBURI = UriFactory.CreateDocumentCollectionUri(sourceDatabaseName, sourceCollectionName);
var sourceCollection = (DocumentCollection)await sourceClient.CreateDocumentCollectionIfNotExistsAsync(UriFactory.CreateDatabaseUri(sourceDatabaseName), new DocumentCollection { Id = sourceCollectionName });
return sourceCollection;
}
catch (Exception ex)
{
logger.LogError(ex);
throw;
}
}
public async Task<DocumentCollection> CreateSampleDocumentCollection(DocumentClient sampleClient, bool IsFixedCollection = false)
{
try
{
var sampleCosmosDBSettings = CloneSettings.GetConfigurationSection("SampleCosmosDBSettings");
string sampleDatabaseName = sampleCosmosDBSettings["DatabaseName"]; ;
string sampleCollectionName = sampleCosmosDBSettings["CollectionName"];
int offerThroughput = 1000;
int.TryParse(sampleCosmosDBSettings["OfferThroughputRUs"], out offerThroughput);
await sampleClient.CreateDatabaseIfNotExistsAsync(new Database { Id = sampleDatabaseName });
DocumentCollection newDocumentCollection;
if (!IsFixedCollection)
{
var partitionKeyDefinition = new PartitionKeyDefinition();
partitionKeyDefinition.Paths.Add("/CompositeName");
newDocumentCollection = (DocumentCollection)await sampleClient.CreateDocumentCollectionIfNotExistsAsync
(UriFactory.CreateDatabaseUri(sampleDatabaseName),
new DocumentCollection { Id = sampleCollectionName, PartitionKey = partitionKeyDefinition },
new RequestOptions { OfferThroughput = offerThroughput });
}
else
{
//no partition key if it is a fixed collection
newDocumentCollection = (DocumentCollection)await sampleClient.CreateDocumentCollectionIfNotExistsAsync
(UriFactory.CreateDatabaseUri(sampleDatabaseName),
new DocumentCollection { Id = sampleCollectionName},
new RequestOptions { OfferThroughput = offerThroughput });
}
return newDocumentCollection;
}
catch (Exception ex)
{
logger.LogError(ex);
throw;
}
}
public async Task<DocumentCollection> CreateTargetDocumentCollection(DocumentClient targetClient, IndexingPolicy indexingPolicy, PartitionKeyDefinition partitionKeyDefinition)
{
try
{
//var targetCosmosDBSettings = CloneSettings.GetConfigurationSection("TargetCosmosDBSettings");
string targetDatabaseName = CloneSettings.TargetSettings.DatabaseName;
string targetCollectionName = CloneSettings.TargetSettings.CollectionName;
await targetClient.CreateDatabaseIfNotExistsAsync(new Database { Id = targetDatabaseName });
DocumentCollection newDocumentCollection;
if (partitionKeyDefinition != null && partitionKeyDefinition.Paths.Count>0)
{
if(CloneSettings.CopyPartitionKey)
{
// Partition key exists in Source (Unlimited Storage)
newDocumentCollection = (DocumentCollection)await targetClient.CreateDocumentCollectionIfNotExistsAsync
(UriFactory.CreateDatabaseUri(targetDatabaseName),
new DocumentCollection { Id = targetCollectionName, PartitionKey = partitionKeyDefinition, IndexingPolicy = indexingPolicy },
new RequestOptions { OfferEnableRUPerMinuteThroughput = true, OfferThroughput = CloneSettings.TargetMigrationOfferThroughputRUs });
}
else
{
newDocumentCollection = (DocumentCollection)await targetClient.CreateDocumentCollectionIfNotExistsAsync
(UriFactory.CreateDatabaseUri(targetDatabaseName),
new DocumentCollection { Id = targetCollectionName, IndexingPolicy = indexingPolicy },
new RequestOptions { OfferEnableRUPerMinuteThroughput = true, OfferThroughput = CloneSettings.TargetMigrationOfferThroughputRUs });
}
}
else
{ //no partition key set in source (Fixed storage)
newDocumentCollection = (DocumentCollection)await targetClient.CreateDocumentCollectionIfNotExistsAsync
(UriFactory.CreateDatabaseUri(targetDatabaseName),
new DocumentCollection { Id = targetCollectionName, IndexingPolicy = indexingPolicy },
new RequestOptions { OfferEnableRUPerMinuteThroughput = true, OfferThroughput = CloneSettings.TargetMigrationOfferThroughputRUs });
}
logger.LogInfo($"SuccessFully Created Target. Database: {targetDatabaseName} Collection:{targetCollectionName}");
return newDocumentCollection;
}
catch (Exception ex)
{
logger.LogError(ex);
throw;
}
}
public IQueryable<T> GetSourceEntityDocumentQuery<T>(DocumentClient sourceClient, int batchSize = -1)
{
try
{
//var SourceCosmosDBSettings = CloneSettings.GetConfigurationSection("SourceCosmosDBSettings");
string sourceDatabaseName = CloneSettings.SourceSettings.DatabaseName;
string sourceCollectionName = CloneSettings.SourceSettings.CollectionName;
FeedOptions queryOptions = new FeedOptions { MaxItemCount = batchSize, EnableCrossPartitionQuery = true };
string EntityDataQuery = $"SELECT * FROM c";
var documentQuery = sourceClient.CreateDocumentQuery<T>(UriFactory.CreateDocumentCollectionUri(sourceDatabaseName, sourceCollectionName), EntityDataQuery, queryOptions);
return documentQuery;
}
catch (Exception ex)
{
logger.LogError(ex);
throw;
}
}
public IQueryable<T> GetScrubDataDocumentQuery<T>(DocumentClient targetClient,string filterCondition, int batchSize = -1)
{
try
{
//var SourceCosmosDBSettings = CloneSettings.GetConfigurationSection("SourceCosmosDBSettings");
string DatabaseName = CloneSettings.TargetSettings.DatabaseName;
string CollectionName = CloneSettings.TargetSettings.CollectionName;
FeedOptions queryOptions = new FeedOptions { MaxItemCount = batchSize, EnableCrossPartitionQuery = true };
string scrubDataQuery;
if (string.IsNullOrEmpty(filterCondition))
{
scrubDataQuery = "SELECT * FROM c";
}
else
{
scrubDataQuery = "SELECT * FROM c" + " where " + filterCondition;
}
var documentQuery = targetClient.CreateDocumentQuery<T>(UriFactory.CreateDocumentCollectionUri(DatabaseName, CollectionName), scrubDataQuery, queryOptions);
return documentQuery;
}
catch (Exception ex)
{
logger.LogError(ex);
throw;
}
}
public async Task<bool> SetTargetRestOfferThroughPut()
{
using (var client = GetTargetDocumentDbClient())
{
var collection = this.GetTargetDocumentCollection(client);
FeedOptions queryOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = true };
//var Ioffer = cosmosClient.CreateOfferQuery(queryOptions);
//var offer = Ioffer.AsEnumerable().SingleOrDefault();
Offer offer = client.CreateOfferQuery()
.Where(r => r.ResourceLink == collection.Result.SelfLink)
.AsEnumerable()
.SingleOrDefault();
offer = new OfferV2(offer, CloneSettings.TargetRestOfferThroughputRUs);
await client.ReplaceOfferAsync(offer);
//.Where(r => r.ResourceLink == collection.)
//.AsEnumerable()
//.SingleOrDefault();
}
return true;
}
public bool CompareRecordCount()
{
//var SourceCosmosDBSettings = CloneSettings.GetConfigurationSection("SourceCosmosDBSettings");
string sourceDatabaseName = CloneSettings.SourceSettings.DatabaseName;
string sourceCollectionName = CloneSettings.SourceSettings.CollectionName;
//var TargetCosmosDBSettings = CloneSettings.GetConfigurationSection("SourceCosmosDBSettings");
string targetDatabaseName = CloneSettings.TargetSettings.DatabaseName;
string targetCollectionName = CloneSettings.TargetSettings.CollectionName;
string totalCountQuery = "SELECT VALUE COUNT(1) FROM p";
FeedOptions queryOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = true };
long sourceTotalRecordCount, targetTotalRecordCount;
using (var cosmosClient = GetSourceDocumentDbClient())
{
sourceTotalRecordCount = cosmosClient.CreateDocumentQuery<long>(
UriFactory.CreateDocumentCollectionUri(sourceDatabaseName, sourceCollectionName), totalCountQuery, queryOptions)
.AsEnumerable().First();
}
using (var cosmosClient = GetTargetDocumentDbClient())
{
targetTotalRecordCount = cosmosClient.CreateDocumentQuery<long>(
UriFactory.CreateDocumentCollectionUri(targetDatabaseName, targetCollectionName), totalCountQuery, queryOptions)
.AsEnumerable().First();
}
return (sourceTotalRecordCount == targetTotalRecordCount) ? true: false;
}
public long GetSourceRecordCount()
{
//var SourceCosmosDBSettings = CloneSettings.GetConfigurationSection("SourceCosmosDBSettings");
string sourceDatabaseName = CloneSettings.SourceSettings.DatabaseName;
string sourceCollectionName = CloneSettings.SourceSettings.CollectionName;
string totalCountQuery = "SELECT VALUE COUNT(1) FROM c";
FeedOptions queryOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = true };
long sourceTotalRecordCount;
using (var cosmosClient = GetSourceDocumentDbClient())
{
sourceTotalRecordCount = cosmosClient.CreateDocumentQuery<long>(
UriFactory.CreateDocumentCollectionUri(sourceDatabaseName, sourceCollectionName), totalCountQuery, queryOptions)
.AsEnumerable().First();
}
return sourceTotalRecordCount;
}
public long GetRecordCountToScrub(ScrubRule scrubbingRule)
{
//var SourceCosmosDBSettings = CloneSettings.GetConfigurationSection("SourceCosmosDBSettings");
string DatabaseName = CloneSettings.TargetSettings.DatabaseName;
string CollectionName = CloneSettings.TargetSettings.CollectionName;
string totalCountQuery;
if (string.IsNullOrEmpty(scrubbingRule.FilterCondition))
{
totalCountQuery = "SELECT VALUE COUNT(1) FROM c";
}
else
{
totalCountQuery = "SELECT VALUE COUNT(1) FROM c" + " where " + scrubbingRule.FilterCondition;
}
FeedOptions queryOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = true };
long sourceTotalRecordCount;
using (var cosmosClient = GetTargetDocumentDbClient())
{
sourceTotalRecordCount = cosmosClient.CreateDocumentQuery<long>(
UriFactory.CreateDocumentCollectionUri(DatabaseName, CollectionName), totalCountQuery, queryOptions)
.AsEnumerable().First();
}
return sourceTotalRecordCount;
}
}
}

Просмотреть файл

@ -0,0 +1,280 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using CosmosCloneCommon.Model;
using CosmosCloneCommon.Sample;
namespace CosmosCloneCommon.Utility
{
public class ObjectScrubber
{
public List<JToken> ScrubObjectList(List<string> srcList, ScrubRule scrubRule)
{
//var scrubbedObjects = new List<string>();
var scrubbedObjects = new List<JToken>();
var propNames = scrubRule.PropertyName.Split('.').ToList();
if(scrubRule.Type == RuleType.NullValue || scrubRule.Type == RuleType.SingleValue)
{
foreach (var strObj in srcList)
{
try
{
JToken jToken = getUpdatedJsonArrayValue((JToken)JObject.Parse(strObj), propNames, scrubRule.UpdateValue);
scrubbedObjects.Add(jToken);
}
catch(Exception ex)
{
CloneLogger.LogInfo("Log failed");
CloneLogger.LogError(ex);
throw ;
}
}
}
else if(scrubRule.Type == RuleType.Shuffle)
{
//get all similar values
var propertyValues = new List<JToken>();
foreach (var strObj in srcList)
{
try
{
List<JToken> jTokenList = new List<JToken>();
getPropertyValues((JToken)JObject.Parse(strObj), propNames, ref jTokenList);
propertyValues.AddRange(jTokenList);
}
catch (Exception ex)
{
CloneLogger.LogInfo("Log failed");
CloneLogger.LogError(ex);
throw ;
}
}
var shuffledTokens = RandomNumberGenerator.Shuffle(propertyValues);
var shuffledTokenQ = new Queue<JToken>(shuffledTokens);
foreach (var strObj in srcList)
{
try
{
JToken jToken = getDocumentShuffledToken((JToken)JObject.Parse(strObj), propNames, ref shuffledTokenQ);
scrubbedObjects.Add(jToken);
}
catch (Exception ex)
{
CloneLogger.LogInfo("Log failed");
CloneLogger.LogError(ex);
throw ;
}
}
}
else
{
foreach (var strObj in srcList)
{
scrubbedObjects.Add((JToken)strObj);
}
}
return scrubbedObjects;
}
public List<JToken> getPropertyValues(JToken token, List<string> propNames, ref List<JToken> jTokenList)
{
if(jTokenList == null)
{
jTokenList = new List<JToken>();
}
if (token == null || token.Type == JTokenType.Null) return jTokenList;
bool isLeaflevel = false;
for (int i = 1; i < propNames.Count; i++)
{
if (i == propNames.Count - 1) isLeaflevel = true;
var currentProperty = propNames[i];
if (token.Type == JTokenType.Array)
{
var jArray = (JArray)token;
for (int k = 0; k < jArray.Count; k++)
{
if (isLeaflevel == true)
{
if (jArray[k][currentProperty] != null && jArray[k][currentProperty].Type != JTokenType.Null)
{
jTokenList.Add(jArray[k][currentProperty]);
}
else
{
jTokenList.Add(null);//In future, to retain null feature modify this to conditional
}
continue;
}
else
{
getPropertyValues(jArray[k], propNames.GetRange(i, propNames.Count - i), ref jTokenList);
continue;
}
}
}
else
{
var jObj = (JObject)token;
if (isLeaflevel == true)
{
if (jObj[currentProperty] != null )
{
jTokenList.Add(jObj[currentProperty]);
}
else
{
jTokenList.Add(null);//In future, to retain null feature modify this to conditional
}
}
else
{
getPropertyValues((JToken)jObj[currentProperty], propNames.GetRange(i, propNames.Count - i), ref jTokenList);
}
}
break;
}
return jTokenList;
}
public JToken getDocumentShuffledToken(JToken token, List<string> propNames, ref Queue<JToken> tokenQ)
{
if (token == null || token.Type == JTokenType.Null) return null;
JToken jTokenResult = token;//just to initialize
bool isLeaflevel = false;
for (int i = 1; i < propNames.Count; i++)
{
if (i == propNames.Count - 1) isLeaflevel = true;
var currentProperty = propNames[i];
if (token.Type == JTokenType.Array)
{
var jArray = (JArray)token;
for (int k = 0; k < jArray.Count; k++)
{
if (isLeaflevel == true)
{
if (jArray[k][currentProperty] != null && jArray[k][currentProperty].Type != JTokenType.Null)
{
jArray[k][currentProperty] = tokenQ.Dequeue();
}
continue;
}
else
{
jArray[k] = getDocumentShuffledToken(jArray[k], propNames.GetRange(i, propNames.Count - i), ref tokenQ);
continue;
}
}
var str2 = jArray.ToString();
jTokenResult = (JToken)jArray;
}
else
{
var jObj = (JObject)token;
if (isLeaflevel == true)
{
if (jObj[currentProperty] != null)
{
jObj[currentProperty] = tokenQ.Dequeue();
}
}
else
{
jObj[currentProperty] = getDocumentShuffledToken((JToken)jObj[currentProperty], propNames.GetRange(i, propNames.Count - i), ref tokenQ);
}
var str3 = jObj.ToString();
jTokenResult = (JToken)jObj;
}
break;
}
if (jTokenResult == null)
{
jTokenResult = token;
}
return jTokenResult;
}
public JToken getUpdatedJsonArrayValue(JToken token, List<string> propNames, string overwritevalue)
{
if (token == null || token.Type == JTokenType.Null) return null;
JToken jTokenResult=token;//just to initialize
bool isLeaflevel = false;
for (int i = 1; i < propNames.Count; i++)
{
if (i == propNames.Count - 1) isLeaflevel = true;
var currentProperty = propNames[i];
if (token.Type == JTokenType.Array)
{
var jArray = (JArray)token;
for (int k = 0; k < jArray.Count; k++)
{
if (isLeaflevel == true)
{
if (jArray[k][currentProperty] != null && jArray[k][currentProperty].Type != JTokenType.Null)
{
jArray[k][currentProperty] = overwritevalue;
}
continue;
}
else
{
if (jArray[k] != null && jArray[k][currentProperty].Type != JTokenType.Null)
{
jArray[k] = getUpdatedJsonArrayValue(jArray[k], propNames.GetRange(i, propNames.Count - i), overwritevalue);
continue;
}
//else return null;
}
}
var str2 = jArray.ToString();
jTokenResult = (JToken)jArray;
}
else
{
var jObj = (JObject)token;
if (isLeaflevel == true)
{
if(jObj[currentProperty] != null && jObj[currentProperty].Type != JTokenType.Null)
{
jObj[currentProperty] = overwritevalue;
}
}
else
{
if (jObj[currentProperty] != null && jObj[currentProperty].Type != JTokenType.Null)
{
jObj[currentProperty] = getUpdatedJsonArrayValue((JToken)jObj[currentProperty], propNames.GetRange(i, propNames.Count - i), overwritevalue);
}
//else return null;
}
var str3 = jObj.ToString();
jTokenResult = (JToken)jObj;
}
break;
}
if(jTokenResult == null)
{
jTokenResult = token;
}
return jTokenResult;
}
}
}

Просмотреть файл

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="EndPointUrl" value="__DBUrl__" />
<add key="AuthorizationKey" value="__accesskey__" />
<add key="DatabaseName" value="TestDB" />
<add key="CollectionName" value="TestColl1" />
<add key="CollectionThroughput" value="10000" />
<add key="ShouldCleanupOnStart" value="true" />
<add key="ShouldCleanupOnFinish" value="false" />
<add key="NumberOfDocumentsToImport" value="10000" />
<add key="NumberOfBatches" value="10" />
<add key="CollectionPartitionKey" value="/profileid" />
</appSettings>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Azure.Documents.Client" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

Просмотреть файл

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Azure.CosmosDB.BulkExecutor" version="1.2.0" targetFramework="net461" />
<package id="Microsoft.Azure.DocumentDB" version="2.1.3" targetFramework="net461" />
<package id="MongoDB.Bson" version="2.4.4" targetFramework="net461" />
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net461" />
<package id="System.Buffers" version="4.5.0" targetFramework="net461" />
<package id="System.Memory" version="4.5.0" targetFramework="net461" />
<package id="System.Net.Http.WinHttpHandler" version="4.5.0" targetFramework="net461" />
<package id="System.Numerics.Vectors" version="4.4.0" targetFramework="net461" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.0" targetFramework="net461" />
</packages>