├── ZensibleMongo.Tests
├── DataExample.cs
├── packages.config
├── Properties
│ └── AssemblyInfo.cs
├── ZensibleMongo.Tests.csproj
└── MongoExtensionTest.cs
├── ZensibleMongo
├── Interfaces
│ ├── ICreateRecipe.cs
│ ├── IDeleteMultiRecipe.cs
│ ├── IDeleteSingleRecipe.cs
│ ├── IFilterRecipeContainer.cs
│ ├── IUpdateMultiRecipe.cs
│ ├── IUpdateSingleRecipe.cs
│ ├── IDeleteRecipe.cs
│ ├── IFilterMultiRecipe.cs
│ ├── IFilterSingleRecipe.cs
│ ├── IMongoCollectionContainer.cs
│ ├── ICreateSingleRecipe.cs
│ ├── ICreateMultiRecipe.cs
│ ├── IFilterRecipe.cs
│ └── IUpdateRecipe.cs
├── Delete
│ ├── DeleteSingleRecipe.cs
│ └── DeleteMultiRecipe.cs
├── Update
│ ├── SetUpdateSingleRecipe.cs
│ └── SetUpdateMultiRecipe.cs
├── packages.config
├── Create
│ ├── CreateSingleRecipe.cs
│ └── CreateMultiRecipe.cs
├── ZensibleMongo.nuspec
├── Filter
│ ├── ForAllRecipe.cs
│ ├── ForIdRecipe.cs
│ ├── ForAllWhereRecipe.cs
│ └── ForFilterSingleWhere.cs
├── DeleteExtension.cs
├── CreateExtension.cs
├── Properties
│ └── AssemblyInfo.cs
├── PullExtension.cs
├── Factory.cs
├── FilterExtension.cs
├── HelpersExtension.cs
├── UpdateExtension.cs
├── PushExtension.cs
└── ZensibleMongo.csproj
├── LICENSE
├── ZensibleMongo.sln
├── .gitattributes
├── README.md
└── .gitignore
/ZensibleMongo.Tests/DataExample.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Tests
2 | {
3 | public struct DataExample
4 | {
5 | public int A { get; set; }
6 | public int B { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/ZensibleMongo/Interfaces/ICreateRecipe.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Interfaces
2 | {
3 | using System.Collections.Immutable;
4 |
5 | ///
6 | /// Inferface for create recipes
7 | ///
8 | ///
9 | public interface ICreateRecipe : IMongoCollectionContainer
10 | {
11 |
12 |
13 |
14 | }
15 | }
--------------------------------------------------------------------------------
/ZensibleMongo/Delete/DeleteSingleRecipe.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Delete
2 | {
3 | using Interfaces;
4 |
5 | ///
6 | /// Recipe for deleting a single document
7 | ///
8 | ///
9 | internal class DeleteSingleRecipe : Recipe, IDeleteSingleRecipe
10 | {
11 | }
12 | }
--------------------------------------------------------------------------------
/ZensibleMongo/Interfaces/IDeleteMultiRecipe.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Interfaces
2 | {
3 | using System.Collections.Immutable;
4 | using MongoDB.Driver;
5 |
6 | ///
7 | /// Inferface for recipes that delete single document
8 | ///
9 | ///
10 | public interface IDeleteMultiRecipe : IDeleteRecipe
11 | {
12 | }
13 | }
--------------------------------------------------------------------------------
/ZensibleMongo/Interfaces/IDeleteSingleRecipe.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Interfaces
2 | {
3 | using System.Collections.Immutable;
4 | using MongoDB.Driver;
5 |
6 | ///
7 | /// Inferface for recipes that delete single document
8 | ///
9 | ///
10 | public interface IDeleteSingleRecipe : IDeleteRecipe
11 | {
12 | }
13 | }
--------------------------------------------------------------------------------
/ZensibleMongo/Interfaces/IFilterRecipeContainer.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Interfaces
2 | {
3 | ///
4 | /// Interface for recipes that contain filters
5 | ///
6 | ///
7 | public interface IFilterRecipeContainer
8 | {
9 | ///
10 | /// Filter
11 | ///
12 | IFilterRecipe FilterRecipe { get; }
13 | }
14 | }
--------------------------------------------------------------------------------
/ZensibleMongo/Interfaces/IUpdateMultiRecipe.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Interfaces
2 | {
3 | using System.Collections.Immutable;
4 | using MongoDB.Driver;
5 |
6 | ///
7 | /// Inferface for update recipe that only updates multiple documents
8 | ///
9 | ///
10 | public interface IUpdateMultiRecipe : IUpdateRecipe
11 | {
12 | }
13 | }
--------------------------------------------------------------------------------
/ZensibleMongo/Interfaces/IUpdateSingleRecipe.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Interfaces
2 | {
3 | using System.Collections.Immutable;
4 | using MongoDB.Driver;
5 |
6 | ///
7 | /// Inferface for update recipe that only updates a single document
8 | ///
9 | ///
10 | public interface IUpdateSingleRecipe : IUpdateRecipe
11 | {
12 | }
13 | }
--------------------------------------------------------------------------------
/ZensibleMongo/Interfaces/IDeleteRecipe.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Interfaces
2 | {
3 | using System.Collections.Immutable;
4 | using MongoDB.Driver;
5 |
6 | ///
7 | /// Inferface for recipes that updates the collection
8 | ///
9 | ///
10 | public interface IDeleteRecipe : IMongoCollectionContainer, IFilterRecipeContainer
11 | {
12 | }
13 | }
--------------------------------------------------------------------------------
/ZensibleMongo/Update/SetUpdateSingleRecipe.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Update
2 | {
3 | using Interfaces;
4 |
5 | ///
6 | /// Recipe for setting a field on a single document
7 | ///
8 | ///
9 | ///
10 | internal class SetUpdateSingleRecipe : SetUpdateMultiRecipe, IUpdateSingleRecipe
11 | {
12 | }
13 | }
--------------------------------------------------------------------------------
/ZensibleMongo/Interfaces/IFilterMultiRecipe.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace ZensibleMongo.Interfaces
8 | {
9 | ///
10 | /// Filter for selecting multiple documents
11 | ///
12 | ///
13 | public interface IFilterMultiRecipe : IFilterRecipe
14 | {
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/ZensibleMongo/Interfaces/IFilterSingleRecipe.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace ZensibleMongo.Interfaces
8 | {
9 | ///
10 | /// A filter to select a single document
11 | ///
12 | ///
13 | public interface IFilterSingleRecipe : IFilterRecipe
14 | {
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/ZensibleMongo/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ZensibleMongo/Interfaces/IMongoCollectionContainer.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Interfaces
2 | {
3 | using MongoDB.Driver;
4 |
5 | ///
6 | /// Interface for mongo collection holders
7 | ///
8 | ///
9 | public interface IMongoCollectionContainer
10 | {
11 | ///
12 | /// Mongo collection
13 | ///
14 | IMongoCollection Collection { get; }
15 | }
16 | }
--------------------------------------------------------------------------------
/ZensibleMongo/Interfaces/ICreateSingleRecipe.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Interfaces
2 | {
3 | using System.Collections.Immutable;
4 |
5 | ///
6 | /// Inferface for single create recipe
7 | ///
8 | ///
9 | public interface ICreateSingleRecipe : ICreateRecipe
10 | {
11 | ///
12 | /// Document to create on the collection
13 | ///
14 | TDocument Document { get; set; }
15 | }
16 | }
--------------------------------------------------------------------------------
/ZensibleMongo/Create/CreateSingleRecipe.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Create
2 | {
3 | using System.Collections.Immutable;
4 | using Interfaces;
5 | using MongoDB.Driver;
6 |
7 | ///
8 | /// Create a single document createMultiRecipe
9 | ///
10 | ///
11 | internal class CreateSingleRecipe : ICreateSingleRecipe
12 | {
13 | public IMongoCollection Collection { get; set; }
14 | public TDocument Document { get; set; }
15 | }
16 | }
--------------------------------------------------------------------------------
/ZensibleMongo/Interfaces/ICreateMultiRecipe.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Interfaces
2 | {
3 | using System.Collections.Immutable;
4 |
5 | ///
6 | /// Inferface for multiple creates recipe
7 | ///
8 | ///
9 | public interface ICreateMultiRecipe : ICreateRecipe
10 | {
11 | ///
12 | /// Immutable list of documents to create
13 | ///
14 | ///
15 | ImmutableList AllDocuments();
16 | }
17 | }
--------------------------------------------------------------------------------
/ZensibleMongo/Interfaces/IFilterRecipe.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Interfaces
2 | {
3 | using System.Collections.Immutable;
4 | using MongoDB.Driver;
5 |
6 | ///
7 | /// Interface for selector recipes
8 | ///
9 | ///
10 | public interface IFilterRecipe : IMongoCollectionContainer
11 | {
12 | ///
13 | /// Immutable list of filters to select with
14 | ///
15 | ///
16 | ImmutableList> Filters();
17 | }
18 | }
--------------------------------------------------------------------------------
/ZensibleMongo/Delete/DeleteMultiRecipe.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Delete
2 | {
3 | using Interfaces;
4 | using MongoDB.Driver;
5 |
6 | ///
7 | /// Delete recipe
8 | ///
9 | ///
10 | internal class Recipe : IDeleteMultiRecipe
11 | {
12 | ///
13 | /// Mongo collection
14 | ///
15 | public IMongoCollection Collection { get; set; }
16 |
17 | ///
18 | /// Selector for delete
19 | ///
20 | public IFilterRecipe FilterRecipe { get; set; }
21 | }
22 | }
--------------------------------------------------------------------------------
/ZensibleMongo/Interfaces/IUpdateRecipe.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Interfaces
2 | {
3 | using System.Collections.Immutable;
4 | using MongoDB.Driver;
5 |
6 | ///
7 | /// Inferface for recipes that updates the collection
8 | ///
9 | ///
10 | public interface IUpdateRecipe : IMongoCollectionContainer, IFilterRecipeContainer
11 | {
12 | ///
13 | /// All update recipes
14 | ///
15 | ///
16 | ImmutableList> UpdateDefinitions();
17 | }
18 | }
--------------------------------------------------------------------------------
/ZensibleMongo/ZensibleMongo.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $id$
5 | $version$
6 | $title$
7 | $author$
8 | $author$
9 | https://github.com/trustpilot/ZensibleMongo/blob/master/LICENSE
10 | https://github.com/trustpilot/ZensibleMongo
11 | http://i.imgur.com/delHwBl.jpg?1
12 | false
13 | $description$
14 | Pull and Push now follows async convention
15 | Copyright 2015
16 | Mongo MongoDb Extension sensible simplify Pure
17 |
18 |
19 |
--------------------------------------------------------------------------------
/ZensibleMongo/Filter/ForAllRecipe.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Filter
2 | {
3 | using System.Collections.Immutable;
4 | using Interfaces;
5 | using MongoDB.Driver;
6 |
7 |
8 | ///
9 | /// For all selector recipe
10 | ///
11 | ///
12 | internal class ForAllRecipe : IFilterMultiRecipe
13 | {
14 | ///
15 | /// Mongo collection
16 | ///
17 | public IMongoCollection Collection { get; set; }
18 |
19 | ///
20 | /// Selector filters
21 | ///
22 | ///
23 | public ImmutableList> Filters()
24 | {
25 | return ImmutableList>.Empty;
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/ZensibleMongo.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/ZensibleMongo/Create/CreateMultiRecipe.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Create
2 | {
3 | using System.Collections.Immutable;
4 | using Interfaces;
5 | using MongoDB.Driver;
6 |
7 | ///
8 | /// Create recipe
9 | ///
10 | ///
11 | internal class CreateMultiRecipe : ICreateMultiRecipe
12 | {
13 | ///
14 | /// Documents
15 | ///
16 | public ImmutableList Documents { get; set; }
17 |
18 | ///
19 | /// Mongo collection
20 | ///
21 | public IMongoCollection Collection { get; set; }
22 |
23 | ///
24 | /// Immutable list of documents to create
25 | ///
26 | ///
27 | public ImmutableList AllDocuments()
28 | {
29 | return Documents;
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/ZensibleMongo/Filter/ForIdRecipe.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Filter
2 | {
3 | using System.Collections.Immutable;
4 | using Interfaces;
5 | using MongoDB.Bson;
6 | using MongoDB.Driver;
7 |
8 | ///
9 | /// For Id Recipe
10 | ///
11 | ///
12 | internal class ForIdRecipe : IFilterSingleRecipe
13 | {
14 | ///
15 | /// Mongo document id
16 | ///
17 | public ObjectId Id { get; set; }
18 |
19 | ///
20 | /// Mongo collection
21 | ///
22 | public IMongoCollection Collection { get; set; }
23 |
24 | ///
25 | /// Selectors
26 | ///
27 | ///
28 | public ImmutableList> Filters()
29 | {
30 | var filter = Builders.Filter.Eq(new StringFieldDefinition("_id"), Id);
31 | return ImmutableList.Create(filter);
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Trustpilot
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/ZensibleMongo/Filter/ForAllWhereRecipe.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Filter
2 | {
3 | using System;
4 | using System.Collections.Immutable;
5 | using System.Linq.Expressions;
6 | using Interfaces;
7 | using MongoDB.Driver;
8 |
9 | ///
10 | /// For all where recipe
11 | ///
12 | ///
13 | internal class ForAllWhereRecipe : IFilterMultiRecipe
14 | {
15 | ///
16 | /// Predicate to satisfy for selection
17 | ///
18 | public Expression> Predicate { get; set; }
19 |
20 | ///
21 | /// Mongo collection
22 | ///
23 | public IMongoCollection Collection { get; set; }
24 |
25 | ///
26 | /// Document selectors
27 | ///
28 | ///
29 | public ImmutableList> Filters()
30 | {
31 | var theFilter = Builders.Filter.Where(Predicate);
32 | return ImmutableList.Create(theFilter);
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/ZensibleMongo/Filter/ForFilterSingleWhere.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Filter
2 | {
3 | using System;
4 | using System.Collections.Immutable;
5 | using System.Linq.Expressions;
6 | using Interfaces;
7 | using MongoDB.Driver;
8 |
9 | ///
10 | /// For a single document where recipe
11 | ///
12 | ///
13 | internal class ForFilterSingleWhere : IFilterSingleRecipe
14 | {
15 | ///
16 | /// Predicate to satisfy for selection
17 | ///
18 | public Expression> Predicate { get; set; }
19 |
20 | ///
21 | /// Mongo collection
22 | ///
23 | public IMongoCollection Collection { get; set; }
24 |
25 | ///
26 | /// Selectors
27 | ///
28 | ///
29 | public ImmutableList> Filters()
30 | {
31 | var theFilter = Builders.Filter.Where(Predicate);
32 | return ImmutableList.Create(theFilter);
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/ZensibleMongo/DeleteExtension.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo
2 | {
3 | using Delete;
4 | using Filter;
5 | using Interfaces;
6 |
7 | ///
8 | /// Extention for all delete recipes
9 | ///
10 | public static class DeleteExtension
11 | {
12 | ///
13 | /// Recipe for deleting multiple documents on the collection.
14 | ///
15 | ///
16 | ///
17 | ///
18 | public static IDeleteMultiRecipe Delete(this IFilterMultiRecipe recipe)
19 | {
20 | return new Recipe { Collection = recipe.Collection, FilterRecipe = recipe };
21 | }
22 |
23 | ///
24 | /// Recipe for deleting a single document on the collection.
25 | ///
26 | ///
27 | ///
28 | ///
29 | public static IDeleteSingleRecipe Delete(this IFilterSingleRecipe recipe)
30 | {
31 | return new DeleteSingleRecipe
32 | {
33 | Collection = recipe.Collection,
34 | FilterRecipe = recipe
35 | };
36 | }
37 |
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/ZensibleMongo.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ZensibleMongo.Tests")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ZensibleMongo.Tests")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("51a32c41-be8f-4325-9e2f-5e52c3598de7")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/ZensibleMongo.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.23107.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZensibleMongo", "ZensibleMongo\ZensibleMongo.csproj", "{C578346C-AA39-4E6F-BA5D-9708D44A8FC1}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZensibleMongo.Tests", "ZensibleMongo.Tests\ZensibleMongo.Tests.csproj", "{51A32C41-BE8F-4325-9E2F-5E52C3598DE7}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {C578346C-AA39-4E6F-BA5D-9708D44A8FC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {C578346C-AA39-4E6F-BA5D-9708D44A8FC1}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {C578346C-AA39-4E6F-BA5D-9708D44A8FC1}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {C578346C-AA39-4E6F-BA5D-9708D44A8FC1}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {51A32C41-BE8F-4325-9E2F-5E52C3598DE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {51A32C41-BE8F-4325-9E2F-5E52C3598DE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {51A32C41-BE8F-4325-9E2F-5E52C3598DE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {51A32C41-BE8F-4325-9E2F-5E52C3598DE7}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | EndGlobal
29 |
--------------------------------------------------------------------------------
/ZensibleMongo/CreateExtension.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo
2 | {
3 | using System.Collections.Immutable;
4 | using Create;
5 | using Interfaces;
6 | using MongoDB.Driver;
7 |
8 | ///
9 | /// Create extension
10 | ///
11 | public static class CreateExtension
12 | {
13 | ///
14 | /// Recipe for creating multiple documents on the collection.
15 | ///
16 | ///
17 | ///
18 | /// Documents to be created.
19 | ///
20 | public static ICreateMultiRecipe Create(this IMongoCollection collection, params TDocument[] documents)
21 | {
22 | return new CreateMultiRecipe { Collection = collection, Documents = ImmutableList.Create(documents) };
23 | }
24 |
25 |
26 | ///
27 | /// Recipe for creating a single document on the collection.
28 | ///
29 | ///
30 | ///
31 | /// Document to be created.
32 | ///
33 | public static ICreateSingleRecipe Create(this IMongoCollection collection, TDocument document)
34 | {
35 | return new CreateSingleRecipe { Collection = collection, Document = document };
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/ZensibleMongo/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Zensible Mongo")]
9 | [assembly: AssemblyDescription("An extension library for simplifying mongo c# driver, more details can be found at https://github.com/trustpilot/ZensibleMongo")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Jannick Johnsen")]
12 | [assembly: AssemblyProduct("ZensibleMongo")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("c578346c-aa39-4e6f-ba5d-9708d44a8fc1")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.1.0.3")]
36 | [assembly: AssemblyFileVersion("1.1.0.3")]
37 |
--------------------------------------------------------------------------------
/ZensibleMongo/Update/SetUpdateMultiRecipe.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Update
2 | {
3 | using System;
4 | using System.Collections.Immutable;
5 | using System.Linq.Expressions;
6 | using Interfaces;
7 | using MongoDB.Driver;
8 |
9 | ///
10 | /// Recipe for setting a field on a document
11 | ///
12 | ///
13 | ///
14 | internal class SetUpdateMultiRecipe : IUpdateMultiRecipe
15 | {
16 | ///
17 | /// Field selector
18 | ///
19 | public Expression> Field { get; set; }
20 |
21 | ///
22 | /// Value to set the selected field to
23 | ///
24 | public TField Value { get; set; }
25 |
26 | ///
27 | /// Next update recipe
28 | ///
29 | public IUpdateRecipe NextRecipe { get; set; }
30 |
31 | ///
32 | /// Filter to use for update
33 | ///
34 | public IFilterRecipe FilterRecipe { get; set; }
35 |
36 | ///
37 | /// Mongo collection
38 | ///
39 | public IMongoCollection Collection { get; set; }
40 |
41 | ///
42 | /// All updates to perform on document
43 | ///
44 | ///
45 | public ImmutableList> UpdateDefinitions()
46 | {
47 | var update = Builders.Update.Set(Field, Value);
48 | return NextRecipe?.UpdateDefinitions().Add(update) ?? ImmutableList.Create(update);
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/ZensibleMongo/PullExtension.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo
2 | {
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 | using Filter;
6 | using Interfaces;
7 | using MongoDB.Driver;
8 |
9 | ///
10 | /// Extension for handling pull from mongo collection
11 | ///
12 | public static class PullExtension
13 | {
14 | ///
15 | /// Pulls the multiple documents from the mongo db based on the filter recipe
16 | ///
17 | ///
18 | ///
19 | /// cancellation token
20 | ///
21 | public static async Task> PullAsync(
22 | this IFilterRecipe recipe,
23 | CancellationToken token = default(CancellationToken))
24 | {
25 | var filter = Factory.Combine(recipe.Filters());
26 |
27 | return await recipe.Collection.FindAsync(filter, null, token);
28 | }
29 |
30 | ///
31 | /// Pulls the a single document from the mongo db based on the filter recipe
32 | ///
33 | ///
34 | ///
35 | /// cancellation token
36 | ///
37 | public static async Task PullAsync(
38 | this IFilterSingleRecipe recipe,
39 | CancellationToken token = default(CancellationToken))
40 | {
41 | var filter = Factory.Combine(recipe.Filters());
42 | return await recipe.Collection.FindAsync(filter, null, token).FirstOrDefaultAsync();
43 | }
44 |
45 |
46 |
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/ZensibleMongo/Factory.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo
2 | {
3 | using System;
4 | using System.Collections.Immutable;
5 | using System.Linq;
6 | using Interfaces;
7 | using MongoDB.Driver;
8 |
9 | internal static class Factory
10 | {
11 |
12 | ///
13 | /// Clones a object via shallow copy
14 | ///
15 | /// Object Type to Clone
16 | /// Object to Clone
17 | /// New Object reference
18 | /// http://stackoverflow.com/questions/2023210/cannot-access-protected-member-object-memberwiseclone
19 | internal static T CloneObject(this T obj)
20 | {
21 | if (obj == null) return default(T);
22 | System.Reflection.MethodInfo inst = obj.GetType().GetMethod("MemberwiseClone",
23 | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
24 | if (inst != null)
25 | return (T)inst.Invoke(obj, null);
26 | else
27 | return default(T);
28 | }
29 |
30 | internal static FilterDefinition Combine(ImmutableList> filters)
31 | {
32 | if (filters.IsEmpty)
33 | {
34 | return Builders.Filter.Where(_ => true);
35 | }
36 |
37 | return filters.Count == 1 ? filters.First() : Builders.Filter.And(filters);
38 | }
39 |
40 | internal static UpdateDefinition Combine(ImmutableList> updates)
41 | {
42 | return Builders.Update.Combine(updates.ToArray());
43 | }
44 |
45 | internal static FilterDefinition ExtractFilter(IFilterRecipeContainer recipe)
46 | {
47 | if (recipe.FilterRecipe == null)
48 | {
49 | throw new Exception("No Filter found");
50 | }
51 |
52 | return Combine(recipe.FilterRecipe.Filters());
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/ZensibleMongo/FilterExtension.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo
2 | {
3 | using System;
4 | using System.Linq.Expressions;
5 | using Filter;
6 | using Interfaces;
7 | using MongoDB.Bson;
8 | using MongoDB.Driver;
9 |
10 | ///
11 | /// Extension for all filter recipes
12 | ///
13 | public static class FilterExtension
14 | {
15 | ///
16 | /// Recipe for seleting documents based on a predicate
17 | ///
18 | ///
19 | ///
20 | /// a function to test documents for a condition
21 | ///
22 | public static IFilterMultiRecipe ForAllWhere(
23 | this IMongoCollection collection,
24 | Expression> predicate)
25 | {
26 | return new ForAllWhereRecipe { Collection = collection, Predicate = predicate };
27 | }
28 |
29 | ///
30 | /// Recipe for seleting all documents
31 | ///
32 | ///
33 | ///
34 | ///
35 | public static IFilterMultiRecipe ForAll(this IMongoCollection collection)
36 | {
37 | return new ForAllRecipe { Collection = collection };
38 | }
39 |
40 | ///
41 | /// Recipe for seleting documents based on a its id
42 | ///
43 | ///
44 | ///
45 | /// Mongo id of the document
46 | ///
47 | public static IFilterSingleRecipe ForId(this IMongoCollection collection, ObjectId id)
48 | {
49 | return new ForIdRecipe { Collection = collection, Id = id };
50 | }
51 |
52 | ///
53 | /// Recipe for seleting the first document that passes a condition
54 | ///
55 | ///
56 | ///
57 | /// a function to test documents for a condition
58 | ///
59 | public static IFilterSingleRecipe ForSingleWhere(
60 | this IMongoCollection collection,
61 | Expression> predicate)
62 | {
63 | return new ForFilterSingleWhere { Collection = collection, Predicate = predicate };
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/ZensibleMongo/HelpersExtension.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo
2 | {
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using MongoDB.Driver;
7 |
8 | ///
9 | /// Addition helper extension for mongo
10 | ///
11 | public static class HelpersExtension
12 | {
13 | ///
14 | /// Get the first document on the cursor otherwise returns default
15 | ///
16 | ///
17 | /// Mongo cursor
18 | ///
19 | public static async Task FirstOrDefaultAsync(this IAsyncCursor cursor)
20 | {
21 | var hasValue = await cursor.MoveNextAsync();
22 | return hasValue ? cursor.Current.FirstOrDefault() : default(TDocument);
23 | }
24 |
25 | ///
26 | /// Get the first document on the cursor otherwise returns default
27 | ///
28 | ///
29 | /// Mongo cursor task
30 | ///
31 | public static async Task FirstOrDefaultAsync(this Task> cursorTask)
32 | {
33 | var res = await cursorTask;
34 | return await res.FirstOrDefaultAsync();
35 | }
36 |
37 | ///
38 | /// gets the first document on the cursor otherwise returns default (this method is blocking)
39 | ///
40 | ///
41 | /// Mongo cursor
42 | ///
43 | public static TDocument FirstOrDefault(this IAsyncCursor cursor)
44 | {
45 | return FirstOrDefaultAsync(cursor).Result;
46 | }
47 |
48 | ///
49 | /// Gets a list of all documents on the cursor
50 | ///
51 | ///
52 | /// Mongo cursor task
53 | ///
54 | public static async Task> ToListAsync(this Task> cursorTask)
55 | {
56 | var res = await cursorTask;
57 | return await res.ToListAsync();
58 | }
59 |
60 | ///
61 | /// Gets a list of all documents on the cursor
62 | ///
63 | ///
64 | /// Mongo cursor
65 | ///
66 | public static List ToList(this IAsyncCursor cursor)
67 | {
68 | return cursor.ToListAsync().Result;
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Zensible Mongo
2 |
3 | Extension library to simplify working with mongo, it uses a builder pattern approach to performing calls to the mongo db, this allows for specific type of calls to be stored.
4 |
5 | # Motivation
6 | We all had to perform simple mongo actions but because of the mindboogling poor api of the offical mongo driver instead gone insane.
7 |
8 | For instance lets say we want to find a single document by id
9 | ```
10 | var filter = Builders.Filter.Eq("_id", id);
11 | var result = collection.Find(filter);
12 | var document = await result.SingleOrDefaultAsync()
13 | ```
14 |
15 | Alternative with zensible mongo
16 | ```
17 | var document = await collection.ForId(id).PullAsync();
18 | ```
19 |
20 | Or lets assume you want to insert a document into mongo and get the id that it got inserted with
21 | ```
22 | await collection.InsertOneAsync(document) <--- returns void
23 | ```
24 | Hmm thats weired there doesn't seem to be a way to get the id... ofc it changes the id directly on the document you are passing it. Nice unsafe shared memory you got there!
25 |
26 | Alternative with zensible mongo
27 | ```
28 | var documentWithID = await collection.Create(document).PushAsync()
29 | documentWithID.ShouldNotBe(document) //pass
30 | ```
31 | ahh nice a cloned safe version that is different
32 |
33 |
34 | # How To
35 |
36 |
37 | ### Query
38 | For a look up simply chose a selector such as ForId, ForSingleWhere etc.
39 |
40 | To Fetch a single document based on a condition.
41 | ```
42 | var document = await collection.ForSingleWhere(d => d.IsDue).PullAsync();
43 | ```
44 | ForSingleWhere should be be read: For a Single document Where (predicate) is true..
45 |
46 | To fetch all documents based on a condition.
47 | ```
48 | var document = await collection.ForAllWhere(d => d.IsDue).PullAsync();
49 | ```
50 | ForAllWhere should be be read: For All document Where (predicate) is true...
51 |
52 | To fetch all documents
53 | ```
54 | var document = await collection.ForAllWhere(d => d.IsDue).PullAsync();
55 | ```
56 | ForAllWhere should be be read: For All document Where (predicate) is true...
57 |
58 |
59 | ### Update
60 | Like with the query we begin by ForId/ForSingleWhere/For..
61 | ```
62 | var document = await collection.ForId(id)
63 | .Set(d => d.Field, value)
64 | .PushAsync();
65 | ```
66 | BONUS: if the selection only refers to one document that document will be returned.
67 |
68 | To change multiple fields simply string them together
69 | ```
70 | var document = await collection.ForId(id)
71 | .Set(d => d.Field1, value1)
72 | .Set(d => d.Field2, value2)
73 | .Set(d => d.Field3, value3)
74 | ..
75 | ..
76 | .PushAsync();
77 | ```
78 |
79 |
80 | ### Delete
81 | Like with query simply attach delete and the result will be a delete
82 | ```
83 | var document = await collection.ForId(id).Delete().PushAsync();
84 | ```
85 | BONUS: if the selection only refers to one document that document will be returned.
86 |
87 |
88 | ### Create
89 | To insert a document in the mongo collection simply use Create
90 | ```
91 | var newDocument = await collection.Create(document).PushAsync(); // newDocument != document
92 | ```
93 |
94 | For multiple documents
95 | ```
96 | var manyNewDocs = await collection.Create(doc1, doc2, ...).PushAsync();
97 | ```
98 |
99 | ## What is up with the Pull/Push?
100 | One of the features of this extension library is that actions can be stored and then used.
101 |
102 | for instance lets say I have a mail server and I want to define a query for all read mails.
103 | ```
104 | var allReadMailsQuery = collection.ForAllWhere(m => m.IsRead)
105 | ```
106 |
107 | Now when I need it I can either fetch it, delete it etc etc..
108 | ```
109 | var allReadMails = await allReadMailsQuery.PullAsync();
110 | await allReadMailsQuery.Delete().PushAsync();
111 | ...
112 | ...
113 | ```
114 |
115 |
116 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | build/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 |
28 | # MSTest test Results
29 | [Tt]est[Rr]esult*/
30 | [Bb]uild[Ll]og.*
31 |
32 | # NUNIT
33 | *.VisualState.xml
34 | TestResult.xml
35 |
36 | # Build Results of an ATL Project
37 | [Dd]ebugPS/
38 | [Rr]eleasePS/
39 | dlldata.c
40 |
41 | # DNX
42 | project.lock.json
43 | artifacts/
44 |
45 | *_i.c
46 | *_p.c
47 | *_i.h
48 | *.ilk
49 | *.meta
50 | *.obj
51 | *.pch
52 | *.pdb
53 | *.pgc
54 | *.pgd
55 | *.rsp
56 | *.sbr
57 | *.tlb
58 | *.tli
59 | *.tlh
60 | *.tmp
61 | *.tmp_proj
62 | *.log
63 | *.vspscc
64 | *.vssscc
65 | .builds
66 | *.pidb
67 | *.svclog
68 | *.scc
69 |
70 | # Chutzpah Test files
71 | _Chutzpah*
72 |
73 | # Visual C++ cache files
74 | ipch/
75 | *.aps
76 | *.ncb
77 | *.opensdf
78 | *.sdf
79 | *.cachefile
80 |
81 | # Visual Studio profiler
82 | *.psess
83 | *.vsp
84 | *.vspx
85 |
86 | # TFS 2012 Local Workspace
87 | $tf/
88 |
89 | # Guidance Automation Toolkit
90 | *.gpState
91 |
92 | # ReSharper is a .NET coding add-in
93 | _ReSharper*/
94 | *.[Rr]e[Ss]harper
95 | *.DotSettings.user
96 |
97 | # JustCode is a .NET coding add-in
98 | .JustCode
99 |
100 | # TeamCity is a build add-in
101 | _TeamCity*
102 |
103 | # DotCover is a Code Coverage Tool
104 | *.dotCover
105 |
106 | # NCrunch
107 | _NCrunch_*
108 | .*crunch*.local.xml
109 |
110 | # MightyMoose
111 | *.mm.*
112 | AutoTest.Net/
113 |
114 | # Web workbench (sass)
115 | .sass-cache/
116 |
117 | # Installshield output folder
118 | [Ee]xpress/
119 |
120 | # DocProject is a documentation generator add-in
121 | DocProject/buildhelp/
122 | DocProject/Help/*.HxT
123 | DocProject/Help/*.HxC
124 | DocProject/Help/*.hhc
125 | DocProject/Help/*.hhk
126 | DocProject/Help/*.hhp
127 | DocProject/Help/Html2
128 | DocProject/Help/html
129 |
130 | # Click-Once directory
131 | publish/
132 |
133 | # Publish Web Output
134 | *.[Pp]ublish.xml
135 | *.azurePubxml
136 | ## TODO: Comment the next line if you want to checkin your
137 | ## web deploy settings but do note that will include unencrypted
138 | ## passwords
139 | #*.pubxml
140 |
141 | *.publishproj
142 |
143 | # NuGet Packages
144 | *.nupkg
145 | # The packages folder can be ignored because of Package Restore
146 | **/packages/*
147 | # except build/, which is used as an MSBuild target.
148 | !**/packages/build/
149 | # Uncomment if necessary however generally it will be regenerated when needed
150 | #!**/packages/repositories.config
151 |
152 | # Windows Azure Build Output
153 | csx/
154 | *.build.csdef
155 |
156 | # Windows Store app package directory
157 | AppPackages/
158 |
159 | # Visual Studio cache files
160 | # files ending in .cache can be ignored
161 | *.[Cc]ache
162 | # but keep track of directories ending in .cache
163 | !*.[Cc]ache/
164 |
165 | # Others
166 | ClientBin/
167 | [Ss]tyle[Cc]op.*
168 | ~$*
169 | *~
170 | *.dbmdl
171 | *.dbproj.schemaview
172 | *.pfx
173 | *.publishsettings
174 | node_modules/
175 | orleans.codegen.cs
176 |
177 | # RIA/Silverlight projects
178 | Generated_Code/
179 |
180 | # Backup & report files from converting an old project file
181 | # to a newer Visual Studio version. Backup files are not needed,
182 | # because we have git ;-)
183 | _UpgradeReport_Files/
184 | Backup*/
185 | UpgradeLog*.XML
186 | UpgradeLog*.htm
187 |
188 | # SQL Server files
189 | *.mdf
190 | *.ldf
191 |
192 | # Business Intelligence projects
193 | *.rdl.data
194 | *.bim.layout
195 | *.bim_*.settings
196 |
197 | # Microsoft Fakes
198 | FakesAssemblies/
199 |
200 | # Node.js Tools for Visual Studio
201 | .ntvs_analysis.dat
202 |
203 | # Visual Studio 6 build log
204 | *.plg
205 |
206 | # Visual Studio 6 workspace options file
207 | *.opt
208 |
209 | # LightSwitch generated files
210 | GeneratedArtifacts/
211 | _Pvt_Extensions/
212 | ModelManifest.xml
213 |
--------------------------------------------------------------------------------
/ZensibleMongo/UpdateExtension.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo
2 | {
3 | using System;
4 | using System.Linq.Expressions;
5 | using Filter;
6 | using Interfaces;
7 | using Update;
8 |
9 | ///
10 | /// Extension for update recipes
11 | ///
12 | public static class UpdateExtension
13 | {
14 | ///
15 | /// Recipe for setting a field on multiple documents
16 | ///
17 | ///
18 | ///
19 | ///
20 | /// Field selector
21 | /// Updates field with the specificed value
22 | ///
23 | public static IUpdateMultiRecipe Set(
24 | this IFilterRecipe recipe,
25 | Expression> field,
26 | TField value)
27 | {
28 | return new SetUpdateMultiRecipe
29 | {
30 | Collection = recipe.Collection,
31 | Field = field,
32 | Value = value,
33 | FilterRecipe = recipe
34 | };
35 | }
36 |
37 | ///
38 | /// Recipe for setting a field on multiple documents
39 | ///
40 | ///
41 | ///
42 | ///
43 | /// Field selector
44 | /// Updates field with the specificed value
45 | ///
46 | public static IUpdateMultiRecipe Set(
47 | this IUpdateMultiRecipe updateMultiRecipe,
48 | Expression> field, TField value)
49 | {
50 | return new SetUpdateMultiRecipe
51 | {
52 | Collection = updateMultiRecipe.Collection,
53 | Field = field,
54 | Value = value,
55 | FilterRecipe = updateMultiRecipe.FilterRecipe
56 | };
57 | }
58 |
59 | ///
60 | /// Recipe for setting a field on a single document
61 | ///
62 | ///
63 | ///
64 | ///
65 | /// Field selector
66 | /// Updates field with the specificed value
67 | ///
68 | public static IUpdateSingleRecipe Set(
69 | this IUpdateSingleRecipe recipe,
70 | Expression> field, TField value)
71 | {
72 | return new SetUpdateSingleRecipe
73 | {
74 | Collection = recipe.Collection,
75 | Field = field,
76 | Value = value
77 | };
78 | }
79 |
80 | ///
81 | /// Recipe for setting a field on a single document
82 | ///
83 | ///
84 | ///
85 | ///
86 | /// Field selector
87 | /// Updates field with the specificed value
88 | ///
89 | public static IUpdateSingleRecipe Set(
90 | this IFilterSingleRecipe recipe,
91 | Expression> field, TField value)
92 | {
93 | return new SetUpdateSingleRecipe
94 | {
95 | Collection = recipe.Collection,
96 | FilterRecipe = recipe,
97 | Field = field,
98 | Value = value
99 | };
100 | }
101 |
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/ZensibleMongo/PushExtension.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 | using Create;
9 | using Delete;
10 | using Interfaces;
11 | using MongoDB.Driver;
12 |
13 | ///
14 | /// Extension for handling pushes to mongo collection
15 | ///
16 | public static class PushExtension
17 | {
18 | ///
19 | /// Updates to the mongo db based on the createMultiRecipe
20 | ///
21 | ///
22 | ///
23 | /// Update Options
24 | /// Cancellation Token
25 | ///
26 | public static async Task PushAsync(
27 | this IUpdateRecipe recipe,
28 | UpdateOptions options = null,
29 | CancellationToken token = default(CancellationToken))
30 | {
31 | var filter = Factory.ExtractFilter(recipe);
32 | var update = Factory.Combine(recipe.UpdateDefinitions());
33 |
34 | return await recipe.Collection.UpdateManyAsync(filter, update, options, token);
35 | }
36 |
37 | ///
38 | /// Finds and updates a single documents and returns the document
39 | ///
40 | ///
41 | ///
42 | /// Update Options
43 | /// Cancellation Token
44 | ///
45 | public static async Task PushAsync(
46 | this IUpdateSingleRecipe recipe,
47 | UpdateOptions options = null,
48 | CancellationToken token = default(CancellationToken))
49 | {
50 | var filter = Factory.ExtractFilter(recipe);
51 | var update = Factory.Combine(recipe.UpdateDefinitions());
52 | return await recipe.Collection.FindOneAndUpdateAsync(filter, update, null, token);
53 | }
54 |
55 | ///
56 | /// Creates a single documents and returns the document
57 | ///
58 | ///
59 | ///
60 | /// Cancellation Token
61 | ///
62 | public static async Task PushAsync(
63 | this ICreateSingleRecipe recipe,
64 | CancellationToken token = default(CancellationToken))
65 | {
66 |
67 | var value = recipe.Document.CloneObject();
68 | await recipe.Collection.InsertOneAsync(value, token);
69 | return value;
70 | }
71 |
72 | ///
73 | /// Creates multiple documents and returns them updated with their id.
74 | /// (Input is cloned and is not affected)
75 | ///
76 | ///
77 | ///
78 | ///
79 | /// Cancellation Token
80 | ///
81 | public static async Task> PushAsync(
82 | this ICreateMultiRecipe createMultiRecipe,
83 | InsertManyOptions options = null,
84 | CancellationToken token = default(CancellationToken))
85 | {
86 | var inserts = createMultiRecipe.AllDocuments().Select(v => v.CloneObject()).ToArray();
87 | await createMultiRecipe.Collection.InsertManyAsync(inserts, options, token);
88 | return inserts;
89 | }
90 |
91 | ///
92 | /// Deletes multiple documents based on the createMultiRecipe
93 | /// (Input is cloned and is not affected)
94 | ///
95 | ///
96 | ///
97 | /// Cancellation Token
98 | ///
99 | public static async Task PushAsync(
100 | this IDeleteMultiRecipe recipe,
101 | CancellationToken token = default(CancellationToken))
102 | {
103 | var filter = Factory.ExtractFilter(recipe);
104 | return await recipe.Collection.DeleteManyAsync(filter, token);
105 | }
106 |
107 | ///
108 | /// Finds and deletes a single documents then returns that document
109 | ///
110 | ///
111 | ///
112 | /// Cancellation Token
113 | public static async Task PushAsync(
114 | this IDeleteSingleRecipe recipe,
115 | CancellationToken token = default(CancellationToken))
116 | {
117 | var filter = Factory.ExtractFilter(recipe);
118 | return await recipe.Collection.FindOneAndDeleteAsync(filter, cancellationToken: token);
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/ZensibleMongo/ZensibleMongo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {C578346C-AA39-4E6F-BA5D-9708D44A8FC1}
8 | Library
9 | Properties
10 | ZensibleMongo
11 | ZensibleMongo
12 | v4.5.2
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 | bin\Debug\ZensibleMongo.XML
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 | ..\packages\MongoDB.Bson.2.0.1\lib\net45\MongoDB.Bson.dll
36 | True
37 |
38 |
39 | ..\packages\MongoDB.Driver.2.0.1\lib\net45\MongoDB.Driver.dll
40 | True
41 |
42 |
43 | ..\packages\MongoDB.Driver.Core.2.0.1\lib\net45\MongoDB.Driver.Core.dll
44 | True
45 |
46 |
47 |
48 | ..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
49 | True
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
105 |
--------------------------------------------------------------------------------
/ZensibleMongo.Tests/ZensibleMongo.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Debug
7 | AnyCPU
8 | {51A32C41-BE8F-4325-9E2F-5E52C3598DE7}
9 | Library
10 | Properties
11 | ZensibleMongo.Tests
12 | ZensibleMongo.Tests
13 | v4.5.2
14 | 512
15 |
16 |
17 |
18 |
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 | ..\packages\MongoDB.Bson.2.0.1\lib\net45\MongoDB.Bson.dll
38 | True
39 |
40 |
41 | ..\packages\MongoDB.Driver.2.0.1\lib\net45\MongoDB.Driver.dll
42 | True
43 |
44 |
45 | ..\packages\MongoDB.Driver.Core.2.0.1\lib\net45\MongoDB.Driver.Core.dll
46 | True
47 |
48 |
49 | ..\packages\Newtonsoft.Json.6.0.3\lib\net45\Newtonsoft.Json.dll
50 | True
51 |
52 |
53 | ..\packages\NSubstitute.1.8.2.0\lib\net45\NSubstitute.dll
54 | True
55 |
56 |
57 | ..\packages\Shouldly.2.6.0\lib\net40\Shouldly.dll
58 | True
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | ..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll
70 | True
71 |
72 |
73 | ..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll
74 | True
75 |
76 |
77 | ..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll
78 | True
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | {c578346c-aa39-4e6f-ba5d-9708d44a8fc1}
92 | ZensibleMongo
93 |
94 |
95 |
96 |
97 |
98 | 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}.
99 |
100 |
101 |
102 |
109 |
--------------------------------------------------------------------------------
/ZensibleMongo.Tests/MongoExtensionTest.cs:
--------------------------------------------------------------------------------
1 | namespace ZensibleMongo.Tests
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq.Expressions;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 | using MongoDB.Bson;
9 | using MongoDB.Driver;
10 | using NSubstitute;
11 | using Shouldly;
12 | using Xunit;
13 |
14 | public class MongoExtensionTest
15 | {
16 | private Expression> SomeField => e => e.A;
17 |
18 | private Expression> SomeWhereTest => e => e.A == 0;
19 |
20 |
21 |
22 |
23 | [Fact]
24 | public async Task Create_Single_ReturnSingle()
25 | {
26 | var col = Substitute.For>();
27 |
28 | var data = new DataExample() { A = 0, B = 1 };
29 |
30 | var result = await col.Create(data).PushAsync();
31 |
32 | #pragma warning disable 4014
33 | col.Received().InsertOneAsync(data, default(CancellationToken));
34 | #pragma warning restore 4014
35 |
36 | data.ShouldBe(result);
37 |
38 | }
39 |
40 |
41 | [Fact]
42 | public async Task Create_ManyItems_ReturnMany()
43 | {
44 | var col = Substitute.For>();
45 |
46 | var data = new DataExample() { A = 0, B = 1 };
47 | var manyData = new[] {data, data};
48 |
49 | var result = await col.Create(manyData)
50 | .PushAsync();
51 |
52 | #pragma warning disable 4014
53 | col.Received().InsertManyAsync(Arg.Any>(), null, default(CancellationToken));
54 | #pragma warning restore 4014
55 |
56 | result.ShouldBe(manyData);
57 | }
58 |
59 |
60 | [Fact]
61 | public async Task ForId_Set_UpdateAndReturn()
62 | {
63 | var col = Substitute.For>();
64 | var data = 0;
65 | var id = ValidObjectId();
66 |
67 | var result = await col.ForId(id)
68 | .Set(SomeField, data)
69 | .PushAsync();
70 |
71 | #pragma warning disable 4014
72 | col.Received().FindOneAndUpdateAsync(
73 | Arg.Any>(),
74 | Arg.Any>());
75 | #pragma warning restore 4014
76 |
77 | result.ShouldBeOfType();
78 |
79 | }
80 |
81 | [Fact]
82 | public async Task ForSingleWhere_Update_ReturnSingle()
83 | {
84 | var col = Substitute.For>();
85 | var data = 0;
86 |
87 |
88 | var result = await col.ForSingleWhere(SomeWhereTest)
89 | .Set(SomeField, data)
90 | .PushAsync();
91 |
92 | #pragma warning disable 4014
93 | col.Received().FindOneAndUpdateAsync(
94 | Arg.Any>(),
95 | Arg.Any>());
96 | #pragma warning restore 4014
97 |
98 | result.ShouldBeAssignableTo();
99 |
100 | }
101 |
102 | [Fact]
103 | public async Task ForAll_Set_ManyUpdates()
104 | {
105 | var col = Substitute.For>();
106 | var data = 0;
107 |
108 | await col.ForAll()
109 | .Set(SomeField, data)
110 | .PushAsync();
111 |
112 |
113 | #pragma warning disable 4014
114 | col.Received().UpdateManyAsync(
115 | Arg.Any>(),
116 | Arg.Any>());
117 | #pragma warning restore 4014
118 |
119 | }
120 |
121 | [Fact]
122 | public async Task ForAllWhere_Set_ManyUpdates()
123 | {
124 | var col = Substitute.For>();
125 | var data = 0;
126 |
127 | await col.ForAllWhere(SomeWhereTest)
128 | .Set(SomeField, data)
129 | .PushAsync();
130 |
131 | #pragma warning disable 4014
132 | col.Received().UpdateManyAsync(
133 | Arg.Any>(),
134 | Arg.Any>());
135 | #pragma warning restore 4014
136 |
137 | }
138 |
139 | [Fact]
140 | public async Task ForAllWhere_Delete_ManyDeletes()
141 | {
142 | var col = Substitute.For>();
143 |
144 | await col.ForAllWhere(SomeWhereTest)
145 | .Delete()
146 | .PushAsync();
147 |
148 | #pragma warning disable 4014
149 | col.Received().DeleteManyAsync(
150 | Arg.Any>(),
151 | Arg.Any());
152 | #pragma warning restore 4014
153 |
154 | }
155 |
156 | [Fact]
157 | public async Task ForAll_Delete_ManyDeletes()
158 | {
159 | var col = Substitute.For>();
160 |
161 | var result = await col.ForAll()
162 | .Delete()
163 | .PushAsync();
164 |
165 | #pragma warning disable 4014
166 | col.Received().DeleteManyAsync(
167 | Arg.Any>(),
168 | Arg.Any()); ;
169 | #pragma warning restore 4014
170 |
171 | result.ShouldBeAssignableTo();
172 |
173 | }
174 |
175 | [Fact]
176 | public async Task ForId_Delete_DeleteAndReturn()
177 | {
178 | var col = Substitute.For>();
179 | var id = ValidObjectId();
180 |
181 | var result = await col.ForId(id)
182 | .Delete()
183 | .PushAsync();
184 |
185 | #pragma warning disable 4014
186 | col.Received().FindOneAndDeleteAsync(
187 | Arg.Any>(),
188 | Arg.Any>(),
189 | Arg.Any());
190 | #pragma warning restore 4014
191 |
192 | result.ShouldBeOfType();
193 |
194 | }
195 |
196 | [Fact]
197 | public async Task ForSingleWhere_Delete_ReturnSingle()
198 | {
199 | var col = Substitute.For>();
200 |
201 | var result = await col.ForSingleWhere(SomeWhereTest)
202 | .Delete()
203 | .PushAsync();
204 |
205 | #pragma warning disable 4014
206 | col.Received().FindOneAndDeleteAsync(
207 | Arg.Any>(),
208 | Arg.Any>(),
209 | Arg.Any());
210 | #pragma warning restore 4014
211 |
212 | result.ShouldBeAssignableTo();
213 |
214 | }
215 |
216 |
217 | [Fact]
218 | public async Task ForId_Pull_ReturnSingle()
219 | {
220 | var col = Substitute.For>();
221 | var id = ValidObjectId();
222 |
223 | var result = await col.ForId(id).PullAsync();
224 |
225 | #pragma warning disable 4014
226 | col.Received().FindAsync(
227 | Arg.Any>(),
228 | Arg.Any>(),
229 | Arg.Any());
230 | #pragma warning restore 4014
231 |
232 | result.ShouldBeAssignableTo();
233 |
234 | }
235 |
236 |
237 | [Fact]
238 | public async Task ForAllWhere_Pull_ReturnMany()
239 | {
240 | var col = Substitute.For>();
241 |
242 | var result = await col.ForAllWhere(SomeWhereTest)
243 | .PullAsync().ToListAsync();
244 |
245 | #pragma warning disable 4014
246 | col.Received().FindAsync(
247 | Arg.Any>(),
248 | Arg.Any>(),
249 | Arg.Any());
250 | #pragma warning restore 4014
251 |
252 | result.ShouldBeAssignableTo>();
253 | }
254 |
255 | [Fact]
256 | public async Task ForAll_Pull_ReturnMany()
257 | {
258 | var col = Substitute.For>();
259 |
260 | var result = await col.ForAll()
261 | .PullAsync().ToListAsync();
262 |
263 | #pragma warning disable 4014
264 | col.Received().FindAsync(
265 | Arg.Any>(),
266 | Arg.Any>(),
267 | Arg.Any());
268 | #pragma warning restore 4014
269 |
270 | result.ShouldBeAssignableTo>();
271 |
272 | }
273 |
274 | [Fact]
275 | public async Task ForSingleWhere_Pull_ReturnSingle()
276 | {
277 | var col = Substitute.For>();
278 |
279 | var result = await col.ForSingleWhere(SomeWhereTest)
280 | .PullAsync();
281 |
282 | #pragma warning disable 4014
283 | col.Received().FindAsync(
284 | Arg.Any>(),
285 | Arg.Any>(),
286 | Arg.Any());
287 | #pragma warning restore 4014
288 |
289 | result.ShouldBeAssignableTo();
290 |
291 | }
292 |
293 | public string ValidId()
294 | {
295 | return "507f191e810c19729de860ea";
296 | }
297 |
298 | public ObjectId ValidObjectId()
299 | {
300 | return ObjectId.Parse(ValidId());
301 | }
302 |
303 |
304 | }
305 | }
306 |
--------------------------------------------------------------------------------