Last active
December 2, 2015 14:51
-
-
Save hanssens/63db5bce5674cc950f3e to your computer and use it in GitHub Desktop.
GenericDataRepository for easy CRUD operations with RavenDB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Hanssens.Integrations.RavenDb | |
{ | |
/** | |
* Built by : hanssens.com | |
* License : MIT | |
* See also : https://gist.github.com/hanssens/63db5bce5674cc950f3e | |
*/ | |
/// <summary> | |
/// Contract required for all objects that want to use the GenericDocumentRepository. | |
/// </summary> | |
/// <remarks> | |
/// Extend or modify it as you desire. The only requirement is that 'Id' exists, but | |
/// you may change its type to for example long, string or Guid. | |
/// </remarks> | |
public interface IRavenDbEntity { | |
int Id { get; set; } | |
} | |
/// <summary> | |
/// Provides a generic CRUD repository for any object type that derives from IRavenDbEntity. | |
/// </summary> | |
/// <typeparam name="T">The class type, which should implement IRavenDbEntity.</typeparam> | |
/// <remarks> | |
/// Each individual function in this class is responsible, and self-manages the | |
/// opening and closing of session(s). Therefor every instance of the GenericDocumentRepository | |
/// should be as short-lived as possible. | |
/// The reason for this is a trade-off: either the user, e.g. calling application, is responsible | |
/// for managing sessions - or this repository is. Not having to bother the calling application | |
/// with this seems to be the neater approach. | |
/// Another noteworthy element is that several operations require "knowledge" of the unique identifier. | |
/// Therefor the IRavenDbEntity interface is defined. You can adjust this to your will by changing its | |
/// type, for example to long or Guid, if you wish. | |
/// </remarks> | |
public class GenericDocumentRepository<T> : IDisposable where T : IRavenDbEntity | |
{ | |
protected string House { get; set; } | |
/// <summary> | |
/// Provides access to an already instantiated data access provider, e.g. the DocumentStore. | |
/// </summary> | |
/// <remarks> | |
/// Note that this property deliberately has a protected access-level; you do not want your | |
/// consumers to sneakily directly address the DocumentStore. | |
/// </remarks> | |
protected Raven.Client.Document.DocumentStore DataContext { get; set; } | |
/// <summary> | |
/// Initialises a new instance of the GenericDocumentRepository. | |
/// </summary> | |
public GenericDocumentRepository() : this(new DocumentStore()) { } | |
/// <summary> | |
/// Initialises a new instance of the GenericDocumentRepository. | |
/// </summary> | |
public GenericDocumentRepository(DocumentStore documentStore) | |
{ | |
DataContext = documentStore; | |
} | |
/// <summary> | |
/// Deletes a single document from the database. | |
/// </summary> | |
/// <param name="id">Unique identifier of the object to be deleted.</param> | |
public void Delete(long id) | |
{ | |
using (var session = DataContext.OpenSession()) | |
{ | |
var instance = session.Load<T>(id); | |
session.Delete(instance); | |
session.SaveChanges(); | |
} | |
} | |
/// <summary> | |
/// Inserts a single item into the database. | |
/// </summary> | |
/// <param name="instance">The instance to be inserted.</param> | |
/// <remarks> | |
/// Use 'BatchInsert' for multiple items. | |
/// </remarks> | |
public T Insert(T instance) | |
{ | |
var now = DateTime.Now; | |
instance.CreatedOn = now; | |
instance.LastModifiedOn = now; | |
using (var session = DataContext.OpenSession()) | |
{ | |
session.Store(instance); | |
session.SaveChanges(); | |
return instance; | |
} | |
} | |
/// <summary> | |
/// Loads a single instance from the database. | |
/// </summary> | |
/// <param name="id">Unique identifier of the object.</param> | |
public T Get(long id) | |
{ | |
var returnValue = default(T); | |
using (var session = DataContext.OpenSession()) | |
{ | |
returnValue = session.Load<T>(id); | |
} | |
return returnValue; | |
} | |
/// <summary> | |
/// Fetches a list of items, optionally limited by the 'skip' and 'take' filters. | |
/// </summary> | |
/// <param name="skip">Amount of records to skip. Defaults to '0'.</param> | |
/// <param name="take">Amount of records to fetch. Defaults to '50'.</param> | |
/// <returns>Returns a collection of items.</returns> | |
public virtual IEnumerable<T> GetAll(int skip = 0, int take = 50) | |
{ | |
using (var session = DataContext.OpenSession()) | |
{ | |
return session.Query<T>() | |
.Skip(skip) | |
.Take(take); | |
} | |
} | |
/// <summary> | |
/// Fetches a specific list of items, by a collection of id's. | |
/// </summary> | |
/// <param name="identifiers">List of unique identifiers</param> | |
/// <returns>Returns a collection of items.</returns> | |
public virtual IEnumerable<T> GetAll(IEnumerable<int> identifiers) | |
{ | |
var returnValue = new List<T>(); | |
using (var session = DataContext.OpenSession()) | |
{ | |
foreach (var id in identifiers) | |
{ | |
returnValue = session.Query<T>() | |
.Where(t => identifiers.Contains(t.Id)) | |
.ToList(); | |
} | |
} | |
return returnValue.ToList(); | |
} | |
public virtual IQueryable<T> Query(Expression<Func<T, bool>> predicate) | |
{ | |
using (var session = DataContext.OpenSession()) | |
{ | |
return session.Query<T>().Where(predicate); | |
} | |
} | |
public T Update(T instance) | |
{ | |
throw new NotImplementedException("This is something you may do yourself"); | |
} | |
public void Dispose() | |
{ | |
DataContext.Dispose(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment