Skip to content

Commit

Permalink
Refactoring Repository
Browse files Browse the repository at this point in the history
  • Loading branch information
jchadwick committed Dec 21, 2011
1 parent 6316209 commit abbf86b
Show file tree
Hide file tree
Showing 15 changed files with 121 additions and 122 deletions.
25 changes: 11 additions & 14 deletions Core/DataAccess/IRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,20 @@

namespace Ebuy.DataAccess
{
public interface IRepository<TModel> : IDisposable
where TModel : IEntity
public interface IRepository : IDisposable
{
void Delete(TModel instance);
void Delete(Expression<Func<TModel, bool>> predicate);
void DeleteById(long id);
void DeleteByKey(string key);
IQueryable<TModel> All<TModel>(int pageIndex = 0, int pageSize = 25) where TModel : class, IEntity;

TModel Find(Expression<Func<TModel, bool>> predicate);
TModel FindById(long id);
TModel FindByKey(string key);
void Add<TModel>(TModel instance) where TModel : class, IEntity;
void Add<TModel>(IEnumerable<TModel> instances) where TModel : class, IEntity;

IQueryable<TModel> Query(int pageIndex = 0, int pageSize = 25);
IQueryable<TModel> Query(Expression<Func<TModel, bool>> predicate);
IQueryable<TModel> Query(Expression<Func<TModel, bool>> predicate, out int count, int pageIndex, int pageSize);
void Delete<TModel>(string key) where TModel : class, IEntity;
void Delete<TModel>(TModel instance) where TModel : class, IEntity;
void Delete<TModel>(Expression<Func<TModel, bool>> predicate) where TModel : class, IEntity;

void Save(TModel instance);
void Save(IEnumerable<TModel> instances);
TModel Single<TModel>(string key) where TModel : class, IEntity;
TModel Single<TModel>(Expression<Func<TModel, bool>> predicate) where TModel : class, IEntity;

IQueryable<TModel> Query<TModel>(Expression<Func<TModel, bool>> predicate) where TModel : class, IEntity;
}
}
103 changes: 31 additions & 72 deletions Core/DataAccess/Repository.cs
Original file line number Diff line number Diff line change
@@ -1,29 +1,17 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Linq.Expressions;

namespace Ebuy.DataAccess
{
public class Repository<TModel> : IRepository<TModel>
where TModel : class, IEntity
public class Repository : IRepository
{
private readonly DataContext _context;
private readonly bool _isSharedContext;

protected DbSet<TModel> DataSource
{
get { return _context.Set<TModel>(); }
}

public IQueryable<TModel> Items
{
get { return DataSource.AsQueryable(); }
}


public Repository()
: this(new DataContext(), false)
Expand All @@ -39,6 +27,12 @@ public Repository(DataContext context, bool isSharedContext = true)
}


public IQueryable<TModel> All<TModel>(int pageIndex = 0, int pageSize = 25)
where TModel : class, IEntity
{
return _context.Set<TModel>().Page(pageIndex, pageSize);
}

public void Dispose()
{
// If this is a shared (or null) context then
Expand All @@ -49,103 +43,67 @@ public void Dispose()
_context.Dispose();
}

public void DeleteById(long id)
{
var item = FindById(id);
Delete(item);
}

public void DeleteByKey(string key)
public void Delete<TModel>(string key)
where TModel : class, IEntity
{
Contract.Requires(!string.IsNullOrWhiteSpace(key));

var entity = FindByKey(key);
var entity = Single<TModel>(key);
Delete(entity);
}

public void Delete(TModel instance)
public void Delete<TModel>(TModel instance)
where TModel : class, IEntity
{
Contract.Requires(instance != null);

if (instance != null)
DataSource.Remove(instance);
_context.Set<TModel>().Remove(instance);
}

public void Delete(Expression<Func<TModel, bool>> predicate)
public void Delete<TModel>(Expression<Func<TModel, bool>> predicate)
where TModel : class, IEntity
{
Contract.Requires(predicate != null);

var entity = Find(predicate);
Delete(entity);
}
TModel entity = Single(predicate);

public TModel FindById(long id)
{
Contract.Requires(id > 0);

return Find(x => x.Id == id);
Delete(entity);
}

public TModel FindByKey(string key)
public TModel Single<TModel>(string key)
where TModel : class, IEntity
{
Contract.Requires(!string.IsNullOrWhiteSpace(key));

var entity = Find(x => x.Key == key);
var entity = Single<TModel>(x => x.Key == key);
return entity;
}

public TModel Find(Expression<Func<TModel, bool>> predicate)
public TModel Single<TModel>(Expression<Func<TModel, bool>> predicate)
where TModel : class, IEntity
{
Contract.Requires(predicate != null);

var instance = DataSource.SingleOrDefault(predicate);
var instance = _context.Set<TModel>().SingleOrDefault(predicate);
return instance;
}

public IQueryable<TModel> Query(int pageIndex = 0, int pageSize = 25)
{
return ApplyPaging(DataSource, pageIndex, pageSize);
}

public IQueryable<TModel> Query(Expression<Func<TModel, bool>> predicate)
public IQueryable<TModel> Query<TModel>(Expression<Func<TModel, bool>> predicate)
where TModel : class, IEntity
{
Contract.Requires(predicate != null);

IQueryable<TModel> items = DataSource;
IQueryable<TModel> items = _context.Set<TModel>();

if (predicate != null)
items = items.Where(predicate);

return items;
}

public IQueryable<TModel> Query(Expression<Func<TModel, bool>> predicate, out int count, int pageIndex = 0, int pageSize = 25)
{
Contract.Requires(predicate != null);
Contract.Requires(pageIndex >= 0);
Contract.Requires(pageSize >= 0);

var items = Query(predicate);

items = ApplyPaging(items, pageIndex, pageSize);

count = items.Count();

return items;
}

private static IQueryable<TModel> ApplyPaging(IQueryable<TModel> items, int pageIndex, int pageSize)
{
int skip = pageIndex*pageSize;

if (skip > 0)
items = items.Skip(skip);

items = items.Take(pageSize);
return items;
}

public void Save(TModel instance)
public void Add<TModel>(TModel instance)
where TModel : class, IEntity
{
Contract.Requires(instance != null);

Expand All @@ -158,13 +116,14 @@ public void Save(TModel instance)
_context.SaveChanges();
}

public void Save(IEnumerable<TModel> instances)
public void Add<TModel>(IEnumerable<TModel> instances)
where TModel : class, IEntity
{
Contract.Requires(instances != null);

foreach (var instance in instances)
{
Save(instance);
Add(instance);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions Core/Ebuy.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
<Compile Include="DataAccess\DataContext.cs" />
<Compile Include="DataAccess\IRepository.cs" />
<Compile Include="DataAccess\Repository.cs" />
<Compile Include="Extensions\QueryableExtensions.cs" />
<Compile Include="Model\Auction.cs" />
<Compile Include="Model\Bid.cs" />
<Compile Include="Model\Category.cs" />
Expand Down
23 changes: 23 additions & 0 deletions Core/Extensions/QueryableExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System.Diagnostics.Contracts;
using System.Linq;

namespace Ebuy
{
public static class QueryableExtensions
{
public static IQueryable<T> Page<T>(this IQueryable<T> source, int pageIndex, int pageSize)
{
Contract.Requires(pageIndex >= 0, "Page index cannot be negative");
Contract.Requires(pageSize >= 0, "Page size cannot be negative");

int skip = pageIndex * pageSize;

if (skip > 0)
source = source.Skip(skip);

source = source.Take(pageSize);

return source;
}
}
}
9 changes: 9 additions & 0 deletions Core/Model/Auction.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.Contracts;
using CustomExtensions.DataAnnotations;
Expand Down Expand Up @@ -33,6 +34,14 @@ public bool IsCompleted
public virtual User Owner { get; set; }


public Auction()
{
Bids = new Collection<Bid>();
Categories = new Collection<Category>();
Images = new Collection<WebsiteImage>();
}


internal void PostBid(Bid bid)
{
Contract.Requires(bid != null);
Expand Down
27 changes: 19 additions & 8 deletions Core/Model/Bid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,44 @@ public virtual Guid Id
}
private Guid? _id;

public virtual Currency Price { get; set; }
public virtual DateTime Timestamp { get; set; }
public virtual Auction Auction { get; set; }

public virtual bool IsWinningBid
{
get
{
return Auction != null
&& this == Auction.WinningBid;
&& this == Auction.WinningBid;
}
}

[InverseProperty("Bids")]
public virtual Auction Auction { get; set; }
public virtual Currency Price { get; set; }

public virtual DateTime Timestamp { get; private set; }

public virtual User User { get; set; }


public Bid() : this(DateTime.UtcNow)
{
}

protected internal Bid(DateTime timestamp)
{
Timestamp = timestamp;
}

public class Metadata
{
[Required]
public object Price { get; set; }
[InverseProperty("Bids")]
public object Auction { get; set; }

[Required]
public object Timestamp { get; set; }
public object Price { get; set; }

[Required]
public object Auction { get; set; }
public object Timestamp { get; set; }

[Required]
public object User { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion Core/Model/User.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ protected internal virtual void Bid(Auction auction, Currency currency, DateTime
Contract.Requires(auction != null);
Contract.Requires(currency != null);

var bid = new Bid { User = this, Price = currency, Timestamp = timestamp };
var bid = new Bid(timestamp) { User = this, Price = currency };
auction.PostBid(bid);
}

Expand Down
8 changes: 4 additions & 4 deletions IntegrationTests/Core/DataAccess/AuctionRepositoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@
namespace IntegrationTests.Core.DataAccess
{
[TestClass]
public class AuctionRepositoryTests : RepositoryTestFixture<Auction>
public class AuctionRepositoryTests : RepositoryTestFixture
{
[TestMethod]
public void ShouldSaveNewAuction()
{
AssertCanSaveNewEntity();
AssertCanSaveNewEntity<Auction>();
}

[TestMethod]
public void ShouldFindAuctionById()
{
AssertCanFindById();
AssertCanFindById<Auction>();
}

[TestMethod]
// [TestMethod]
public void ShouldPersistBids()
{
var auction = CreateAndSaveNewEntity<Auction>();
Expand Down
4 changes: 2 additions & 2 deletions IntegrationTests/Core/DataAccess/CategoryRepositoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
namespace IntegrationTests.Core.DataAccess
{
[TestClass]
public class CategoryRepositoryTests : RepositoryTestFixture<Category>
public class CategoryRepositoryTests : RepositoryTestFixture
{
[TestMethod]
public void ShouldSaveNewCategory()
{
AssertCanSaveNewEntity();
AssertCanSaveNewEntity<Category>();
}
}
}
2 changes: 1 addition & 1 deletion IntegrationTests/Core/DataAccess/DataContextTestFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace IntegrationTests.Core.DataAccess
{
public abstract class DataContextTestFixture<T> where T : class
public abstract class DataContextTestFixture
{
protected DataContext DataContext { get; set; }

Expand Down
Loading

0 comments on commit abbf86b

Please sign in to comment.