Skip to content

Commit 2d07034

Browse files
Merge pull request #538 from johelvisguzman/issue535
Added new azure storage service repository context providers
2 parents 8fca0ec + dfd65f0 commit 2d07034

File tree

64 files changed

+1337
-226
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+1337
-226
lines changed

DotNetToolkit.Repository.sln

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetToolkit.Repository.Ca
4747
EndProject
4848
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetToolkit.Repository.Extensions.Ninject", "src\DotNetToolkit.Repository.Extensions.Ninject\DotNetToolkit.Repository.Extensions.Ninject.csproj", "{BC5B405A-725D-47EC-8FE1-D420CFED8939}"
4949
EndProject
50-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetToolkit.Repository.Caching.Couchbase", "src\DotNetToolkit.Repository.Caching.Couchbase\DotNetToolkit.Repository.Caching.Couchbase.csproj", "{45E365E2-B249-4AB8-AC90-8C0CDE5CC61D}"
50+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetToolkit.Repository.Caching.Couchbase", "src\DotNetToolkit.Repository.Caching.Couchbase\DotNetToolkit.Repository.Caching.Couchbase.csproj", "{45E365E2-B249-4AB8-AC90-8C0CDE5CC61D}"
51+
EndProject
52+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetToolkit.Repository.AzureStorageBlob", "src\DotNetToolkit.Repository.AzureStorageBlob\DotNetToolkit.Repository.AzureStorageBlob.csproj", "{6B934185-F853-4664-B90A-B923690461D8}"
53+
EndProject
54+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetToolkit.Repository.AzureStorageTable", "src\DotNetToolkit.Repository.AzureStorageTable\DotNetToolkit.Repository.AzureStorageTable.csproj", "{567784ED-4989-4664-A8F5-E7AA31107A3C}"
5155
EndProject
5256
Global
5357
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -130,6 +134,14 @@ Global
130134
{45E365E2-B249-4AB8-AC90-8C0CDE5CC61D}.Debug|Any CPU.Build.0 = Debug|Any CPU
131135
{45E365E2-B249-4AB8-AC90-8C0CDE5CC61D}.Release|Any CPU.ActiveCfg = Release|Any CPU
132136
{45E365E2-B249-4AB8-AC90-8C0CDE5CC61D}.Release|Any CPU.Build.0 = Release|Any CPU
137+
{6B934185-F853-4664-B90A-B923690461D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
138+
{6B934185-F853-4664-B90A-B923690461D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
139+
{6B934185-F853-4664-B90A-B923690461D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
140+
{6B934185-F853-4664-B90A-B923690461D8}.Release|Any CPU.Build.0 = Release|Any CPU
141+
{567784ED-4989-4664-A8F5-E7AA31107A3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
142+
{567784ED-4989-4664-A8F5-E7AA31107A3C}.Debug|Any CPU.Build.0 = Debug|Any CPU
143+
{567784ED-4989-4664-A8F5-E7AA31107A3C}.Release|Any CPU.ActiveCfg = Release|Any CPU
144+
{567784ED-4989-4664-A8F5-E7AA31107A3C}.Release|Any CPU.Build.0 = Release|Any CPU
133145
EndGlobalSection
134146
GlobalSection(SolutionProperties) = preSolution
135147
HideSolutionNode = FALSE
@@ -154,6 +166,8 @@ Global
154166
{421F9CC1-9A5F-4F3D-A851-AB72958A4E96} = {DD273D5E-6D6C-41FA-A0C8-646CC53C4DC3}
155167
{BC5B405A-725D-47EC-8FE1-D420CFED8939} = {DD273D5E-6D6C-41FA-A0C8-646CC53C4DC3}
156168
{45E365E2-B249-4AB8-AC90-8C0CDE5CC61D} = {DD273D5E-6D6C-41FA-A0C8-646CC53C4DC3}
169+
{6B934185-F853-4664-B90A-B923690461D8} = {DD273D5E-6D6C-41FA-A0C8-646CC53C4DC3}
170+
{567784ED-4989-4664-A8F5-E7AA31107A3C} = {DD273D5E-6D6C-41FA-A0C8-646CC53C4DC3}
157171
EndGlobalSection
158172
GlobalSection(ExtensibilityGlobals) = postSolution
159173
SolutionGuid = {96973E0C-81D1-42DE-9F78-7103241B4E07}

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,18 @@ If you want to use DotNetToolkit.Repository for the first time, the [Getting Sta
7474
<td><a href="https://www.nuget.org/packages/DotNetToolkit.Repository.EntityFrameworkCore/"><img src="https://img.shields.io/nuget/v/DotNetToolkit.Repository.EntityFrameworkCore.svg" alt="DotNetToolkit.Repository.EntityFrameworkCore"></a></td>
7575
<td><a href="https://www.nuget.org/packages/DotNetToolkit.Repository.EntityFrameworkCore/"><img src="https://img.shields.io/nuget/dt/DotNetToolkit.Repository.EntityFrameworkCore.svg" alt="DotNetToolkit.Repository.EntityFrameworkCore"></a></td>
7676
<td><a href="https://www.myget.org/feed/dotnettoolkitrepository-dev/package/nuget/DotNetToolkit.Repository.EntityFrameworkCore"><img src="https://img.shields.io/myget/dotnettoolkitrepository-dev/v/DotNetToolkit.Repository.EntityFrameworkCore.svg?label=myget" alt="MyGet (dev)"></a></td>
77+
</tr>
78+
<tr>
79+
<td><a href="https://github.com/johelvisguzman/DotNetToolkit.Repository/tree/master/src/DotNetToolkit.Repository.AzureStorageBlob/">DotNetToolkit.Repository.AzureStorageBlob</a></td>
80+
<td><a href="https://www.nuget.org/packages/DotNetToolkit.Repository.AzureStorageBlob/"><img src="https://img.shields.io/nuget/v/DotNetToolkit.Repository.AzureStorageBlob.svg" alt="DotNetToolkit.Repository.AzureStorageBlob"></a></td>
81+
<td><a href="https://www.nuget.org/packages/DotNetToolkit.Repository.AzureStorageBlob/"><img src="https://img.shields.io/nuget/dt/DotNetToolkit.Repository.AzureStorageBlob.svg" alt="DotNetToolkit.Repository.AzureStorageBlob"></a></td>
82+
<td><a href="https://www.myget.org/feed/dotnettoolkitrepository-dev/package/nuget/DotNetToolkit.Repository.AzureStorageBlob"><img src="https://img.shields.io/myget/dotnettoolkitrepository-dev/v/DotNetToolkit.Repository.AzureStorageBlob.svg?label=myget" alt="MyGet (dev)"></a></td>
83+
</tr>
84+
<tr>
85+
<td><a href="https://github.com/johelvisguzman/DotNetToolkit.Repository/tree/master/src/DotNetToolkit.Repository.AzureStorageTable/">DotNetToolkit.Repository.AzureStorageTable</a></td>
86+
<td><a href="https://www.nuget.org/packages/DotNetToolkit.Repository.AzureStorageTable/"><img src="https://img.shields.io/nuget/v/DotNetToolkit.Repository.AzureStorageTable.svg" alt="DotNetToolkit.Repository.AzureStorageTable"></a></td>
87+
<td><a href="https://www.nuget.org/packages/DotNetToolkit.Repository.AzureStorageTable/"><img src="https://img.shields.io/nuget/dt/DotNetToolkit.Repository.AzureStorageTable.svg" alt="DotNetToolkit.Repository.AzureStorageTable"></a></td>
88+
<td><a href="https://www.myget.org/feed/dotnettoolkitrepository-dev/package/nuget/DotNetToolkit.Repository.AzureStorageTable"><img src="https://img.shields.io/myget/dotnettoolkitrepository-dev/v/DotNetToolkit.Repository.AzureStorageTable.svg?label=myget" alt="MyGet (dev)"></a></td>
7789
</tr>
7890
<tr>
7991
<th colspan="4">Caching Providers</th>
@@ -135,4 +147,4 @@ If you want more details about the project, please checkout the [project wiki](h
135147

136148
## Performance
137149

138-
Checkout the most current [benchmark results](https://github.com/johelvisguzman/DotNetToolkit.Repository/wiki/Performance)!
150+
Checkout the most current [benchmark results](https://github.com/johelvisguzman/DotNetToolkit.Repository/wiki/Performance)!

appveyor.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ after_build:
5454
- dotnet pack .\src\DotNetToolkit.Repository.NHibernate\DotNetToolkit.Repository.NHibernate.csproj --configuration Release
5555
- dotnet pack .\src\DotNetToolkit.Repository.Json\DotNetToolkit.Repository.Json.csproj --configuration Release
5656
- dotnet pack .\src\DotNetToolkit.Repository.Xml\DotNetToolkit.Repository.Xml.csproj --configuration Release
57+
- dotnet pack .\src\DotNetToolkit.Repository.AzureStorageBlob\DotNetToolkit.Repository.AzureStorageBlob.csproj --configuration Release
58+
- dotnet pack .\src\DotNetToolkit.Repository.AzureStorageTable\DotNetToolkit.Repository.AzureStorageTable.csproj --configuration Release
5759
- dotnet pack .\src\DotNetToolkit.Repository.Extensions.Microsoft.DependencyInjection\DotNetToolkit.Repository.Extensions.Microsoft.DependencyInjection.csproj --configuration Release
5860
- dotnet pack .\src\DotNetToolkit.Repository.Extensions.Unity\DotNetToolkit.Repository.Extensions.Unity.csproj --configuration Release
5961
- dotnet pack .\src\DotNetToolkit.Repository.Extensions.Ninject\DotNetToolkit.Repository.Extensions.Ninject.csproj --configuration Release
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<Import Project="..\..\build\common.props" />
4+
5+
<PropertyGroup>
6+
<TargetFrameworks>net452;netstandard2.0</TargetFrameworks>
7+
<AssemblyName>DotNetToolkit.Repository.AzureStorageBlob</AssemblyName>
8+
<RootNamespace>DotNetToolkit.Repository.AzureStorageBlob</RootNamespace>
9+
<Description>A repository context provider for the Microsoft Azure Storage Blob service for storing binary and text data.</Description>
10+
</PropertyGroup>
11+
12+
<ItemGroup Condition="'$(TargetFramework)' == 'net452'">
13+
<Reference Include="System.Configuration" />
14+
</ItemGroup>
15+
16+
<ItemGroup>
17+
<PackageReference Include="Microsoft.Azure.Storage.Blob" Version="10.0.3" />
18+
</ItemGroup>
19+
20+
<ItemGroup>
21+
<ProjectReference Include="..\DotNetToolkit.Repository\DotNetToolkit.Repository.csproj" />
22+
</ItemGroup>
23+
24+
</Project>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace DotNetToolkit.Repository.AzureStorageBlob
2+
{
3+
using Configuration;
4+
using Microsoft.Azure.Storage.Blob;
5+
6+
/// <summary>
7+
/// Represents a repository context for the Microsoft Azure Storage Blob service for storing binary and text data.
8+
/// </summary>
9+
/// <seealso cref="IRepositoryContext" />
10+
public interface IAzureStorageBlobRepositoryContext : IRepositoryContext
11+
{
12+
/// <summary>
13+
/// Gest the cloud blob container.
14+
/// </summary>
15+
CloudBlobContainer BlobContainer { get; }
16+
}
17+
}
Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
namespace DotNetToolkit.Repository.AzureStorageBlob.Internal
2+
{
3+
using Configuration;
4+
using Configuration.Conventions;
5+
using Extensions;
6+
using Microsoft.Azure.Storage;
7+
using Microsoft.Azure.Storage.Blob;
8+
using Newtonsoft.Json;
9+
using Queries;
10+
using Queries.Strategies;
11+
using System.Collections.Generic;
12+
using System.Configuration;
13+
using System.Linq;
14+
using Utility;
15+
16+
/// <summary>
17+
/// An implementation of <see cref="IAzureStorageBlobRepositoryContext" />.
18+
/// </summary>
19+
/// <seealso cref="IAzureStorageBlobRepositoryContext" />
20+
internal class AzureStorageBlobRepositoryContext : LinqRepositoryContextBase, IAzureStorageBlobRepositoryContext
21+
{
22+
#region Properties
23+
24+
/// <summary>
25+
/// Gest the cloud blob container.
26+
/// </summary>
27+
public CloudBlobContainer BlobContainer { get; }
28+
29+
#endregion
30+
31+
#region Constructors
32+
33+
/// <summary>
34+
/// Initializes a new instance of the <see cref="AzureStorageBlobRepositoryContext" /> class.
35+
/// </summary>
36+
/// <param name="nameOrConnectionString">Either the database name or a connection string.</param>
37+
/// <param name="container">The name of the container.</param>
38+
/// <param name="createIfNotExists">Creates the container if it does not exist.</param>
39+
public AzureStorageBlobRepositoryContext(string nameOrConnectionString, string container = null, bool createIfNotExists = false)
40+
{
41+
Guard.NotEmpty(nameOrConnectionString, nameof(nameOrConnectionString));
42+
43+
Conventions = RepositoryConventions.Default<AzureStorageBlobRepositoryContext>();
44+
45+
var css = GetConnectionStringSettings(nameOrConnectionString);
46+
47+
var connectionString = css != null
48+
? css.ConnectionString
49+
: nameOrConnectionString;
50+
51+
var account = CloudStorageAccount.Parse(connectionString);
52+
var client = account.CreateCloudBlobClient();
53+
54+
if (string.IsNullOrEmpty(container))
55+
container = GetType().Name.ToLower();
56+
57+
BlobContainer = client.GetContainerReference(container);
58+
59+
if (createIfNotExists)
60+
BlobContainer.CreateIfNotExists();
61+
}
62+
63+
#endregion
64+
65+
#region Private Methods
66+
67+
private static ConnectionStringSettings GetConnectionStringSettings(string nameOrConnectionString)
68+
{
69+
var css = ConfigurationManager.ConnectionStrings[nameOrConnectionString];
70+
71+
if (css != null)
72+
return css;
73+
74+
for (var i = 0; i < ConfigurationManager.ConnectionStrings.Count; i++)
75+
{
76+
css = ConfigurationManager.ConnectionStrings[i];
77+
78+
if (css.ConnectionString.Equals(nameOrConnectionString))
79+
return css;
80+
}
81+
82+
return null;
83+
}
84+
85+
private CloudBlockBlob GetBlobkBlobReference(params object[] keyValues)
86+
{
87+
var key = string.Join(":", keyValues);
88+
var blob = BlobContainer.GetBlockBlobReference(key);
89+
90+
return blob;
91+
}
92+
93+
private CloudBlockBlob GetBlobkBlobReference<TEntity>(TEntity entity) where TEntity : class
94+
{
95+
return GetBlobkBlobReference(Conventions.GetPrimaryKeyValues(entity));
96+
}
97+
98+
private IEnumerable<CloudBlockBlob> GetBlobs()
99+
{
100+
BlobContinuationToken continuationToken = null;
101+
102+
do
103+
{
104+
var response = BlobContainer.ListBlobsSegmented(continuationToken);
105+
106+
continuationToken = response.ContinuationToken;
107+
108+
foreach (var blob in response.Results.OfType<CloudBlockBlob>())
109+
{
110+
yield return blob;
111+
}
112+
113+
} while (continuationToken != null);
114+
}
115+
116+
private static string Serialize(object o)
117+
{
118+
if (o == null)
119+
return null;
120+
121+
return JsonConvert.SerializeObject(o, new JsonSerializerSettings()
122+
{
123+
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
124+
});
125+
}
126+
127+
private static T Deserialize<T>(string v)
128+
{
129+
if (string.IsNullOrEmpty(v))
130+
return default(T);
131+
132+
return JsonConvert.DeserializeObject<T>(v);
133+
}
134+
135+
#endregion
136+
137+
#region Overrides of LinqRepositoryContextBase
138+
139+
/// <summary>
140+
/// Returns the entity's query.
141+
/// </summary>
142+
/// <typeparam name="TEntity">The type of the of the entity.</typeparam>
143+
/// <returns>The entity's query.</returns>
144+
protected override IQueryable<TEntity> AsQueryable<TEntity>()
145+
{
146+
return GetBlobs()
147+
.Select(x =>
148+
{
149+
try
150+
{
151+
return Deserialize<TEntity>(x.DownloadText());
152+
}
153+
catch (StorageException storageException)
154+
{
155+
if (storageException.RequestInformation.HttpStatusCode == 404)
156+
return default(TEntity);
157+
158+
throw;
159+
}
160+
})
161+
.AsQueryable();
162+
}
163+
164+
/// <summary>
165+
/// Apply a fetching options to the specified entity's query.
166+
/// </summary>
167+
/// <returns>The entity's query with the applied options.</returns>
168+
protected override IQueryable<TEntity> ApplyFetchingOptions<TEntity>(IQueryable<TEntity> query, IQueryOptions<TEntity> options)
169+
{
170+
if (options?.FetchStrategy?.PropertyPaths?.Any() == true)
171+
Logger.Debug("The azure storage blob context does not support fetching strategy.");
172+
173+
return query;
174+
}
175+
176+
/// <summary>
177+
/// Tracks the specified entity in memory and will be inserted into the database when <see cref="SaveChanges" /> is called.
178+
/// </summary>
179+
/// <typeparam name="TEntity">The type of the entity.</typeparam>
180+
/// <param name="entity">The entity.</param>
181+
public override void Add<TEntity>(TEntity entity)
182+
{
183+
Guard.NotNull(entity, nameof(entity));
184+
185+
var blob = GetBlobkBlobReference(entity);
186+
187+
blob.UploadText(Serialize(entity));
188+
}
189+
190+
/// <summary>
191+
/// Tracks the specified entity in memory and will be updated in the database when <see cref="SaveChanges" /> is called.
192+
/// </summary>
193+
/// <typeparam name="TEntity">The type of the entity.</typeparam>
194+
/// <param name="entity">The entity.</param>
195+
public override void Update<TEntity>(TEntity entity)
196+
{
197+
Guard.NotNull(entity, nameof(entity));
198+
199+
var blob = GetBlobkBlobReference(entity);
200+
201+
blob.UploadText(Serialize(entity));
202+
}
203+
204+
/// <summary>
205+
/// Tracks the specified entity in memory and will be removed from the database when <see cref="SaveChanges" /> is called.
206+
/// </summary>
207+
/// <typeparam name="TEntity">The type of the entity.</typeparam>
208+
/// <param name="entity">The entity.</param>
209+
public override void Remove<TEntity>(TEntity entity)
210+
{
211+
Guard.NotNull(entity, nameof(entity));
212+
213+
var blob = GetBlobkBlobReference(entity);
214+
215+
blob.DeleteIfExists();
216+
}
217+
218+
/// <summary>
219+
/// Saves all changes made in this context to the database.
220+
/// </summary>
221+
/// <returns>The number of state entries written to the database.</returns>
222+
public override int SaveChanges()
223+
{
224+
return -1;
225+
}
226+
227+
/// <summary>
228+
/// Finds an entity with the given primary key values in the repository.
229+
/// </summary>
230+
/// <typeparam name="TEntity">The type of the of the entity.</typeparam>
231+
/// <param name="fetchStrategy">Defines the child objects that should be retrieved when loading the entity.</param>
232+
/// <param name="keyValues">The values of the primary key for the entity to be found.</param>
233+
/// <returns>The entity found in the repository.</returns>
234+
public override TEntity Find<TEntity>(IFetchQueryStrategy<TEntity> fetchStrategy, params object[] keyValues)
235+
{
236+
Guard.NotEmpty(keyValues, nameof(keyValues));
237+
238+
try
239+
{
240+
var blob = GetBlobkBlobReference(keyValues);
241+
242+
return Deserialize<TEntity>(blob.DownloadText());
243+
}
244+
catch (StorageException storageException)
245+
{
246+
if (storageException.RequestInformation.HttpStatusCode == 404)
247+
return default(TEntity);
248+
249+
throw;
250+
}
251+
}
252+
253+
#endregion
254+
}
255+
}

0 commit comments

Comments
 (0)