This commit is contained in:
David Lebee 2019-02-12 17:39:16 -05:00
commit b789b367c2
15 changed files with 364 additions and 0 deletions

41
.gitignore vendored Normal file
View File

@ -0,0 +1,41 @@
# Autosave files
*~
# build
[Oo]bj/
[Bb]in/
packages/
TestResults/
# globs
Makefile.in
*.DS_Store
*.sln.cache
*.suo
*.cache
*.pidb
*.userprefs
*.usertasks
config.log
config.make
config.status
aclocal.m4
install-sh
autom4te.cache/
*.user
*.tar.gz
tarballs/
test-results/
Thumbs.db
.vs/
# Mac bundle stuff
*.dmg
*.app
# resharper
*_Resharper.*
*.Resharper
# dotCover
*.dotCover

29
ObjectStorage.sln Normal file
View File

@ -0,0 +1,29 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoweredSoft.ObjectStorage.Core", "PoweredSoft.ObjectStorage.Core\PoweredSoft.ObjectStorage.Core.csproj", "{81070762-4F21-402D-B10E-6285A46F0572}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoweredSoft.ObjectStorage.MongoDB", "PoweredSoft.ObjectStorage.MongoDB\PoweredSoft.ObjectStorage.MongoDB.csproj", "{D430A3A6-5D41-4B4D-9379-5761FB691619}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoweredSoft.ObjectStorage.MongoDB.Tests", "PoweredSoft.ObjectStorage.MongoDB.Tests\PoweredSoft.ObjectStorage.MongoDB.Tests.csproj", "{D8CB2E20-7298-4EEB-9694-C54654B1BD1C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{81070762-4F21-402D-B10E-6285A46F0572}.Debug|x86.ActiveCfg = Debug|Any CPU
{81070762-4F21-402D-B10E-6285A46F0572}.Debug|x86.Build.0 = Debug|Any CPU
{81070762-4F21-402D-B10E-6285A46F0572}.Release|x86.ActiveCfg = Release|Any CPU
{81070762-4F21-402D-B10E-6285A46F0572}.Release|x86.Build.0 = Release|Any CPU
{D430A3A6-5D41-4B4D-9379-5761FB691619}.Debug|x86.ActiveCfg = Debug|Any CPU
{D430A3A6-5D41-4B4D-9379-5761FB691619}.Debug|x86.Build.0 = Debug|Any CPU
{D430A3A6-5D41-4B4D-9379-5761FB691619}.Release|x86.ActiveCfg = Release|Any CPU
{D430A3A6-5D41-4B4D-9379-5761FB691619}.Release|x86.Build.0 = Release|Any CPU
{D8CB2E20-7298-4EEB-9694-C54654B1BD1C}.Debug|x86.ActiveCfg = Debug|Any CPU
{D8CB2E20-7298-4EEB-9694-C54654B1BD1C}.Debug|x86.Build.0 = Debug|Any CPU
{D8CB2E20-7298-4EEB-9694-C54654B1BD1C}.Release|x86.ActiveCfg = Release|Any CPU
{D8CB2E20-7298-4EEB-9694-C54654B1BD1C}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,9 @@
using System;
namespace PoweredSoft.ObjectStorage.Core
{
public interface IObjectStorageClient
{
IObjectStorageCollection<TEntity> GetCollection<TEntity>();
}
}

View File

@ -0,0 +1,16 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace PoweredSoft.ObjectStorage.Core
{
public interface IObjectStorageCollection<TEntity>
{
string CollectionName { get; }
Task<TEntity> AddAsync(TEntity entity, CancellationToken cancellationToken = default(CancellationToken));
Task DeleteAsync(TEntity entity, CancellationToken cancellationToken = default(CancellationToken));
Task<TEntity> UpdateAsync(TEntity entity, CancellationToken cancellationToken = default(CancellationToken));
IQueryable<TEntity> AsQueryable();
}
}

View File

@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Class1.cs" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,20 @@
using System;
using MongoDB.Driver;
using PoweredSoft.ObjectStorage.MongoDB.Tests.Mock;
using PoweredSoft.ObjectStorage.MongoDB.Tests.Mock.Dal;
using Xunit;
namespace PoweredSoft.ObjectStorage.MongoDB.Tests
{
public class CollectionNameAttributeTests
{
[Fact]
public void TestingGetCollection()
{
var objectStorageClient = MongoDatabaseFactory.GetObjectStorageClient();
var collection = objectStorageClient.GetCollection<Contact>();
Assert.NotNull(collection);
Assert.NotNull(collection.CollectionName);
}
}
}

View File

@ -0,0 +1,37 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using PoweredSoft.ObjectStorage.MongoDB.Tests.Mock;
using PoweredSoft.ObjectStorage.MongoDB.Tests.Mock.Dal;
using Xunit;
namespace PoweredSoft.ObjectStorage.MongoDB.Tests
{
public class CrudTests
{
[Fact]
public async Task CreateUpdateThenDelete()
{
var osc = MongoDatabaseFactory.GetObjectStorageClient();
var collection = osc.GetCollection<Contact>();
var contact = await collection.AddAsync(new Contact
{
FirstName = "Chuck",
LastName = "Not Norris"
});
Assert.NotNull(contact);
contact.LastName = "Norris";
var updatedContact = await collection.UpdateAsync(contact);
Assert.Equal("Norris", updatedContact.LastName);
// delete the test.
await collection.DeleteAsync(updatedContact);
// check that it was deleted.
var shouldBeNull = collection.AsQueryable().FirstOrDefault(t => t.Id == updatedContact.Id);
Assert.Null(shouldBeNull);
}
}
}

View File

@ -0,0 +1,17 @@
using System;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace PoweredSoft.ObjectStorage.MongoDB.Tests.Mock.Dal
{
[MongoCollection("contacts")]
public class Contact
{
[BsonId, BsonElement("id")]
public ObjectId Id { get; set; }
[BsonElement("firstName")]
public string FirstName { get; set; }
[BsonElement("lastName")]
public string LastName { get; set; }
}
}

View File

@ -0,0 +1,14 @@
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace PoweredSoft.ObjectStorage.MongoDB.Tests.Mock.Dal
{
[MongoCollection("tags")]
public class Tag
{
[BsonId, BsonElement("id")]
public ObjectId Id { get; set; }
[BsonElement("name")]
public string Name { get; set; }
}
}

View File

@ -0,0 +1,26 @@
using System;
using MongoDB.Driver;
namespace PoweredSoft.ObjectStorage.MongoDB.Tests.Mock
{
public class MongoDatabaseFactory
{
public static IMongoDatabase GetDatabase()
{
var client = GetClient();
var db = client.GetDatabase("acme");
return db;
}
public static MongoObjectStorageClient GetObjectStorageClient()
{
return new MongoObjectStorageClient(GetDatabase());
}
public static IMongoClient GetClient()
{
var mongoClient = new MongoClient();
return mongoClient;
}
}
}

View File

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
<PackageReference Include="PoweredSoft.DynamicLinq" Version="1.1.7" />
</ItemGroup>
<ItemGroup>
<Folder Include="Mock\" />
<Folder Include="Mock\Dal\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PoweredSoft.ObjectStorage.Core\PoweredSoft.ObjectStorage.Core.csproj" />
<ProjectReference Include="..\PoweredSoft.ObjectStorage.MongoDB\PoweredSoft.ObjectStorage.MongoDB.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,14 @@
using System;
namespace PoweredSoft.ObjectStorage.MongoDB
{
[AttributeUsage(AttributeTargets.Class)]
public class MongoCollectionAttribute : Attribute
{
public MongoCollectionAttribute(string name)
{
Name = name;
}
public string Name { get; }
}
}

View File

@ -0,0 +1,28 @@
using System;
using System.Reflection;
using MongoDB.Driver;
using PoweredSoft.ObjectStorage.Core;
namespace PoweredSoft.ObjectStorage.MongoDB
{
public class MongoObjectStorageClient : IObjectStorageClient
{
public MongoObjectStorageClient(IMongoDatabase database)
{
Database = database;
}
public IMongoDatabase Database { get; }
public IObjectStorageCollection<TEntity> GetCollection<TEntity>()
{
var attribute = typeof(TEntity).GetCustomAttribute<MongoCollectionAttribute>();
if (attribute == null)
throw new Exception("Must add MongoCollectionAttribute on entity class to use this method.");
var mongoCollection = Database.GetCollection<TEntity>(attribute.Name);
var ret = new MongoObjectStorageCollection<TEntity>(mongoCollection);
return ret;
}
}
}

View File

@ -0,0 +1,67 @@
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
using PoweredSoft.DynamicLinq.Helpers;
using PoweredSoft.ObjectStorage.Core;
namespace PoweredSoft.ObjectStorage.MongoDB
{
public class MongoObjectStorageCollection<TEntity> : IObjectStorageCollection<TEntity>
{
public MongoObjectStorageCollection(IMongoCollection<TEntity> collection)
{
if (collection == null)
throw new ArgumentNullException("collection");
Collection = collection;
}
public string CollectionName => Collection.CollectionNamespace.CollectionName;
public IMongoCollection<TEntity> Collection { get; }
public async Task<TEntity> AddAsync(TEntity entity, CancellationToken cancellationToken = default(CancellationToken))
{
await Collection.InsertOneAsync(entity, cancellationToken: cancellationToken);
return entity;
}
public IQueryable<TEntity> AsQueryable()
{
return Collection.AsQueryable();
}
protected virtual Expression<Func<TEntity, bool>> CreateEntityExpression(TEntity entity)
{
var objectKey = typeof(TEntity)
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.FirstOrDefault(t => t.GetCustomAttribute<BsonIdAttribute>() != null);
if (objectKey == null)
throw new Exception("Must have a BsonIdAttribute on one of the properties.");
var constant = objectKey.GetValue(entity);
var expression = QueryableHelpers.CreateConditionExpression<TEntity>(objectKey.Name,
DynamicLinq.ConditionOperators.Equal, constant, DynamicLinq.QueryConvertStrategy.LeaveAsIs);
return expression;
}
public async Task DeleteAsync(TEntity entity, CancellationToken cancellationToken = default(CancellationToken))
{
var expression = CreateEntityExpression(entity);
await Collection.DeleteOneAsync(expression);
}
public async Task<TEntity> UpdateAsync(TEntity entity, CancellationToken cancellationToken = default(CancellationToken))
{
var expression = CreateEntityExpression(entity);
await Collection.ReplaceOneAsync(expression, entity);
return entity;
}
}
}

View File

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\PoweredSoft.ObjectStorage.Core\PoweredSoft.ObjectStorage.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MongoDB.Driver" Version="2.7.3" />
<PackageReference Include="PoweredSoft.DynamicLinq" Version="1.1.7" />
</ItemGroup>
</Project>