Home
%3CLINGO-SUB%20id%3D%22lingo-sub-1061191%22%20slang%3D%22en-US%22%3EScale%20your%20data%20sharing%20needs%20with%20the%20power%20of%20Azure%20Data%20Share%E2%80%99s%20.NET%20SDK%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1061191%22%20slang%3D%22en-US%22%3E%3CP%3EAzure%20Data%20Share%2C%20now%20a%20generally%20available%20service%2C%20makes%20it%20very%20simple%20to%20share%20your%20organization%E2%80%99s%20data%20securely%20with%20your%20partners.%20You%20may%20have%20already%20seen%20and%20tried%20it%20on%20the%20Azure%20Portal%20to%20share%20data%20swiftly%2C%20without%20writing%20any%20code.%20But%20what%20if%20you%20want%20to%20scale%20your%20sharing%20needs%20to%20thousands%20of%20customers%20spread%20across%20the%20world%3F%20Data%20Share%20offers%20a%20rich%20API%2FSDK%20for%20you%20to%20leverage%20and%20scale%20your%20sharing%20relationships%20seamlessly.%20Let%E2%80%99s%20jump%20right%20in%20and%20walk%20through%20a%20sample%20use%20case%20using%20the%20.NET%20SDK.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CFONT%20size%3D%225%22%3EWhy%20use%20the%20.NET%20SDK%3F%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EImagine%20the%20following%20situation%3A%20Your%20organization%20provides%20data%20to%20some%20partners%20and%20consumes%20data%20from%20others%2C%20where%20these%20partners%20can%20be%20departments%20within%20your%20company%20or%20external%20organizations.%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdata-share%2Fshare-your-data%22%20target%3D%22_self%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3EUsing%20Data%20Shares%3C%2FA%3E's%20portal%20experience%20for%20creating%20and%20managing%20the%20first%20few%20sharing%20relationships%20is%20quick%20and%20intuitive.%20However%2C%20as%20the%20number%20of%20sharing%20relationships%20grows%20larger%2C%20the%20process%20would%20soon%20grow%20tedious.%20Imagine%20managing%20potentially%20hundreds%20or%20even%20thousands%20of%20sharing%20relationships.%20This%20would%20become%20manually%20unscalable.%20We%E2%80%99ve%20designed%20the%20Data%20Share%20SDK%20for%20ease-of-use%2C%20to%20facilitate%20the%20scaling%20of%20your%20organization%E2%80%99s%20sharing%20needs.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH1%20id%3D%22toc-hId-357429692%22%20id%3D%22toc-hId-357429692%22%3E%3CFONT%20size%3D%225%22%3EScenario%3CBR%20%2F%3E%3CBR%20%2F%3E%3C%2FFONT%3E%3C%2FH1%3E%0A%3CP%3ESince%20we%20would%20like%20to%20demonstrate%20both%20the%20data%20provider%E2%80%99s%20and%20consumer%E2%80%99s%20perspectives%2C%20let%E2%80%99s%20try%20a%20common%20customer%20scenario%20of%20sharing%20between%20departments%20of%20the%20same%20organization.%20Specifically%2C%20suppose%20the%20provider%20department%20(say%20Marketing)%20has%20its%20data%20in%20a%20blob%20store%20and%20wants%20to%20share%20that%20with%20a%20different%20department%20(say%20Sales).%20To%20make%20this%20sharing%20more%20interesting%2C%20we%E2%80%99ll%20try%20to%20share%20the%20data%20to%20a%20different%20tenant.%20Let's%20see%20how%20the%20Data%20Share%20SDK%20can%20be%20used%20for%20this.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH2%20id%3D%22toc-hId-1047991166%22%20id%3D%22toc-hId-1047991166%22%3E%3CFONT%20size%3D%225%22%3ESetting%20up%20the%20Console%20Application%3CBR%20%2F%3E%3CBR%20%2F%3E%3C%2FFONT%3E%3C%2FH2%3E%0A%3CH3%20id%3D%22toc-hId-1738552640%22%20id%3D%22toc-hId-1738552640%22%3EGetting%20a%20copy%20of%20the%20sample%20code%3CBR%20%2F%3E%3CBR%20%2F%3E%3C%2FH3%3E%0A%3CP%3EStart%20by%20cloning%20the%20sample%20%3CA%20href%3D%22https%3A%2F%2Fgithub.com%2FAzure-Samples%2Fazure-data-share-dotnet-api-sample.git%22%20target%3D%22_self%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3EGit%20repository%3C%2FA%3E%3A%20by%20typing%20on%20the%20command%20prompt%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-markup%22%3E%3CCODE%3Egit%20clone%20%3CA%20href%3D%22https%3A%2F%2Fgithub.com%2FAzure-Samples%2Fazure-data-share-dotnet-api-sample.git%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3Ehttps%3A%2F%2Fgithub.com%2FAzure-Samples%2Fazure-data-share-dotnet-api-sample.git%3C%2FA%3E%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH3%20id%3D%22toc-hId--68901823%22%20id%3D%22toc-hId--68901823%22%3E%3CBR%20%2F%3ECreating%20a%20Service%20Principal%20for%20the%20Console%20Application%3CBR%20%2F%3E%3CBR%20%2F%3E%3C%2FH3%3E%0A%3CP%3EWe'll%20use%20active%20directory%20application%20Id%20and%20secret%20for%20authenticating%20the%20console%20application.%20For%20this%2C%20an%20Azure%20Active%20Directory%20(AAD)%20application%20must%20be%20created%20each%20for%20the%20provider%20and%20the%20consumer.%20Follow%20this%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Factive-directory%2Fdevelop%2Fhowto-create-service-principal-portal%22%20target%3D%22_self%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3Etutorial%20to%20set%20up%20the%20AAD%20application%3C%2FA%3E.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH3%20id%3D%22toc-hId--1876356286%22%20id%3D%22toc-hId--1876356286%22%3ECreating%20Storage%20Accounts%3CBR%20%2F%3E%3CBR%20%2F%3E%3C%2FH3%3E%0A%3CP%3EThe%20console%20application%20will%20share%20data%20from%20the%20provider%20data%20share%20account%20to%20the%20consumer%20data%20share%20account%2C%20each%20of%20which%20will%20point%20to%20an%20underlying%20data%20store.%20For%20this%20demo%20you%20will%20need%20to%20create%20a%20storage%20account%20each%20for%20the%20provider%20and%20consumer.%20Please%20follow%20this%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fstorage%2Fcommon%2Fstorage-quickstart-create-account%3Ftabs%3Dazure-portal%22%20target%3D%22_self%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3Etutorial%20to%20create%20the%20storage%20accounts%3C%2FA%3E.%20Also%20ensure%20that%20the%20Service%20Principal%20created%20in%20the%20previous%20section%20has%20%3CEM%3E%22Owner%22%3C%2FEM%3E%20role%20on%20the%20storage%20accounts.%20To%20learn%20how%20to%20add%20role%20assignment%20to%20resources%2C%20please%20follow%20this%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Frole-based-access-control%2Frole-assignments-portal%22%20target%3D%22_self%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3Etutorial%3C%2FA%3E.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH3%20id%3D%22toc-hId-611156547%22%20id%3D%22toc-hId-611156547%22%3EConfiguring%20the%20run-time%20settings%3CBR%20%2F%3E%3CBR%20%2F%3E%3C%2FH3%3E%0A%3CP%3EOnce%20the%20repository%20has%20been%20cloned%2C%20navigate%20to%20the%20file%20%3CSTRONG%3EDataShareSample.sln%20%3C%2FSTRONG%3Eand%20open%20it.%20By%20default%2C%20it%20should%20open%20in%20Visual%20studio%202017.%20Try%20to%20build%20the%20solution%20and%20make%20sure%20everything%20compiles%20correctly.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3ENow%20we%20will%20go%20ahead%20and%20configure%20the%20run-time%20settings%20in%20the%20%3CEM%3EappSettings.json%3C%2FEM%3E%20file%20(shown%20in%20Snippet%201)%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSTRONG%3ESnippet%201%3A%20appSettings.json%3C%2FSTRONG%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-python%22%3E%3CCODE%3E%7B%0A%20%20%20%20%22configs%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%22provider%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22tenantId%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22clientId%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22objectId%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22secret%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22subscriptionId%22%3A%20%22%22%2C%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22dataShareResourceGroup%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22dataShareAccountName%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22dataShareShareName%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22dataShareInvitation%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22dataShareDataSetName%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22dataShareDataSetMappingName%22%3A%20%22%22%2C%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22storageResourceGroup%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22storageAccountName%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22storageContainerName%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22storageBlobName%22%3A%20%22%22%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%22consumer%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22tenantId%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22clientId%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22objectId%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22secret%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22subscriptionId%22%3A%20%22%22%2C%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22dataShareResourceGroup%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22dataShareAccountName%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22dataShareShareSubscriptionName%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22dataShareInvitation%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22dataShareDataSetName%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22dataShareDataSetMappingName%22%3A%20%22%22%2C%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22storageResourceGroup%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22storageAccountName%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22storageContainerName%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22storageBlobName%22%3A%20%22%22%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%7D%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThat's%20it!%20Now%20that%20you%20have%20everything%20configured%2C%20let%E2%80%99s%20run%20the%20code%20by%20debugging%20through%20the%20important%20lines.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH2%20id%3D%22toc-hId-600653443%22%20id%3D%22toc-hId-600653443%22%3ECode%20walk-through%20and%20execution%3CBR%20%2F%3E%3CBR%20%2F%3E%3C%2FH2%3E%0A%3CP%3E%3CEM%3EProgram.cs%3C%2FEM%3E%20looks%20similar%20to%20the%20code%20given%20below%20in%20Snippet%202.%20Let%E2%80%99s%20have%20a%20look%20within%20the%20Main%20method.%20First%20the%20configurations%20are%20read%20from%20the%20appSettings.json%20that%20you%20have%20just%20filled.%20Following%20this%2C%20a%20Resource%20Group%20is%20created%20(for%20a%20logical%20grouping%20of%20the%20data%20share%20resources%20that%20we%20are%20about%20to%20create).%20Once%20the%20resource%20group%20is%20in%20order%2C%20the%20Data%20Share%20Account%20creation%20code%20is%20invoked%2C%20followed%20immediately%20by%20the%20Share%20creation.%26nbsp%3B%20An%20important%20step%20to%20enable%20the%20data%20sharing%20is%20to%20assign%20the%20Data%20Share%20Account%20the%20Blob%20Reader%20role%20on%20the%20underlying%20provider%20storage%20account.%20Finally%20on%20the%20provider%20side%2C%20Data%20Sets%20are%20created%20and%20an%20invitation%20is%20sent%20to%20the%20consumer.%3CBR%20%2F%3E%3CBR%20%2F%3E%3C%2FP%3E%0A%3CP%3E%3CEM%3E%3CSTRONG%3ENote%3A%20the%20AAD%20application%20should%20have%20permission%20to%20create%20resources%20in%20the%20subscription%20configured%20and%20the%20Microsoft.DataShare%20resource%20provider%20should%20be%20registered%20in%20the%20subscriptions%20configured%20in%20appSettings.json.%3CBR%20%2F%3E%3CBR%20%2F%3E%3C%2FSTRONG%3E%3C%2FEM%3E%3C%2FP%3E%0A%3CP%3EOn%20the%20consumer%20side%2C%20a%20similar%20flow%20is%20followed.%20The%20consumer%20Data%20Share%20Account%20is%20created%2C%26nbsp%3B%20and%20subsequently%20the%20invitation%20is%20accepted%20by%20creating%20a%20Share%20Subscription.%20On%20the%20consumer%20side%2C%20the%20account%20Id%20is%20assigned%20a%20Blob%20writer%20role%20on%20the%20underlying%20consumer%20data%20store.%20A%20Data%20Set%20Mapping%20is%20created%20to%20link%20the%20Data%20Set%20received%20on%20the%20consumer%20side%20to%20the%20consumer%20data%20store.%20Finally%2C%20a%20data%20Synchronization%20is%20initiated%20and%20the%20result%20reported.%3CBR%20%2F%3E%3CBR%20%2F%3E%3C%2FP%3E%0A%3CP%3EGo%20ahead%20and%20execute%20the%20code%20or%20debug%20through%20it%20line%20by%20line%20to%20gain%20a%20better%20understanding.%20You%20should%20be%20able%20to%20track%20the%20resource%20creation%20on%20Azure%20Portal%20while%20the%20code%20executes.%20Further%2C%20the%20blob%20from%20the%20provider%20blob%20store%20would%20appear%20on%20the%20consumer%20blob%20store%20at%20the%20end%20of%20a%20successful%20synchronize%20call.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSTRONG%3ESnippet%202%3A%20Program.cs%3C%2FSTRONG%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-csharp%22%3E%3CCODE%3E%2F%2F%20-----------------------------------------------------------------------%0A%2F%2F%20%20%3CCOPYRIGHT%20file%3D%22Program.cs%22%20company%3D%22Microsoft%20Corporation%22%3E%0A%2F%2F%20%20%20%20%20%20Copyright%20(C)%20Microsoft%20Corporation.%20All%20rights%20reserved.%0A%2F%2F%20%20%3C%2FCOPYRIGHT%3E%0A%2F%2F%20-----------------------------------------------------------------------%0A%0Anamespace%20DataShareSample%0A%7B%0A%20%20%20%20using%20System%3B%0A%20%20%20%20using%20System.IO%3B%0A%20%20%20%20using%20System.Threading.Tasks%3B%0A%20%20%20%20using%20Microsoft.Azure.Management.DataShare.Models%3B%0A%20%20%20%20using%20Microsoft.Azure.Management.ResourceManager.Fluent%3B%0A%20%20%20%20using%20Microsoft.Extensions.Configuration%3B%0A%0A%20%20%20%20public%20class%20Program%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20public%20static%20async%20Task%20Main(string%5B%5D%20args)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Console.WriteLine(%22%5Cr%5Cn%5Cr%5CnReading%20the%20configurations...%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20IConfigurationRoot%20configurationRoot%20%3D%20new%20ConfigurationBuilder()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile(%22AppSettings.json%22).Build()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20configuration%20%3D%20configurationRoot.GetSection(%22configs%22).Get%3CCONFIGURATION%3E()%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Console.WriteLine(%22%5Cr%5Cn%5Cr%5CnIdempotent%20creates%20for%20provider%20resources...%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20providerContext%20%3D%20new%20UserContext(configuration.Provider)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20IResourceGroup%20providerResourceGroup%20%3D%20providerContext.IdempotentCreateResourceGroup()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Account%20providerAccount%20%3D%20providerContext.IdempotentCreateAccount()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Share%20share%20%3D%20providerContext.IdempotentCreateShare()%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Console.WriteLine(%24%22%5Cr%5Cn%5Cr%5CnAssign%20MSI%20of%20%7BproviderAccount.Id%7D%20as%20the%20Blob%20Reader%20on%20the%20Provider%20Storage...%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20await%20providerContext.AssignRoleTaskAsync(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20configuration.Provider%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20providerAccount.Identity.PrincipalId%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%222a2b9908-6ea1-4ae2-8e65-a410df84e7d1%22)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Console.WriteLine(%22%5Cr%5Cn%5Cr%5CnCreate%20data%20set%20and%20send%20invitation%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20DataSet%20dataSet%20%3D%20providerContext.CreateIfNotExistDataSet(configuration.Provider)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Invitation%20invitation%20%3D%20providerContext.CreateIfNotExistInvitation(configuration.Consumer)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Console.WriteLine(%22%5Cr%5Cn%5Cr%5CnIdempotent%20creates%20for%20consumer%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20consumerContext%20%3D%20new%20UserContext(configuration.Consumer)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20IResourceGroup%20consumerResourceGroup%20%3D%20consumerContext.IdempotentCreateResourceGroup()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Account%20consumerAccount%20%3D%20consumerContext.IdempotentCreateAccount()%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Console.WriteLine(%22%5Cr%5Cn%5Cr%5CnTo%20accept%20the%20invitation%20create%20a%20share%20subscription%2Freceived%20share...%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20ShareSubscription%20shareSubscription%20%3D%20consumerContext.CreateIfNotExistShareSubscription(invitation)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Console.WriteLine(%24%22%5Cr%5Cn%5Cr%5CnAssign%20MSI%20of%20%7BconsumerAccount.Id%7D%20as%20the%20Blob%20Contributor%20on%20the%20consumer%20Storage...%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20await%20consumerContext.AssignRoleTaskAsync(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20configuration.Consumer%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20consumerAccount.Identity.PrincipalId%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22ba92f5b4-2d11-453d-a403-e96b0029c9fe%22)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Console.WriteLine(%22%5Cr%5Cn%5Cr%5CnCreate%20data%20set%20mapping%20to%20setup%20storage%20for%20the%20consumer%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20ConsumerSourceDataSet%20consumerSourceDataSet%20%3D%20consumerContext.GetConsumerSourceDataSet()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20DataSetMapping%20dataSetMapping%20%3D%20consumerContext.CreateDataSetMapping(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20configuration.Consumer%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20consumerSourceDataSet)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Console.WriteLine(%22%5Cr%5Cn%5Cr%5CnInitiate%20a%20snapshot%20copy%20(duration%20depends%20on%20how%20large%20the%20data%20is)...%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20ShareSubscriptionSynchronization%20response%20%3D%20consumerContext.Synchronize()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Console.WriteLine(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24%22Synchronization%20Status%3A%20%7Bresponse.Status%7D.%20Check%20resource%20%7BconsumerAccount.Id%7D%20on%20%3CA%20href%3D%22https%3A%2F%2Fportal.azure.com%22%20target%3D%22_blank%22%20rel%3D%22nofollow%20noopener%20noreferrer%20noopener%20noreferrer%22%3Ehttps%3A%2F%2Fportal.azure.com%3C%2FA%3E%20for%20further%20details.%20%5Cr%5Cn%5Cr%5Cn%20Hit%20Enter%20to%20continue...%22)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Console.ReadLine()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%3C%2FCONFIGURATION%3E%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThe%20overall%20program%20flow%20can%20be%20summarized%20by%20Figure%201.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-center%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F161171iDDEFD86A356CB07F%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20alt%3D%22clipboard_image_1.png%22%20title%3D%22clipboard_image_1.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%20style%3D%22text-align%3A%20center%3B%22%3EFigure%201%3A%20Sharing%20Model%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH1%20id%3D%22toc-hId-590150339%22%20id%3D%22toc-hId-590150339%22%3E%3CFONT%20size%3D%225%22%3EAdditional%20Capabilities%3A%20Scheduled%20Snapshots%3CBR%20%2F%3E%3CBR%20%2F%3E%3C%2FFONT%3E%3C%2FH1%3E%0A%3CP%3EIn%20addition%20to%20the%20above%20process%20of%20triggering%20an%20on-demand%20synchronization%2C%20Data%20Share%20also%20provides%20native%20automation.%20You%20may%20choose%20to%20write%20a%20wrapper%20around%20scheduling%20on-demand%20runs%20or%20use%20the%20scheduled%20synchronization%20feature.%20To%20enable%20this%20cool%20feature%2C%20the%20provider%2C%20at%20the%20time%20of%20creating%20the%20share%2C%20specifies%20a%20snapshot%20schedule%20with%20a%20daily%20or%20hourly%20frequency%20along%20with%20a%20schedule%20start%20time%3B%20the%20consumer%20simply%20needs%20to%20accept%20the%20schedule%20by%20creating%20a%20Trigger%20on%20their%20side%20to%20receive%20automated%20snapshots%20as%20per%20the%20schedule.%20The%20consumer%2C%20of%20course%20always%20has%20the%20option%20to%20disable%20or%20re-enable%20the%20schedule.%20This%20is%20specifically%20useful%20for%20daily%2Fhourly%20reports%20or%20non-real-time%20incremental%20updates.%20The%20snapshots%20taken%20after%20the%20first%20snapshot%20will%20be%20incremental%20in%20case%20the%20schedule%20is%20enabled.%20You%20can%20find%20API%20documentation%20for%20this%20at%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fbs-latn-ba%2Frest%2Fapi%2Fdatashare%2Fsynchronizationsettings%2Fcreate%3Fview%3Dazurermps-6.8.1%22%20target%3D%22_self%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3ESynchronization%20Settings%3C%2FA%3E%20and%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fbs-latn-ba%2Frest%2Fapi%2Fdatashare%2Ftriggers%2Fcreate%3Fview%3Dazurermps-6.8.1%22%20target%3D%22_self%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3ETriggers%3C%2FA%3E%26nbsp%3B%26nbsp%3B.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CFONT%20size%3D%225%22%3EConclusion%3CBR%20%2F%3E%3CBR%20%2F%3E%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%3EWith%20the%20Azure%20Data%20Share%E2%80%99s%20easy-to-use%20.NET%20SDK%2C%20you%20can%20now%20take%20control%20of%20sharing%20big%20data%20across%20organizations%20and%20geographies%20and%20through%20a%20single%20pane-of-glass%20create%20and%20manage%20all%20your%20sharing%20relationships%20at%20scale.%20For%20further%20reading%20please%20refer%20to%20our%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdata-share%2F.%22%20target%3D%22_self%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3Epublic%20documentation%3C%2FA%3E.%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-TEASER%20id%3D%22lingo-teaser-1061191%22%20slang%3D%22en-US%22%3E%3CP%3EAzure%20Data%20Share%2C%20now%20a%20generally%20available%20service%2C%20makes%20it%20very%20simple%20to%20share%20your%20organization%E2%80%99s%20data%20securely%20with%20your%20partners.%20You%20may%20have%20already%20seen%20and%20tried%20it%20on%20the%20Azure%20Portal%20to%20share%20data%20swiftly%2C%20without%20writing%20any%20code.%20But%20what%20if%20you%20want%20to%20scale%20your%20sharing%20needs%20to%20thousands%20of%20customers%20spread%20across%20the%20world%3F%20Data%20Share%20offers%20a%20rich%20API%2FSDK%20for%20you%20to%20leverage%20and%20scale%20your%20sharing%20relationships%20seamlessly.%20Let%E2%80%99s%20jump%20right%20in%20and%20walk%20through%20a%20sample%20use%20case%20using%20the%20.NET%20SDK.%3C%2FP%3E%3C%2FLINGO-TEASER%3E%3CLINGO-LABS%20id%3D%22lingo-labs-1061191%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3ESDK%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3ETutorial%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E
Microsoft

Azure Data Share, now a generally available service, makes it very simple to share your organization’s data securely with your partners. You may have already seen and tried it on the Azure Portal to share data swiftly, without writing any code. But what if you want to scale your sharing needs to thousands of customers spread across the world? Data Share offers a rich API/SDK for you to leverage and scale your sharing relationships seamlessly. Let’s jump right in and walk through a sample use case using the .NET SDK.

 

Why use the .NET SDK?

 

Imagine the following situation: Your organization provides data to some partners and consumes data from others, where these partners can be departments within your company or external organizations. Using Data Shares's portal experience for creating and managing the first few sharing relationships is quick and intuitive. However, as the number of sharing relationships grows larger, the process would soon grow tedious. Imagine managing potentially hundreds or even thousands of sharing relationships. This would become manually unscalable. We’ve designed the Data Share SDK for ease-of-use, to facilitate the scaling of your organization’s sharing needs.

 

Scenario

Since we would like to demonstrate both the data provider’s and consumer’s perspectives, let’s try a common customer scenario of sharing between departments of the same organization. Specifically, suppose the provider department (say Marketing) has its data in a blob store and wants to share that with a different department (say Sales). To make this sharing more interesting, we’ll try to share the data to a different tenant. Let's see how the Data Share SDK can be used for this.

 

Setting up the Console Application

Getting a copy of the sample code

Start by cloning the sample Git repository: by typing on the command prompt:

 

git clone https://github.com/Azure-Samples/azure-data-share-dotnet-api-sample.git

 


Creating a Service Principal for the Console Application

We'll use active directory application Id and secret for authenticating the console application. For this, an Azure Active Directory (AAD) application must be created each for the provider and the consumer. Follow this tutorial to set up the AAD application.

 

Creating Storage Accounts

The console application will share data from the provider data share account to the consumer data share account, each of which will point to an underlying data store. For this demo you will need to create a storage account each for the provider and consumer. Please follow this tutorial to create the storage accounts. Also ensure that the Service Principal created in the previous section has "Owner" role on the storage accounts. To learn how to add role assignment to resources, please follow this tutorial.

 

Configuring the run-time settings

Once the repository has been cloned, navigate to the file DataShareSample.sln and open it. By default, it should open in Visual studio 2017. Try to build the solution and make sure everything compiles correctly.

 

Now we will go ahead and configure the run-time settings in the appSettings.json file (shown in Snippet 1):

 

Snippet 1: appSettings.json

 

{
    "configs": {
        "provider": {
            "tenantId": "",
            "clientId": "",
            "objectId": "",
            "secret": "",
            "subscriptionId": "",

            "dataShareResourceGroup": "",
            "dataShareAccountName": "",
            "dataShareShareName": "",
            "dataShareInvitation": "",
            "dataShareDataSetName": "",
            "dataShareDataSetMappingName": "",

            "storageResourceGroup": "",
            "storageAccountName": "",
            "storageContainerName": "",
            "storageBlobName": ""
          },
        "consumer": {
            "tenantId": "",
            "clientId": "",
            "objectId": "",
            "secret": "",
            "subscriptionId": "",

            "dataShareResourceGroup": "",
            "dataShareAccountName": "",
            "dataShareShareSubscriptionName": "",
            "dataShareInvitation": "",
            "dataShareDataSetName": "",
            "dataShareDataSetMappingName": "",

            "storageResourceGroup": "",
            "storageAccountName": "",
            "storageContainerName": "",
            "storageBlobName": ""
          }
      }
  }

 

 

That's it! Now that you have everything configured, let’s run the code by debugging through the important lines.

 

Code walk-through and execution

Program.cs looks similar to the code given below in Snippet 2. Let’s have a look within the Main method. First the configurations are read from the appSettings.json that you have just filled. Following this, a Resource Group is created (for a logical grouping of the data share resources that we are about to create). Once the resource group is in order, the Data Share Account creation code is invoked, followed immediately by the Share creation.  An important step to enable the data sharing is to assign the Data Share Account the Blob Reader role on the underlying provider storage account. Finally on the provider side, Data Sets are created and an invitation is sent to the consumer.

Note: the AAD application should have permission to create resources in the subscription configured and the Microsoft.DataShare resource provider should be registered in the subscriptions configured in appSettings.json.

On the consumer side, a similar flow is followed. The consumer Data Share Account is created,  and subsequently the invitation is accepted by creating a Share Subscription. On the consumer side, the account Id is assigned a Blob writer role on the underlying consumer data store. A Data Set Mapping is created to link the Data Set received on the consumer side to the consumer data store. Finally, a data Synchronization is initiated and the result reported.

Go ahead and execute the code or debug through it line by line to gain a better understanding. You should be able to track the resource creation on Azure Portal while the code executes. Further, the blob from the provider blob store would appear on the consumer blob store at the end of a successful synchronize call.

 

Snippet 2: Program.cs

 

// -----------------------------------------------------------------------
//  <copyright file="Program.cs" company="Microsoft Corporation">
//      Copyright (C) Microsoft Corporation. All rights reserved.
//  </copyright>
// -----------------------------------------------------------------------

namespace DataShareSample
{
    using System;
    using System.IO;
    using System.Threading.Tasks;
    using Microsoft.Azure.Management.DataShare.Models;
    using Microsoft.Azure.Management.ResourceManager.Fluent;
    using Microsoft.Extensions.Configuration;

    public class Program
    {
        public static async Task Main(string[] args)
        {
            Console.WriteLine("\r\n\r\nReading the configurations...");
            IConfigurationRoot configurationRoot = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("AppSettings.json").Build();
            var configuration = configurationRoot.GetSection("configs").Get<Configuration>();

            Console.WriteLine("\r\n\r\nIdempotent creates for provider resources...");
            var providerContext = new UserContext(configuration.Provider);
            IResourceGroup providerResourceGroup = providerContext.IdempotentCreateResourceGroup();
            Account providerAccount = providerContext.IdempotentCreateAccount();
            Share share = providerContext.IdempotentCreateShare();

            Console.WriteLine($"\r\n\r\nAssign MSI of {providerAccount.Id} as the Blob Reader on the Provider Storage...");
            await providerContext.AssignRoleTaskAsync(
                configuration.Provider,
                providerAccount.Identity.PrincipalId,
                "2a2b9908-6ea1-4ae2-8e65-a410df84e7d1");

            Console.WriteLine("\r\n\r\nCreate data set and send invitation");
            DataSet dataSet = providerContext.CreateIfNotExistDataSet(configuration.Provider);

            Invitation invitation = providerContext.CreateIfNotExistInvitation(configuration.Consumer);

            Console.WriteLine("\r\n\r\nIdempotent creates for consumer");
            var consumerContext = new UserContext(configuration.Consumer);
            IResourceGroup consumerResourceGroup = consumerContext.IdempotentCreateResourceGroup();
            Account consumerAccount = consumerContext.IdempotentCreateAccount();

            Console.WriteLine("\r\n\r\nTo accept the invitation create a share subscription/received share...");
            ShareSubscription shareSubscription = consumerContext.CreateIfNotExistShareSubscription(invitation);

            Console.WriteLine($"\r\n\r\nAssign MSI of {consumerAccount.Id} as the Blob Contributor on the consumer Storage...");
            await consumerContext.AssignRoleTaskAsync(
                configuration.Consumer,
                consumerAccount.Identity.PrincipalId,
                "ba92f5b4-2d11-453d-a403-e96b0029c9fe");

            Console.WriteLine("\r\n\r\nCreate data set mapping to setup storage for the consumer");
            ConsumerSourceDataSet consumerSourceDataSet = consumerContext.GetConsumerSourceDataSet();
            DataSetMapping dataSetMapping = consumerContext.CreateDataSetMapping(
                configuration.Consumer,
                consumerSourceDataSet);

            Console.WriteLine("\r\n\r\nInitiate a snapshot copy (duration depends on how large the data is)...");
            ShareSubscriptionSynchronization response = consumerContext.Synchronize();
            Console.WriteLine(
                $"Synchronization Status: {response.Status}. Check resource {consumerAccount.Id} on https://portal.azure.com for further details. \r\n\r\n Hit Enter to continue...");

            Console.ReadLine();
        }
    }
}

 

 

The overall program flow can be summarized by Figure 1.

 

clipboard_image_1.png

Figure 1: Sharing Model

 

Additional Capabilities: Scheduled Snapshots

In addition to the above process of triggering an on-demand synchronization, Data Share also provides native automation. You may choose to write a wrapper around scheduling on-demand runs or use the scheduled synchronization feature. To enable this cool feature, the provider, at the time of creating the share, specifies a snapshot schedule with a daily or hourly frequency along with a schedule start time; the consumer simply needs to accept the schedule by creating a Trigger on their side to receive automated snapshots as per the schedule. The consumer, of course always has the option to disable or re-enable the schedule. This is specifically useful for daily/hourly reports or non-real-time incremental updates. The snapshots taken after the first snapshot will be incremental in case the schedule is enabled. You can find API documentation for this at Synchronization Settings and Triggers  .

 

Conclusion

With the Azure Data Share’s easy-to-use .NET SDK, you can now take control of sharing big data across organizations and geographies and through a single pane-of-glass create and manage all your sharing relationships at scale. For further reading please refer to our public documentation.