Skip to content

Commit 0426001

Browse files
Merge pull request #2 from johelvisguzman/feature/ef6
Introduced a new entity framework repository
2 parents 3c516c2 + 7953b75 commit 0426001

File tree

20 files changed

+1066
-18
lines changed

20 files changed

+1066
-18
lines changed

DotNetToolkit.Repository.sln

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio 15
4-
VisualStudioVersion = 15.0.27130.2003
4+
VisualStudioVersion = 15.0.27004.2006
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{DD273D5E-6D6C-41FA-A0C8-646CC53C4DC3}"
77
EndProject
88
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetToolkit.Repository", "src\DotNetToolkit.Repository\DotNetToolkit.Repository.csproj", "{76BC5AB7-1198-4C99-B2C3-3B734931F8EE}"
99
EndProject
1010
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{DAB3DD1E-AD99-46C9-AC42-07E2F03D5A06}"
1111
EndProject
12-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetToolkit.Repository.Test", "test\DotNetToolkit.Repository.Test\DotNetToolkit.Repository.Test.csproj", "{EAE7B507-D908-4650-A301-C3341F005A51}"
12+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetToolkit.Repository.Test", "test\DotNetToolkit.Repository.Test\DotNetToolkit.Repository.Test.csproj", "{EAE7B507-D908-4650-A301-C3341F005A51}"
13+
EndProject
14+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetToolkit.Repository.EntityFramework", "src\DotNetToolkit.Repository.EntityFramework\DotNetToolkit.Repository.EntityFramework.csproj", "{8DBCF7DE-532D-45DF-A6B8-5D89415C5B77}"
15+
EndProject
16+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetToolkit.Repository.Integration.Test", "test\DotNetToolkit.Repository.Integration.Test\DotNetToolkit.Repository.Integration.Test.csproj", "{2F99B66F-A347-4E8D-8ACA-5A34246A1FA6}"
1317
EndProject
1418
Global
1519
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -25,13 +29,23 @@ Global
2529
{EAE7B507-D908-4650-A301-C3341F005A51}.Debug|Any CPU.Build.0 = Debug|Any CPU
2630
{EAE7B507-D908-4650-A301-C3341F005A51}.Release|Any CPU.ActiveCfg = Release|Any CPU
2731
{EAE7B507-D908-4650-A301-C3341F005A51}.Release|Any CPU.Build.0 = Release|Any CPU
32+
{8DBCF7DE-532D-45DF-A6B8-5D89415C5B77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33+
{8DBCF7DE-532D-45DF-A6B8-5D89415C5B77}.Debug|Any CPU.Build.0 = Debug|Any CPU
34+
{8DBCF7DE-532D-45DF-A6B8-5D89415C5B77}.Release|Any CPU.ActiveCfg = Release|Any CPU
35+
{8DBCF7DE-532D-45DF-A6B8-5D89415C5B77}.Release|Any CPU.Build.0 = Release|Any CPU
36+
{2F99B66F-A347-4E8D-8ACA-5A34246A1FA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37+
{2F99B66F-A347-4E8D-8ACA-5A34246A1FA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
38+
{2F99B66F-A347-4E8D-8ACA-5A34246A1FA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
39+
{2F99B66F-A347-4E8D-8ACA-5A34246A1FA6}.Release|Any CPU.Build.0 = Release|Any CPU
2840
EndGlobalSection
2941
GlobalSection(SolutionProperties) = preSolution
3042
HideSolutionNode = FALSE
3143
EndGlobalSection
3244
GlobalSection(NestedProjects) = preSolution
3345
{76BC5AB7-1198-4C99-B2C3-3B734931F8EE} = {DD273D5E-6D6C-41FA-A0C8-646CC53C4DC3}
3446
{EAE7B507-D908-4650-A301-C3341F005A51} = {DAB3DD1E-AD99-46C9-AC42-07E2F03D5A06}
47+
{8DBCF7DE-532D-45DF-A6B8-5D89415C5B77} = {DD273D5E-6D6C-41FA-A0C8-646CC53C4DC3}
48+
{2F99B66F-A347-4E8D-8ACA-5A34246A1FA6} = {DAB3DD1E-AD99-46C9-AC42-07E2F03D5A06}
3549
EndGlobalSection
3650
GlobalSection(ExtensibilityGlobals) = postSolution
3751
SolutionGuid = {96973E0C-81D1-42DE-9F78-7103241B4E07}

appveyor.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,14 @@ build:
4444

4545
after_build:
4646
- dotnet pack .\src\DotNetToolkit.Repository\DotNetToolkit.Repository.csproj --configuration Release
47+
- dotnet pack .\src\DotNetToolkit.Repository.EntityFramework\DotNetToolkit.Repository.EntityFramework.csproj --configuration Release
4748

4849
#---------------------------------#
4950
# tests configuration #
5051
#---------------------------------#
5152
test_script:
5253
- dotnet test .\test\DotNetToolkit.Repository.Test\DotNetToolkit.Repository.Test.csproj --configuration Release
54+
- dotnet test .\test\DotNetToolkit.Repository.Integration.Test\DotNetToolkit.Repository.Integration.Test.csproj --configuration Release
5355

5456
artifacts:
5557
- path: '**\DotNetToolkit.Repository.*.nupkg' # find all NuGet packages recursively
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<Import Project="..\..\build\common.props" />
4+
5+
<PropertyGroup>
6+
<TargetFramework>net451</TargetFramework>
7+
<AssemblyName>DotNetToolkit.Repository.EntityFramework</AssemblyName>
8+
<RootNamespace>DotNetToolkit.Repository.EntityFramework</RootNamespace>
9+
<Description>A toolkit that provides a lightweight starter kit for using the Repository pattern for the Entity Framework.</Description>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="EntityFramework" Version="6.2.0" />
14+
</ItemGroup>
15+
16+
<ItemGroup>
17+
<ProjectReference Include="..\DotNetToolkit.Repository\DotNetToolkit.Repository.csproj" />
18+
</ItemGroup>
19+
20+
</Project>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
namespace DotNetToolkit.Repository.EntityFramework
2+
{
3+
using System.Data.Entity;
4+
5+
/// <summary>
6+
/// Represents a repository for entity framework.
7+
/// </summary>
8+
public class EfRepository<TEntity, TKey> : EfRepositoryBase<TEntity, TKey> where TEntity : class
9+
{
10+
#region Constructors
11+
12+
/// <summary>
13+
/// Initializes a new instance of the <see cref="EfRepository{TEntity, TKey}" /> class.
14+
/// </summary>
15+
/// <param name="context">The database context.</param>
16+
public EfRepository(DbContext context) : base(context) { }
17+
18+
#endregion
19+
}
20+
21+
/// <summary>
22+
/// Represents a repository for entity framework with a default primary key value of type integer.
23+
/// </summary>
24+
public class EfRepository<TEntity> : EfRepositoryBase<TEntity, int> where TEntity : class
25+
{
26+
#region Constructors
27+
28+
/// <summary>
29+
/// Initializes a new instance of the <see cref="EfRepository{TEntity}" /> class.
30+
/// </summary>
31+
/// <param name="context">The database context.</param>
32+
public EfRepository(DbContext context) : base(context) { }
33+
34+
#endregion
35+
}
36+
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
namespace DotNetToolkit.Repository.EntityFramework
2+
{
3+
using FetchStrategies;
4+
using System;
5+
using System.Data.Entity;
6+
using System.Linq;
7+
8+
/// <summary>
9+
/// Represents a repository for entity framework.
10+
/// </summary>
11+
public abstract class EfRepositoryBase<TEntity, TKey> : RepositoryBase<TEntity, TKey> where TEntity : class
12+
{
13+
#region Fields
14+
15+
private bool _disposed;
16+
17+
#endregion
18+
19+
#region Properties
20+
21+
/// <summary>
22+
/// Gets the entity set.
23+
/// </summary>
24+
protected IDbSet<TEntity> DbSet { get; private set; }
25+
26+
/// <summary>
27+
/// Gets the database context.
28+
/// </summary>
29+
protected DbContext Context { get; private set; }
30+
31+
#endregion
32+
33+
#region Constructors
34+
35+
/// <summary>
36+
/// Initializes a new instance of the <see cref="EfRepositoryBase{TEntity, TKey}" /> class.
37+
/// </summary>
38+
/// <param name="context">The database context.</param>
39+
protected EfRepositoryBase(DbContext context)
40+
{
41+
if (context == null)
42+
throw new ArgumentNullException(nameof(context));
43+
44+
Context = context;
45+
DbSet = Context.Set<TEntity>();
46+
}
47+
48+
#endregion
49+
50+
#region Protected Methods
51+
52+
/// <summary>
53+
/// Releases unmanaged and - optionally - managed resources.
54+
/// </summary>
55+
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
56+
protected virtual void Dispose(bool disposing)
57+
{
58+
if (_disposed) return;
59+
60+
if (disposing)
61+
{
62+
if (Context != null)
63+
{
64+
Context.Dispose();
65+
}
66+
}
67+
68+
_disposed = true;
69+
}
70+
71+
#endregion
72+
73+
#region Overrides of RepositoryBase<TEntity,TKey>
74+
75+
/// <summary>
76+
/// A protected overridable method for adding the specified <paramref name="entity" /> into the repository.
77+
/// </summary>
78+
protected override void AddItem(TEntity entity)
79+
{
80+
DbSet.Add(entity);
81+
}
82+
83+
/// <summary>
84+
/// A protected overridable method for deleting the specified <paramref name="entity" /> from the repository.
85+
/// </summary>
86+
protected override void DeleteItem(TEntity entity)
87+
{
88+
DbSet.Remove(entity);
89+
}
90+
91+
/// <summary>
92+
/// A protected overridable method for updating the specified <paramref name="entity" /> in the repository.
93+
/// </summary>
94+
protected override void UpdateItem(TEntity entity)
95+
{
96+
Context.Entry(entity).State = EntityState.Modified;
97+
}
98+
99+
/// <summary>
100+
/// A protected overridable method for saving changes made in the current unit of work in the repository.
101+
/// </summary>
102+
protected override void SaveChanges()
103+
{
104+
Context.SaveChanges();
105+
}
106+
107+
/// <summary>
108+
/// A protected overridable method for getting an entity query that supplies the specified fetching strategy from the repository.
109+
/// </summary>
110+
protected override IQueryable<TEntity> GetQuery(IFetchStrategy<TEntity> fetchStrategy = null)
111+
{
112+
var query = DbSet.AsQueryable();
113+
return fetchStrategy == null ? query : fetchStrategy.IncludePaths.Aggregate(query, (current, path) => current.Include(path));
114+
}
115+
116+
/// <summary>
117+
/// Gets an entity query with the given primary key value from the repository.
118+
/// </summary>
119+
protected override TEntity GetQuery(TKey key, IFetchStrategy<TEntity> fetchStrategy)
120+
{
121+
return fetchStrategy == null ? DbSet.Find(key) : base.GetQuery(key, fetchStrategy);
122+
}
123+
124+
/// <summary>
125+
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
126+
/// </summary>
127+
public override void Dispose()
128+
{
129+
Dispose(true);
130+
GC.SuppressFinalize(this);
131+
}
132+
133+
#endregion
134+
}
135+
}

src/DotNetToolkit.Repository/DotNetToolkit.Repository.csproj

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,19 @@
1313
<PackageReference Include="System.Linq.Queryable" Version="4.3.0" />
1414
</ItemGroup>
1515

16+
<ItemGroup>
17+
<Compile Update="Properties\Resources.Designer.cs">
18+
<DesignTime>True</DesignTime>
19+
<AutoGen>True</AutoGen>
20+
<DependentUpon>Resources.resx</DependentUpon>
21+
</Compile>
22+
</ItemGroup>
23+
24+
<ItemGroup>
25+
<EmbeddedResource Update="Properties\Resources.resx">
26+
<Generator>ResXFileCodeGenerator</Generator>
27+
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
28+
</EmbeddedResource>
29+
</ItemGroup>
30+
1631
</Project>
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
namespace DotNetToolkit.Repository.Helpers
2+
{
3+
using Properties;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Globalization;
7+
using System.Reflection;
8+
9+
internal static class ConventionHelper
10+
{
11+
/// <summary>
12+
/// Gets the value of the specified object primary key property.
13+
/// </summary>
14+
/// <param name="obj">The object containing the property.</param>
15+
/// <returns>The property value.</returns>
16+
/// <exception cref="System.ArgumentNullException"><paramref name="obj" /> is <c>null</c>.</exception>
17+
/// <exception cref="System.InvalidOperationException">Primary key could not be found for the entity type.</exception>
18+
public static object GetPrimaryKeyPropertyValue(object obj)
19+
{
20+
if (obj == null)
21+
throw new ArgumentNullException(nameof(obj));
22+
23+
var propertyInfo = GetPrimaryKeyPropertyInfo(obj.GetType());
24+
return propertyInfo.GetValue(obj, null);
25+
}
26+
27+
/// <summary>
28+
/// Sets a value for the specified object primary key property.
29+
/// </summary>
30+
/// <param name="obj">The object containing the property.</param>
31+
/// <param name="value">The value to set for the property.</param>
32+
/// <exception cref="System.ArgumentNullException"><paramref name="obj" /> is <c>null</c>.</exception>
33+
/// <exception cref="System.InvalidOperationException">The instance of entity type requires a primary key to be defined.</exception>
34+
public static void SetPrimaryKeyPropertyValue(object obj, object value)
35+
{
36+
if (obj == null)
37+
throw new ArgumentNullException(nameof(obj));
38+
39+
var propertyInfo = GetPrimaryKeyPropertyInfo(obj.GetType());
40+
propertyInfo.SetValue(obj, value, null);
41+
}
42+
43+
/// <summary>
44+
/// Gets the primary key property information for the specified type.
45+
/// </summary>
46+
/// <param name="entityType">The entity type to get the primary key from.</param>
47+
/// <returns>The primary key property info.</returns>
48+
/// <exception cref="System.ArgumentNullException"><paramref name="entityType" /> is <c>null</c>.</exception>
49+
/// <exception cref="System.InvalidOperationException">The instance of entity type requires a primary key to be defined.</exception>
50+
public static PropertyInfo GetPrimaryKeyPropertyInfo(Type entityType)
51+
{
52+
if (entityType == null)
53+
throw new ArgumentNullException(nameof(entityType));
54+
55+
foreach (var propertyName in GetPrimaryKeyNameChecks(entityType))
56+
{
57+
var propInfo = entityType.GetTypeInfo().GetDeclaredProperty(propertyName);
58+
59+
if (propInfo != null)
60+
{
61+
return propInfo;
62+
}
63+
}
64+
65+
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resources.EntityRequiresPrimaryKey, entityType));
66+
}
67+
68+
/// <summary>
69+
/// Gets the primary key name checks.
70+
/// </summary>
71+
/// <param name="entityType">The entity type to get the primary key from.</param>
72+
/// <remarks>Assumes the entity has either an 'Id' property or 'EntityName' + 'Id'.</remarks>
73+
/// <returns>The list of primary key names to check.</returns>
74+
private static IEnumerable<string> GetPrimaryKeyNameChecks(Type entityType)
75+
{
76+
const string suffix = "Id";
77+
return new[] { suffix, entityType.Name + suffix };
78+
}
79+
}
80+
}

src/DotNetToolkit.Repository/IRepository.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
namespace DotNetToolkit.Repository
22
{
3+
using System;
34
using Traits;
45

56
/// <summary>
6-
/// Represents a repository for the unit of work and repository pattern.
7+
/// Represents a repository.
78
/// </summary>
89
/// <typeparam name="TEntity">The type of the entity.</typeparam>
910
/// <typeparam name="TKey">The type of the primary key.</typeparam>
10-
public interface IRepository<TEntity, in TKey> : ICanAdd<TEntity>, ICanUpdate<TEntity>, ICanDelete<TEntity, TKey>, ICanGet<TEntity, TKey>, ICanFind<TEntity>
11+
public interface IRepository<TEntity, in TKey> : ICanAggregate<TEntity>, ICanAdd<TEntity>, ICanUpdate<TEntity>, ICanDelete<TEntity, TKey>, ICanGet<TEntity, TKey>, ICanFind<TEntity>, IDisposable
1112
where TEntity : class
1213
{
1314
}

0 commit comments

Comments
 (0)