Skip to content

Commit cde6ec3

Browse files
author
Jeff Treuting
committed
Added a compound key repository that uses Get(params object[] keys)
So now there are the 2 primary key type where you can define the types of the keys for better clarity in seeing what it is, then there is a general one that you don't define the type of the keys up front but can use as many as you like. Plenty of code cleanup and refactoring is needed. Right now there is a ton of code duplication as I was trying to get it working first. Will definitely need to clean it up and combine common code into sub classes. Then once that is done I may make another version that takes 3 key types as well. I may stop there as it will cover most of the use cases I would think, and if not the general version will work.
1 parent a433e57 commit cde6ec3

19 files changed

Lines changed: 1766 additions & 37 deletions

SharpRepository.Ef5Repository/Ef5CompoundKeyRepositoryBase.cs

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,73 @@
88

99
namespace SharpRepository.Ef5Repository
1010
{
11+
public class Ef5CompoundKeyRepositoryBase<T> : LinqCompoundKeyRepositoryBase<T> where T : class, new()
12+
{
13+
protected IDbSet<T> DbSet { get; private set; }
14+
protected DbContext Context { get; private set; }
15+
16+
internal Ef5CompoundKeyRepositoryBase(DbContext dbContext, ICompoundKeyCachingStrategy<T> cachingStrategy = null)
17+
: base(cachingStrategy)
18+
{
19+
Initialize(dbContext);
20+
}
21+
22+
private void Initialize(DbContext dbContext)
23+
{
24+
Context = dbContext;
25+
DbSet = Context.Set<T>();
26+
}
27+
28+
protected override void AddItem(T entity)
29+
{
30+
// no generating primary keys
31+
DbSet.Add(entity);
32+
}
33+
34+
protected override void DeleteItem(T entity)
35+
{
36+
DbSet.Remove(entity);
37+
}
38+
39+
protected override void UpdateItem(T entity)
40+
{
41+
// mark this entity as modified, in case it is not currently attached to this context
42+
Context.Entry(entity).State = EntityState.Modified;
43+
}
44+
45+
protected override void SaveChanges()
46+
{
47+
Context.SaveChanges();
48+
}
49+
50+
protected override IQueryable<T> BaseQuery(IFetchStrategy<T> fetchStrategy = null)
51+
{
52+
var query = DbSet.AsQueryable();
53+
return fetchStrategy == null ? query : fetchStrategy.IncludePaths.Aggregate(query, (current, path) => current.Include(path));
54+
}
55+
56+
// we override the implementation fro LinqBaseRepository becausee this is built in and doesn't need to find the key column and do dynamic expressions, etc.
57+
protected override T GetQuery(params object[] keys)
58+
{
59+
return DbSet.Find(keys);
60+
}
61+
62+
public override void Dispose()
63+
{
64+
Dispose(true);
65+
GC.SuppressFinalize(this);
66+
}
67+
68+
protected virtual void Dispose(bool disposing)
69+
{
70+
if (!disposing) return;
71+
if (Context == null) return;
72+
73+
Context.Dispose();
74+
Context = null;
75+
}
76+
}
77+
1178
public class Ef5CompoundKeyRepositoryBase<T, TKey, TKey2> : LinqCompoundKeyRepositoryBase<T, TKey, TKey2> where T : class, new()
1279
{
1380
protected IDbSet<T> DbSet { get; private set; }
@@ -27,17 +94,6 @@ private void Initialize(DbContext dbContext)
2794

2895
protected override void AddItem(T entity)
2996
{
30-
if ((typeof(TKey) == typeof(Guid) || typeof(TKey) == typeof(string)) && (typeof(TKey2) == typeof(Guid) || typeof(TKey2) == typeof(string)))
31-
{
32-
TKey key;
33-
TKey2 key2;
34-
if (GetPrimaryKey(entity, out key, out key2) && Equals(key, default(TKey)) && Equals(key2, default(TKey2)))
35-
{
36-
key = GenerateFirstPrimaryKey();
37-
key2 = GenerateSecondPrimaryKey();
38-
SetPrimaryKey(entity, key, key2);
39-
}
40-
}
4197
DbSet.Add(entity);
4298
}
4399

SharpRepository.Ef5Repository/Ef5Repository.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ public Ef5Repository(DbContext dbContext, ICompoundKeyCachingStrategy<T, TKey, T
1212
}
1313
}
1414

15+
public class Ef5CompoundKeyRepository<T> : Ef5CompoundKeyRepositoryBase<T> where T : class, new()
16+
{
17+
public Ef5CompoundKeyRepository(DbContext dbContext, ICompoundKeyCachingStrategy<T> cachingStrategy = null)
18+
: base(dbContext, cachingStrategy)
19+
{
20+
}
21+
}
22+
1523
/// <summary>
1624
/// Entity Framework repository layer
1725
/// </summary>

SharpRepository.InMemoryRepository/InMemoryCompoundKeyRepositoryBase.cs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,105 @@
88

99
namespace SharpRepository.InMemoryRepository
1010
{
11+
public abstract class InMemoryCompoundKeyRepositoryBase<T> : LinqCompoundKeyRepositoryBase<T> where T : class, new()
12+
{
13+
private readonly ConcurrentDictionary<string, T> _items = new ConcurrentDictionary<string, T>();
14+
15+
internal InMemoryCompoundKeyRepositoryBase(ICompoundKeyCachingStrategy<T> cachingStrategy = null)
16+
: base(cachingStrategy)
17+
{
18+
}
19+
20+
protected override IQueryable<T> BaseQuery(IFetchStrategy<T> fetchStrategy = null)
21+
{
22+
return CloneDictionary(_items).AsQueryable();
23+
}
24+
25+
protected override T GetQuery(params object[] keys)
26+
{
27+
T result;
28+
_items.TryGetValue(String.Join("/", keys), out result);
29+
30+
return result;
31+
}
32+
33+
private static IEnumerable<T> CloneDictionary(ConcurrentDictionary<string, T> list)
34+
{
35+
// when you Google deep copy of generic list every answer uses either the IClonable interface on the T or having the T be Serializable
36+
// since we can't really put those constraints on T I'm going to do it via reflection
37+
38+
var type = typeof(T);
39+
var properties = type.GetProperties();
40+
41+
var clonedList = new List<T>(list.Count);
42+
43+
foreach (var keyValuePair in list)
44+
{
45+
var newItem = new T();
46+
foreach (var propInfo in properties)
47+
{
48+
propInfo.SetValue(newItem, propInfo.GetValue(keyValuePair.Value, null), null);
49+
}
50+
51+
clonedList.Add(newItem);
52+
}
53+
54+
return clonedList;
55+
}
56+
57+
protected override void AddItem(T entity)
58+
{
59+
object[] keys;
60+
61+
if (!GetPrimaryKeys(entity, out keys))
62+
{
63+
throw new ArgumentException("Primary keys not set");
64+
}
65+
66+
_items[String.Join("/", keys)] = entity;
67+
}
68+
69+
protected override void DeleteItem(T entity)
70+
{
71+
object[] keys;
72+
73+
if (!GetPrimaryKeys(entity, out keys))
74+
{
75+
throw new ArgumentException("Primary keys not set");
76+
}
77+
78+
T tmp;
79+
_items.TryRemove(String.Join("/", keys), out tmp);
80+
}
81+
82+
protected override void UpdateItem(T entity)
83+
{
84+
object[] keys;
85+
86+
if (!GetPrimaryKeys(entity, out keys))
87+
{
88+
throw new ArgumentException("Primary keys not set");
89+
}
90+
91+
_items[String.Join("/", keys)] = entity;
92+
}
93+
94+
protected override void SaveChanges()
95+
{
96+
97+
}
98+
99+
public override void Dispose()
100+
{
101+
102+
}
103+
104+
public override string ToString()
105+
{
106+
return "SharpRepository.InMemoryRepository";
107+
}
108+
}
109+
11110
public abstract class InMemoryCompoundKeyRepositoryBase<T, TKey, TKey2> : LinqCompoundKeyRepositoryBase<T, TKey, TKey2> where T : class, new()
12111
{
13112
private struct CompoundKey

SharpRepository.InMemoryRepository/InMemoryRepository.cs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,32 @@
22

33
namespace SharpRepository.InMemoryRepository
44
{
5-
public class InMemoryRepository<T, TKey, TKey2> : InMemoryCompoundKeyRepositoryBase<T, TKey, TKey2> where T : class, new()
5+
public class InMemoryRepository<T, TKey> : InMemoryRepositoryBase<T, TKey> where T : class, new()
66
{
7-
public InMemoryRepository(ICompoundKeyCachingStrategy<T, TKey, TKey2> cachingStrategy = null)
7+
public InMemoryRepository(ICachingStrategy<T, TKey> cachingStrategy = null) : base(cachingStrategy)
8+
{
9+
}
10+
}
11+
12+
public class InMemoryRepository<T> : InMemoryRepositoryBase<T, int> where T : class, new()
13+
{
14+
public InMemoryRepository(ICachingStrategy<T, int> cachingStrategy = null)
815
: base(cachingStrategy)
916
{
1017
}
1118
}
1219

13-
public class InMemoryRepository<T, TKey> : InMemoryRepositoryBase<T, TKey> where T : class, new()
20+
public class InMemoryCompoundKeyRepository<T> : InMemoryCompoundKeyRepositoryBase<T> where T : class, new()
1421
{
15-
public InMemoryRepository(ICachingStrategy<T, TKey> cachingStrategy = null) : base(cachingStrategy)
16-
{
22+
public InMemoryCompoundKeyRepository(ICompoundKeyCachingStrategy<T> cachingStrategy = null)
23+
: base(cachingStrategy)
24+
{
1725
}
1826
}
1927

20-
public class InMemoryRepository<T> : InMemoryRepositoryBase<T, int> where T : class, new()
28+
public class InMemoryRepository<T, TKey, TKey2> : InMemoryCompoundKeyRepositoryBase<T, TKey, TKey2> where T : class, new()
2129
{
22-
public InMemoryRepository(ICachingStrategy<T, int> cachingStrategy = null)
30+
public InMemoryRepository(ICompoundKeyCachingStrategy<T, TKey, TKey2> cachingStrategy = null)
2331
: base(cachingStrategy)
2432
{
2533
}

0 commit comments

Comments
 (0)