├── .gitignore ├── LICENSE.md ├── OfferingSolutions.GenericEFCore.SampleApp ├── DataBaseContext.cs ├── ExampleRepositories │ ├── IPersonRepository.cs │ └── PersonRepository.cs ├── Migrations │ ├── 20190829134133_CreateDatabase.Designer.cs │ ├── 20190829134133_CreateDatabase.cs │ └── DataBaseContextModelSnapshot.cs ├── Models │ ├── Person.cs │ └── Thing.cs ├── OfferingSolutions.GenericEFCore.SampleApp.csproj └── Program.cs ├── OfferingSolutions.GenericEFCore.Tests ├── CustomRepositoryTests.cs ├── DataBaseContext.cs ├── ExampleRepositories │ ├── IPersonRepository.cs │ └── PersonRepository.cs ├── Models │ ├── Person.cs │ └── Thing.cs └── OfferingSolutions.GenericEFCore.Tests.csproj ├── OfferingSolutions.GenericEFCore.sln ├── OfferingSolutions.GenericEFCore ├── BaseContext │ └── ContextBase.cs ├── OfferingSolutions.GenericEFCore.csproj ├── RepositoryBase │ ├── GenericRepositoryBase.cs │ └── IGenericRepositoryBase.cs ├── RepositoryContext │ ├── GenericRepositoryContext.cs │ └── IGenericRepositoryContext.cs ├── Services │ ├── Factory.cs │ ├── IRepositoryService.cs │ └── RepositoryServiceImpl.cs ├── UnitOfWork │ ├── IOsUnitOfWork.cs │ └── OsUnitOfWork.cs └── UnitOfWorkContext │ ├── IOsUnitOfWorkContext.cs │ └── OsUnitOfWorkContext.cs ├── README.md └── azure-builds └── build.yml /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | OfferingSolutions.UoWCore.SampleApp/bin/ 3 | OfferingSolutions.UoWCore/bin/ 4 | OfferingSolutions.UoWCore.SampleApp/obj/ 5 | 6 | /OfferingSolutions.GenericEFCore.SampleApp/bin/ 7 | /OfferingSolutions.GenericEFCore.SampleApp/obj 8 | /OfferingSolutions.GenericEFCore/bin 9 | /OfferingSolutions.GenericEFCore/obj 10 | .vscode/launch.json 11 | .vscode/tasks.json 12 | /OfferingSolutions.GenericEFCore.Tests/bin 13 | /OfferingSolutions.GenericEFCore.Tests/obj 14 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | Copyright (c) 2019 Fabian Gosebrink 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore.SampleApp/DataBaseContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using OfferingSolutions.GenericEFCore.SampleApp.Models; 3 | 4 | namespace OfferingSolutions.GenericEFCore.SampleApp 5 | { 6 | public class DataBaseContext : DbContext 7 | { 8 | public DbSet Persons { get; set; } 9 | public DbSet Things { get; set; } 10 | 11 | protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 12 | { 13 | optionsBuilder.UseSqlServer(@"Server=.\SQLEXPRESS;Database=GenericEFCore;Trusted_Connection=True;"); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore.SampleApp/ExampleRepositories/IPersonRepository.cs: -------------------------------------------------------------------------------- 1 | using OfferingSolutions.GenericEFCore.RepositoryContext; 2 | using OfferingSolutions.GenericEFCore.SampleApp.Models; 3 | 4 | namespace SampleApp.ExampleRepositories 5 | { 6 | interface IPersonRepository : IGenericRepositoryContext 7 | { 8 | void MyNewFunction(int id); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore.SampleApp/ExampleRepositories/PersonRepository.cs: -------------------------------------------------------------------------------- 1 | using OfferingSolutions.GenericEFCore.RepositoryContext; 2 | using OfferingSolutions.GenericEFCore.SampleApp; 3 | using OfferingSolutions.GenericEFCore.SampleApp.Models; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | namespace SampleApp.ExampleRepositories 8 | { 9 | public class PersonRepository : GenericRepositoryContext, IPersonRepository 10 | { 11 | public PersonRepository(DataBaseContext dbContext) 12 | : base(dbContext) 13 | { 14 | 15 | } 16 | 17 | public void MyNewFunction(int id) 18 | { 19 | //Do Something 20 | } 21 | 22 | public new List GetAll() 23 | { 24 | return base.GetAll().ToList(); 25 | } 26 | 27 | public override void Add(Person toAdd) 28 | { 29 | MyAdditionalAddFunction(); 30 | base.Add(toAdd); 31 | } 32 | 33 | private void MyAdditionalAddFunction() 34 | { 35 | //Do something else... 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore.SampleApp/Migrations/20190829134133_CreateDatabase.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | using OfferingSolutions.GenericEFCore.SampleApp; 9 | 10 | namespace OfferingSolutions.GenericEFCore.SampleApp.Migrations 11 | { 12 | [DbContext(typeof(DataBaseContext))] 13 | [Migration("20190829134133_CreateDatabase")] 14 | partial class CreateDatabase 15 | { 16 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 17 | { 18 | #pragma warning disable 612, 618 19 | modelBuilder 20 | .HasAnnotation("ProductVersion", "2.2.6-servicing-10079") 21 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 22 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 23 | 24 | modelBuilder.Entity("OfferingSolutions.GenericEFCore.SampleApp.Models.Person", b => 25 | { 26 | b.Property("Id") 27 | .ValueGeneratedOnAdd() 28 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 29 | 30 | b.Property("Age"); 31 | 32 | b.Property("Name"); 33 | 34 | b.HasKey("Id"); 35 | 36 | b.ToTable("Persons"); 37 | }); 38 | 39 | modelBuilder.Entity("OfferingSolutions.GenericEFCore.SampleApp.Models.Thing", b => 40 | { 41 | b.Property("Id") 42 | .ValueGeneratedOnAdd() 43 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 44 | 45 | b.Property("Name"); 46 | 47 | b.Property("PersonId"); 48 | 49 | b.HasKey("Id"); 50 | 51 | b.HasIndex("PersonId"); 52 | 53 | b.ToTable("Things"); 54 | }); 55 | 56 | modelBuilder.Entity("OfferingSolutions.GenericEFCore.SampleApp.Models.Thing", b => 57 | { 58 | b.HasOne("OfferingSolutions.GenericEFCore.SampleApp.Models.Person") 59 | .WithMany("Things") 60 | .HasForeignKey("PersonId"); 61 | }); 62 | #pragma warning restore 612, 618 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore.SampleApp/Migrations/20190829134133_CreateDatabase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Metadata; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | namespace OfferingSolutions.GenericEFCore.SampleApp.Migrations 5 | { 6 | public partial class CreateDatabase : Migration 7 | { 8 | protected override void Up(MigrationBuilder migrationBuilder) 9 | { 10 | migrationBuilder.CreateTable( 11 | name: "Persons", 12 | columns: table => new 13 | { 14 | Id = table.Column(nullable: false) 15 | .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 16 | Name = table.Column(nullable: true), 17 | Age = table.Column(nullable: false) 18 | }, 19 | constraints: table => 20 | { 21 | table.PrimaryKey("PK_Persons", x => x.Id); 22 | }); 23 | 24 | migrationBuilder.CreateTable( 25 | name: "Things", 26 | columns: table => new 27 | { 28 | Id = table.Column(nullable: false) 29 | .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 30 | Name = table.Column(nullable: true), 31 | PersonId = table.Column(nullable: true) 32 | }, 33 | constraints: table => 34 | { 35 | table.PrimaryKey("PK_Things", x => x.Id); 36 | table.ForeignKey( 37 | name: "FK_Things_Persons_PersonId", 38 | column: x => x.PersonId, 39 | principalTable: "Persons", 40 | principalColumn: "Id", 41 | onDelete: ReferentialAction.Restrict); 42 | }); 43 | 44 | migrationBuilder.CreateIndex( 45 | name: "IX_Things_PersonId", 46 | table: "Things", 47 | column: "PersonId"); 48 | } 49 | 50 | protected override void Down(MigrationBuilder migrationBuilder) 51 | { 52 | migrationBuilder.DropTable( 53 | name: "Things"); 54 | 55 | migrationBuilder.DropTable( 56 | name: "Persons"); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore.SampleApp/Migrations/DataBaseContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 7 | using OfferingSolutions.GenericEFCore.SampleApp; 8 | 9 | namespace OfferingSolutions.GenericEFCore.SampleApp.Migrations 10 | { 11 | [DbContext(typeof(DataBaseContext))] 12 | partial class DataBaseContextModelSnapshot : ModelSnapshot 13 | { 14 | protected override void BuildModel(ModelBuilder modelBuilder) 15 | { 16 | #pragma warning disable 612, 618 17 | modelBuilder 18 | .HasAnnotation("ProductVersion", "2.2.6-servicing-10079") 19 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 20 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 21 | 22 | modelBuilder.Entity("OfferingSolutions.GenericEFCore.SampleApp.Models.Person", b => 23 | { 24 | b.Property("Id") 25 | .ValueGeneratedOnAdd() 26 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 27 | 28 | b.Property("Age"); 29 | 30 | b.Property("Name"); 31 | 32 | b.HasKey("Id"); 33 | 34 | b.ToTable("Persons"); 35 | }); 36 | 37 | modelBuilder.Entity("OfferingSolutions.GenericEFCore.SampleApp.Models.Thing", b => 38 | { 39 | b.Property("Id") 40 | .ValueGeneratedOnAdd() 41 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 42 | 43 | b.Property("Name"); 44 | 45 | b.Property("PersonId"); 46 | 47 | b.HasKey("Id"); 48 | 49 | b.HasIndex("PersonId"); 50 | 51 | b.ToTable("Things"); 52 | }); 53 | 54 | modelBuilder.Entity("OfferingSolutions.GenericEFCore.SampleApp.Models.Thing", b => 55 | { 56 | b.HasOne("OfferingSolutions.GenericEFCore.SampleApp.Models.Person") 57 | .WithMany("Things") 58 | .HasForeignKey("PersonId"); 59 | }); 60 | #pragma warning restore 612, 618 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore.SampleApp/Models/Person.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace OfferingSolutions.GenericEFCore.SampleApp.Models 7 | { 8 | public class Person 9 | { 10 | public int Id { get; set; } 11 | public string Name { get; set; } 12 | public int Age { get; set; } 13 | public List Things { get; set; } 14 | 15 | public override string ToString() 16 | { 17 | return $"{Name} {Age}"; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore.SampleApp/Models/Thing.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace OfferingSolutions.GenericEFCore.SampleApp.Models 7 | { 8 | public class Thing 9 | { 10 | public int Id { get; set; } 11 | public string Name { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore.SampleApp/OfferingSolutions.GenericEFCore.SampleApp.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | all 13 | runtime; build; native; contentfiles; analyzers; buildtransitive 14 | 15 | 16 | all 17 | runtime; build; native; contentfiles; analyzers; buildtransitive 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore.SampleApp/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Query; 3 | using OfferingSolutions.GenericEFCore.SampleApp.Models; 4 | using OfferingSolutions.GenericEFCore.UnitOfWorkContext; 5 | using SampleApp.ExampleRepositories; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | 10 | namespace OfferingSolutions.GenericEFCore.SampleApp 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | try 17 | { 18 | using (IOsUnitOfWorkContext unitOfWorkContext = new OsUnitOfWorkContext(new DataBaseContext())) 19 | { 20 | Person person = new Person() 21 | { 22 | Age = 35, 23 | Name = "Fabian", 24 | Things = new List() { 25 | new Thing() 26 | { 27 | Name = "A Thing" 28 | } 29 | } 30 | }; 31 | 32 | // Adding a new Entity, for example "Person" 33 | unitOfWorkContext.Add(person); 34 | 35 | // Savechanges 36 | unitOfWorkContext.Save(); 37 | 38 | unitOfWorkContext.SaveASync(); 39 | 40 | // Get all Persons 41 | var persons = unitOfWorkContext.GetAll().ToList(); 42 | var personsAsync = unitOfWorkContext.GetAllAsync(); 43 | 44 | foreach (var item in persons) 45 | { 46 | Console.WriteLine(item.Name + " " + item.Age); 47 | } 48 | 49 | List allPersonsOnAge35 = unitOfWorkContext.GetAll(x => x.Age == 35).ToList(); 50 | var countAll = unitOfWorkContext.Count(); 51 | var countAllWithpredicate = unitOfWorkContext.Count(x => x.Age == 35); 52 | 53 | Console.WriteLine(allPersonsOnAge35.Count); 54 | 55 | // Get all Persons with the age of 35 ordered by Name 56 | List allPersonsOnAge35Ordered = unitOfWorkContext.GetAll(x => x.Age == 35, orderBy: q => q.OrderBy(d => d.Name)).ToList(); 57 | 58 | // Get all Persons with the age of 35 ordered by Name and include its properties 59 | Func, IIncludableQueryable> include = source => source.Include(y => y.Things); 60 | 61 | List allPersonsOnAge35OrderedAndWithThings = unitOfWorkContext.GetAll( 62 | x => x.Age == 35, 63 | orderBy: q => q.OrderBy(d => d.Name), 64 | include: include) 65 | .ToList(); 66 | 67 | // Get all Persons and include its properties 68 | List allPersonsWithThings = unitOfWorkContext.GetAll(include: include).ToList(); 69 | 70 | // Find a single Person with a specific name, is null if not found 71 | Person findBy = unitOfWorkContext.GetSingle(x => x.Id == 6); 72 | var findByASync = unitOfWorkContext.GetSingleAsync(x => x.Id == 6); 73 | 74 | // Find a single Person with a specific name and include its siblings 75 | Person findByWithThings = unitOfWorkContext.GetSingle(x => x.Name == "Fabian", include: include); 76 | 77 | // Find a person by id but throws exception if not found 78 | // var personWithIdMayThrowException = unitOfWorkContext.GetSingleBy(x => x.Id == 6); 79 | // var personWithIdMayThrowExceptionASync = unitOfWorkContext.GetSingleByASync(x => x.Id == 6); 80 | 81 | // Update an existing person 82 | Person findOneToUpdate = unitOfWorkContext.GetSingle(x => x.Name == "Fabian"); 83 | findOneToUpdate.Name = "Fabian2"; 84 | 85 | unitOfWorkContext.Update(person); 86 | unitOfWorkContext.Save(); 87 | 88 | Person findOneAfterUpdate = unitOfWorkContext.GetSingle(x => x.Name == "Fabian2"); 89 | 90 | // Deleting a Person by Id or by entity 91 | unitOfWorkContext.Delete(person); 92 | } 93 | 94 | /////////////////////////////////////////////////////////////////// 95 | // Custom repositories 96 | /////////////////////////////////////////////////////////////////// 97 | 98 | using (IPersonRepository personRepository = new PersonRepository(new DataBaseContext())) 99 | { 100 | personRepository.Add(new Person() { Name = "John Doe" }); 101 | personRepository.Save(); 102 | var receivedPerson = personRepository.GetSingle(x => x.Name == "John Doe", source => source.Include(y => y.Things)); 103 | var allPersons = personRepository.GetAll(x => x.Name == "John Doe"); 104 | var allPersonCountWithPredicate = personRepository.Count(x => x.Name == "John Doe"); 105 | var allPersonsWithThings = personRepository.GetAll(x => x.Name == "John Doe", source => source.Include(y => y.Things), q => q.OrderBy(d => d.Name)); 106 | Console.WriteLine(receivedPerson); 107 | 108 | // Does something good ... 109 | personRepository.MyNewFunction(6); 110 | } 111 | 112 | Console.ReadLine(); 113 | } 114 | catch (Exception ex) 115 | { 116 | Console.WriteLine(ex); 117 | throw; 118 | } 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore.Tests/CustomRepositoryTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using OfferingSolutions.GenericEFCore.SampleApp.Models; 4 | using OfferingSolutions.GenericEFCore.Tests.ExampleRepositories; 5 | using System.Collections.Generic; 6 | 7 | namespace OfferingSolutions.GenericEFCore.Tests 8 | { 9 | [TestClass] 10 | public class CustomRepositoryTests 11 | { 12 | [TestMethod] 13 | public void Insert_Adds_To_Database() 14 | { 15 | // Arrange 16 | var options = new DbContextOptionsBuilder() 17 | .UseInMemoryDatabase(databaseName: nameof(Insert_Adds_To_Database)) 18 | .Options; 19 | 20 | // Act 21 | using (IPersonRepository personRepository = new PersonRepository(new DataBaseContext(options))) 22 | { 23 | personRepository.Add(new Person() { Name = "John Doe" }); 24 | personRepository.Save(); 25 | } 26 | 27 | // Assert 28 | using (IPersonRepository personRepository = new PersonRepository(new DataBaseContext(options))) 29 | { 30 | var savedPerson = personRepository.GetSingle(x => x.Name == "John Doe"); 31 | Assert.IsNotNull(savedPerson); 32 | Assert.IsNotNull(savedPerson.Id); 33 | } 34 | } 35 | 36 | [TestMethod] 37 | public void Count_Counts_Correct() 38 | { 39 | // Arrange 40 | var options = new DbContextOptionsBuilder() 41 | .UseInMemoryDatabase(databaseName: nameof(Count_Counts_Correct)) 42 | .Options; 43 | 44 | // Act 45 | using (IPersonRepository personRepository = new PersonRepository(new DataBaseContext(options))) 46 | { 47 | personRepository.Add(new Person() { Name = "John Doe" }); 48 | personRepository.Add(new Person() { Name = "Jane Doe" }); 49 | personRepository.Save(); 50 | } 51 | 52 | // Assert 53 | using (IPersonRepository personRepository = new PersonRepository(new DataBaseContext(options))) 54 | { 55 | var countWithPredicate = personRepository.Count(x => x.Name == "John Doe"); 56 | Assert.AreEqual(1, countWithPredicate); 57 | var overallCount = personRepository.Count(); 58 | Assert.AreEqual(2, overallCount); 59 | } 60 | } 61 | 62 | [TestMethod] 63 | public void Update_Modifies_Entry_In_Database() 64 | { 65 | // Arrange 66 | var options = new DbContextOptionsBuilder() 67 | .UseInMemoryDatabase(databaseName: nameof(Update_Modifies_Entry_In_Database)) 68 | .Options; 69 | 70 | // Act 71 | using (IPersonRepository personRepository = new PersonRepository(new DataBaseContext(options))) 72 | { 73 | personRepository.Add(new Person() { Name = "John Doe" }); 74 | personRepository.Save(); 75 | var savedPerson = personRepository.GetSingle(x => x.Name == "John Doe"); 76 | savedPerson.Name = "Jane Doe"; 77 | personRepository.Update(savedPerson); 78 | personRepository.Save(); 79 | } 80 | 81 | // Assert 82 | using (IPersonRepository personRepository = new PersonRepository(new DataBaseContext(options))) 83 | { 84 | var savedPerson = personRepository.GetSingle(x => x.Name == "Jane Doe"); 85 | Assert.IsNotNull(savedPerson); 86 | Assert.IsNotNull(savedPerson.Id); 87 | } 88 | } 89 | 90 | [TestMethod] 91 | public void DeleteByEntity_Removes_Entry_From_Database() 92 | { 93 | // Arrange 94 | var options = new DbContextOptionsBuilder() 95 | .UseInMemoryDatabase(databaseName: nameof(DeleteByEntity_Removes_Entry_From_Database)) 96 | .Options; 97 | 98 | // Act 99 | using (IPersonRepository personRepository = new PersonRepository(new DataBaseContext(options))) 100 | { 101 | personRepository.Add(new Person() { Name = "John Doe" }); 102 | personRepository.Add(new Person() { Name = "Jane Doe" }); 103 | personRepository.Save(); 104 | var savedPerson = personRepository.GetSingle(x => x.Name == "John Doe"); 105 | personRepository.Delete(savedPerson); 106 | personRepository.Save(); 107 | } 108 | 109 | // Assert 110 | using (IPersonRepository personRepository = new PersonRepository(new DataBaseContext(options))) 111 | { 112 | var personCount = personRepository.Count(); 113 | Assert.AreEqual(1, personCount); 114 | } 115 | } 116 | 117 | [TestMethod] 118 | public void DeleteById_Removes_Entry_From_Database() 119 | { 120 | // Arrange 121 | var options = new DbContextOptionsBuilder() 122 | .UseInMemoryDatabase(databaseName: nameof(DeleteById_Removes_Entry_From_Database)) 123 | .Options; 124 | 125 | // Act 126 | using (IPersonRepository personRepository = new PersonRepository(new DataBaseContext(options))) 127 | { 128 | personRepository.Add(new Person() { Name = "John Doe" }); 129 | personRepository.Add(new Person() { Name = "Jane Doe" }); 130 | personRepository.Save(); 131 | var savedPerson = personRepository.GetSingle(x => x.Name == "John Doe"); 132 | personRepository.Delete(x => x.Id == savedPerson.Id); 133 | personRepository.Save(); 134 | } 135 | 136 | // Assert 137 | using (IPersonRepository personRepository = new PersonRepository(new DataBaseContext(options))) 138 | { 139 | var personCount = personRepository.Count(); 140 | Assert.AreEqual(1, personCount); 141 | } 142 | } 143 | 144 | [TestMethod] 145 | public void Include_Selects_Child_Items_From_Database() 146 | { 147 | // Arrange 148 | var options = new DbContextOptionsBuilder() 149 | .UseInMemoryDatabase(databaseName: nameof(Include_Selects_Child_Items_From_Database)) 150 | .Options; 151 | 152 | // Act 153 | using (IPersonRepository personRepository = new PersonRepository(new DataBaseContext(options))) 154 | { 155 | Person john = new Person() 156 | { 157 | Name = "John Doe", 158 | Things = new List() { 159 | new Thing() { Name = "Thing1"} } 160 | }; 161 | 162 | Person jane = new Person() 163 | { 164 | Name = "Jane Doe", 165 | Things = new List() { 166 | new Thing() { Name = "Thing2"} } 167 | }; 168 | 169 | personRepository.Add(john); 170 | personRepository.Add(jane); 171 | personRepository.Save(); 172 | } 173 | 174 | // Assert 175 | using (IPersonRepository personRepository = new PersonRepository(new DataBaseContext(options))) 176 | { 177 | var personCount = personRepository.Count(); 178 | Assert.AreEqual(2, personCount); 179 | 180 | var johnFromDb = personRepository 181 | .GetSingle(x => x.Name == "John Doe", 182 | source => source.Include(x => x.Things)); 183 | 184 | Assert.IsNotNull(johnFromDb); 185 | Assert.IsNotNull(johnFromDb.Things); 186 | Assert.AreEqual(1, johnFromDb.Things.Count); 187 | 188 | var janeFromDb = personRepository 189 | .GetSingle(x => x.Name == "Jane Doe", 190 | source => source.Include(x => x.Things)); 191 | 192 | Assert.IsNotNull(janeFromDb); 193 | Assert.IsNotNull(janeFromDb.Things); 194 | Assert.AreEqual(1, janeFromDb.Things.Count); 195 | } 196 | } 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore.Tests/DataBaseContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using OfferingSolutions.GenericEFCore.SampleApp.Models; 3 | 4 | namespace OfferingSolutions.GenericEFCore.Tests 5 | { 6 | public class DataBaseContext : DbContext 7 | { 8 | public DataBaseContext() 9 | { } 10 | 11 | public DataBaseContext(DbContextOptions options) 12 | : base(options) 13 | { } 14 | 15 | public DbSet Persons { get; set; } 16 | public DbSet Things { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore.Tests/ExampleRepositories/IPersonRepository.cs: -------------------------------------------------------------------------------- 1 | using OfferingSolutions.GenericEFCore.RepositoryContext; 2 | using OfferingSolutions.GenericEFCore.SampleApp.Models; 3 | 4 | namespace OfferingSolutions.GenericEFCore.Tests.ExampleRepositories 5 | { 6 | interface IPersonRepository : IGenericRepositoryContext 7 | { 8 | void MyNewFunction(int id); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore.Tests/ExampleRepositories/PersonRepository.cs: -------------------------------------------------------------------------------- 1 | using OfferingSolutions.GenericEFCore.RepositoryContext; 2 | using OfferingSolutions.GenericEFCore.SampleApp.Models; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace OfferingSolutions.GenericEFCore.Tests.ExampleRepositories 7 | { 8 | public class PersonRepository : GenericRepositoryContext, IPersonRepository 9 | { 10 | public PersonRepository(DataBaseContext dbContext) 11 | : base(dbContext) 12 | { 13 | 14 | } 15 | 16 | public void MyNewFunction(int id) 17 | { 18 | //Do Something 19 | } 20 | 21 | public new List GetAll() 22 | { 23 | return base.GetAll().ToList(); 24 | } 25 | 26 | public override void Add(Person toAdd) 27 | { 28 | MyAdditionalAddFunction(); 29 | base.Add(toAdd); 30 | } 31 | 32 | private void MyAdditionalAddFunction() 33 | { 34 | //Do something else... 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore.Tests/Models/Person.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace OfferingSolutions.GenericEFCore.SampleApp.Models 7 | { 8 | public class Person 9 | { 10 | public int Id { get; set; } 11 | public string Name { get; set; } 12 | public int Age { get; set; } 13 | public List Things { get; set; } 14 | 15 | public override string ToString() 16 | { 17 | return $"{Name} {Age}"; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore.Tests/Models/Thing.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace OfferingSolutions.GenericEFCore.SampleApp.Models 7 | { 8 | public class Thing 9 | { 10 | public int Id { get; set; } 11 | public string Name { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore.Tests/OfferingSolutions.GenericEFCore.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.0 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29215.179 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OfferingSolutions.GenericEFCore", "OfferingSolutions.GenericEFCore\OfferingSolutions.GenericEFCore.csproj", "{B111FA4A-8875-4B38-A272-9DFDA7C4D990}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OfferingSolutions.GenericEFCore.SampleApp", "OfferingSolutions.GenericEFCore.SampleApp\OfferingSolutions.GenericEFCore.SampleApp.csproj", "{314C8C42-8B4D-4303-B738-DBA7253A12C6}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OfferingSolutions.GenericEFCore.Tests", "OfferingSolutions.GenericEFCore.Tests\OfferingSolutions.GenericEFCore.Tests.csproj", "{3622BDD3-9A92-43B4-A655-1442E26E47ED}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {B111FA4A-8875-4B38-A272-9DFDA7C4D990}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {B111FA4A-8875-4B38-A272-9DFDA7C4D990}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {B111FA4A-8875-4B38-A272-9DFDA7C4D990}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {B111FA4A-8875-4B38-A272-9DFDA7C4D990}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {314C8C42-8B4D-4303-B738-DBA7253A12C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {314C8C42-8B4D-4303-B738-DBA7253A12C6}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {314C8C42-8B4D-4303-B738-DBA7253A12C6}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {314C8C42-8B4D-4303-B738-DBA7253A12C6}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {3622BDD3-9A92-43B4-A655-1442E26E47ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {3622BDD3-9A92-43B4-A655-1442E26E47ED}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {3622BDD3-9A92-43B4-A655-1442E26E47ED}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {3622BDD3-9A92-43B4-A655-1442E26E47ED}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {549DCE18-0407-4414-B522-31719C5C0546} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore/BaseContext/ContextBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Linq.Expressions; 4 | using System.Threading.Tasks; 5 | using Microsoft.EntityFrameworkCore; 6 | using Microsoft.EntityFrameworkCore.Query; 7 | using OfferingSolutions.GenericEFCore.UnitOfWork; 8 | 9 | namespace OfferingSolutions.GenericEFCore.BaseContext 10 | { 11 | public class ContextBase 12 | { 13 | private readonly IOsUnitOfWork _osUnitOfWork; 14 | 15 | public ContextBase(DbContext databaseContext) 16 | { 17 | _osUnitOfWork = new OsUnitOfWork(databaseContext); 18 | } 19 | 20 | public int Save() 21 | { 22 | return _osUnitOfWork.Save(); 23 | } 24 | 25 | public Task SaveASync() 26 | { 27 | return _osUnitOfWork.SaveAsync(); 28 | } 29 | 30 | public void Dispose() 31 | { 32 | _osUnitOfWork.Dispose(); 33 | } 34 | 35 | public int Count() where T : class 36 | { 37 | return _osUnitOfWork.GetRepository().Count(); 38 | } 39 | 40 | public int Count(Expression> predicate) where T : class 41 | { 42 | return _osUnitOfWork.GetRepository().Count(predicate); 43 | } 44 | 45 | public IQueryable GetAll() where T : class 46 | { 47 | return _osUnitOfWork.GetRepository().GetAll(null, null, null, null, null); 48 | } 49 | 50 | public IQueryable GetAll(Expression> predicate) where T : class 51 | { 52 | return _osUnitOfWork.GetRepository().GetAll(predicate, null, null, null, null); 53 | } 54 | 55 | public IQueryable GetAll(Expression> predicate = null, 56 | Func, IIncludableQueryable> include = null, 57 | Func, IOrderedQueryable> orderBy = null, 58 | int? skip = null, int? take = null) where T : class 59 | { 60 | return _osUnitOfWork.GetRepository().GetAll(predicate, include, orderBy, skip, take); 61 | } 62 | 63 | public IQueryable GetAll(Expression> predicate = null, 64 | Func, IIncludableQueryable> include = null, 65 | string orderBy = null, string orderDirection = "asc", 66 | int? skip = null, int? take = null) where T : class 67 | { 68 | return _osUnitOfWork.GetRepository().GetAll(predicate, include, orderBy, orderDirection, skip, take); 69 | } 70 | 71 | public Task> GetAllAsync(Expression> predicate = null, 72 | Func, IIncludableQueryable> include = null, 73 | Func, IOrderedQueryable> orderBy = null, 74 | int? skip = null, int? take = null) where T : class 75 | { 76 | return _osUnitOfWork.GetRepository().GetAllAsync(predicate, include, orderBy, skip, take); 77 | } 78 | 79 | public Task> GetAllAsync(Expression> predicate = null, 80 | Func, IIncludableQueryable> include = null, 81 | string orderBy = null, string orderDirection = "asc", 82 | int? skip = null, int? take = null) where T : class 83 | { 84 | return _osUnitOfWork.GetRepository().GetAllAsync(predicate, include, orderBy, orderDirection, skip, take); 85 | } 86 | 87 | public Task> GetAllAsync() where T : class 88 | { 89 | return _osUnitOfWork.GetRepository().GetAllAsync(null, null, null, null, null); 90 | } 91 | 92 | public Task> GetAllAsync(Expression> predicate) where T : class 93 | { 94 | return _osUnitOfWork.GetRepository().GetAllAsync(predicate, null, null, null, null); 95 | } 96 | 97 | public IQueryable GetAll(Func, IIncludableQueryable> include) where T : class 98 | { 99 | return _osUnitOfWork.GetRepository().GetAll(null, include, null, null, null); 100 | } 101 | 102 | public Task> GetAllAsync(Func, IIncludableQueryable> include) where T : class 103 | { 104 | return _osUnitOfWork.GetRepository().GetAllAsync(null, include, null, null, null); 105 | } 106 | 107 | public T GetSingle( 108 | Expression> predicate = null, 109 | Func, IIncludableQueryable> include = null) where T : class 110 | { 111 | return _osUnitOfWork.GetRepository().GetSingle(predicate, include); 112 | } 113 | 114 | public Task GetSingleAsync( 115 | Expression> predicate = null, 116 | Func, IIncludableQueryable> include = null) where T : class 117 | { 118 | return _osUnitOfWork.GetRepository().GetSingleAsync(predicate, include); 119 | } 120 | 121 | public virtual void Add(T entity) where T : class 122 | { 123 | _osUnitOfWork.GetRepository().Add(entity); 124 | } 125 | 126 | public virtual void AddAsync(T entity) where T : class 127 | { 128 | _osUnitOfWork.GetRepository().AddAsync(entity); 129 | } 130 | 131 | public T Update(T entity) where T : class 132 | { 133 | return _osUnitOfWork.GetRepository().Update(entity); 134 | } 135 | 136 | public void Delete(T toDelete) where T : class 137 | { 138 | _osUnitOfWork.GetRepository().Delete(toDelete); 139 | } 140 | 141 | public void Delete(Expression> predicate) where T : class 142 | { 143 | _osUnitOfWork.GetRepository().Delete(predicate); 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore/OfferingSolutions.GenericEFCore.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.1 5 | 1.3.2 6 | Fabian Gosebrink 7 | true 8 | false 9 | https://github.com/OfferingSolutions/Entity-Framework-Core-Generic-Repository 10 | https://github.com/OfferingSolutions/Entity-Framework-Core-Generic-Repository 11 | Generic Repository Entity Framework Core 12 | MIT 13 | Offering you a complete abstraction of the UnitOfWork-Pattern & Repository pattern with the basic CRUD-Operations, the Repository Pattern and extended functions like CustomRepositores all in one small lib. Made for the Entity Framework Core. 14 | 1.3.2.0 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore/RepositoryBase/GenericRepositoryBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Linq.Expressions; 4 | using System.Threading.Tasks; 5 | using Microsoft.EntityFrameworkCore; 6 | using Microsoft.EntityFrameworkCore.Query; 7 | using System.Linq.Dynamic.Core; 8 | 9 | namespace OfferingSolutions.GenericEFCore.RepositoryBase 10 | { 11 | internal class GenericRepositoryBase : IGenericRepositoryBase where T : class 12 | { 13 | private readonly DbContext _dataBaseContext; 14 | 15 | public GenericRepositoryBase(DbContext context) 16 | { 17 | _dataBaseContext = context; 18 | } 19 | 20 | public IQueryable GetAll() 21 | { 22 | return this.GetAll(null, null, null, null, null); 23 | } 24 | 25 | public IQueryable GetAll(Expression> predicate) 26 | { 27 | return this.GetAll(predicate, null, null, null, null); 28 | } 29 | 30 | public IQueryable GetAll(Func, IIncludableQueryable> include) 31 | { 32 | return this.GetAll(null, include, null, null, null); 33 | } 34 | 35 | public Task> GetAllAsync() 36 | { 37 | return this.GetAllAsync(null, null, null, null, null); 38 | } 39 | 40 | public Task> GetAllAsync(Expression> predicate) 41 | { 42 | return this.GetAllAsync(predicate, null, null, null, null); 43 | } 44 | 45 | public Task> GetAllAsync(Func, IIncludableQueryable> include) 46 | { 47 | return this.GetAllAsync(null, include, null, null, null); 48 | } 49 | 50 | public IQueryable GetAll(Expression> predicate = null, 51 | Func, IIncludableQueryable> include = null) 52 | { 53 | return GetQueryable(predicate, include); 54 | } 55 | 56 | public IQueryable GetAll(Expression> predicate = null, 57 | Func, IIncludableQueryable> include = null, 58 | Func, IOrderedQueryable> orderBy = null, 59 | int? skip = null, int? take = null) 60 | { 61 | IQueryable query = GetQueryable(predicate, include); 62 | 63 | if (orderBy != null) 64 | { 65 | query = orderBy(query); 66 | } 67 | 68 | if (skip != null && skip.HasValue) 69 | { 70 | query = query.Skip(skip.Value); 71 | } 72 | 73 | if (take != null && take.HasValue) 74 | { 75 | query = query.Take(take.Value); 76 | } 77 | 78 | return query; 79 | } 80 | 81 | public IQueryable GetAll(Expression> predicate = null, 82 | Func, IIncludableQueryable> include = null, 83 | string orderBy = null, string orderDirection = "asc", 84 | int? skip = null, int? take = null) 85 | { 86 | IQueryable query = GetQueryable(predicate, include); 87 | 88 | if (orderBy != null) 89 | { 90 | query = query.OrderBy(orderBy, orderDirection); 91 | } 92 | 93 | if (skip != null && skip.HasValue) 94 | { 95 | query = query.Skip(skip.Value); 96 | } 97 | 98 | if (take != null && take.HasValue) 99 | { 100 | query = query.Take(take.Value); 101 | } 102 | 103 | return query; 104 | } 105 | 106 | public Task> GetAllAsync(Expression> predicate = null, 107 | Func, IIncludableQueryable> include = null, 108 | Func, IOrderedQueryable> orderBy = null, 109 | int? skip = null, int? take = null) 110 | { 111 | IQueryable query = GetQueryable(predicate, include); 112 | 113 | if (orderBy != null) 114 | { 115 | query = orderBy(query); 116 | } 117 | 118 | if (skip != null && skip.HasValue) 119 | { 120 | query = query.Skip(skip.Value); 121 | } 122 | 123 | if (take != null && take.HasValue) 124 | { 125 | query = query.Take(take.Value); 126 | } 127 | 128 | return new Task>(() => query); 129 | } 130 | 131 | public Task> GetAllAsync(Expression> predicate = null, 132 | Func, IIncludableQueryable> include = null) 133 | { 134 | return new Task> (() => GetQueryable(predicate, include)); 135 | } 136 | 137 | public Task> GetAllAsync(Expression> predicate = null, 138 | Func, IIncludableQueryable> include = null, 139 | string orderBy = null, string orderDirection = "asc", 140 | int? skip = null, int? take = null) 141 | { 142 | IQueryable query = GetQueryable(predicate, include); 143 | 144 | if (orderBy != null) 145 | { 146 | query = query.OrderBy(orderBy, orderDirection); 147 | } 148 | 149 | if (skip != null && skip.HasValue) 150 | { 151 | query = query.Skip(skip.Value); 152 | } 153 | 154 | if (take != null && take.HasValue) 155 | { 156 | query = query.Take(take.Value); 157 | } 158 | 159 | return new Task>(() => query); 160 | } 161 | 162 | /// 163 | /// Returns a single instance of T but throws exception if none is found 164 | /// 165 | /// 166 | /// 167 | public T GetSingle( 168 | Expression> predicate = null, 169 | Func, IIncludableQueryable> include = null) 170 | { 171 | IQueryable query = GetQueryable(predicate, include); 172 | 173 | return query.FirstOrDefault(); 174 | } 175 | 176 | public Task GetSingleAsync( 177 | Expression> predicate = null, 178 | Func, IIncludableQueryable> include = null) 179 | { 180 | IQueryable query = GetQueryable(predicate, include); 181 | 182 | return query.FirstOrDefaultAsync(); 183 | } 184 | 185 | public virtual void Add(T entity) 186 | { 187 | _dataBaseContext.Set().Add(entity); 188 | } 189 | 190 | public virtual void AddAsync(T entity) 191 | { 192 | _dataBaseContext.Set().AddAsync(entity); 193 | } 194 | 195 | public T Update(T entity) 196 | { 197 | _dataBaseContext.Set().Update(entity); 198 | return entity; 199 | } 200 | 201 | public void Delete(Expression> predicate) 202 | { 203 | var entity = GetSingle(predicate: predicate); 204 | _dataBaseContext.Set().Remove(entity); 205 | } 206 | 207 | public void Delete(T entity) 208 | { 209 | _dataBaseContext.Set().Remove(entity); 210 | } 211 | 212 | public int Count() 213 | { 214 | return _dataBaseContext.Set().Count(); 215 | } 216 | 217 | public int Count(Expression> predicate) 218 | { 219 | return _dataBaseContext.Set().Count(predicate); 220 | } 221 | 222 | private IQueryable GetQueryable(Expression> predicate = null, Func, IIncludableQueryable> include = null) 223 | { 224 | IQueryable query = _dataBaseContext.Set(); 225 | 226 | if (include != null) 227 | { 228 | query = include(query); 229 | } 230 | 231 | if (predicate != null) 232 | { 233 | query = query.Where(predicate); 234 | } 235 | 236 | return query; 237 | } 238 | } 239 | } -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore/RepositoryBase/IGenericRepositoryBase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Query; 2 | using System; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Threading.Tasks; 6 | 7 | namespace OfferingSolutions.GenericEFCore.RepositoryBase 8 | { 9 | internal interface IGenericRepositoryBase where T : class 10 | { 11 | IQueryable GetAll(); 12 | IQueryable GetAll(Expression> predicate); 13 | IQueryable GetAll(Func, IIncludableQueryable> include); 14 | IQueryable GetAll(Expression> predicate, Func, IIncludableQueryable> include); 15 | IQueryable GetAll(Expression> predicate = null, 16 | Func, IIncludableQueryable> include = null, 17 | Func, IOrderedQueryable> orderBy = null, 18 | int? skip = null, int? take = null); 19 | 20 | IQueryable GetAll(Expression> predicate = null, 21 | Func, IIncludableQueryable> include = null, 22 | string orderBy = null, string orderDirection = "asc", 23 | int? skip = null, int? take = null); 24 | 25 | Task> GetAllAsync(); 26 | Task> GetAllAsync(Expression> predicate); 27 | Task> GetAllAsync(Func, IIncludableQueryable> include); 28 | Task> GetAllAsync(Expression> predicate, Func, IIncludableQueryable> include); 29 | 30 | Task> GetAllAsync(Expression> predicate = null, 31 | Func, IIncludableQueryable> include = null, 32 | Func, IOrderedQueryable> orderBy = null, 33 | int? skip = null, int? take = null); 34 | Task> GetAllAsync(Expression> predicate = null, 35 | Func, IIncludableQueryable> include = null, 36 | string orderBy = null, string orderDirection = "asc", 37 | int? skip = null, int? take = null); 38 | 39 | T GetSingle( 40 | Expression> predicate = null, 41 | Func, IIncludableQueryable> include = null); 42 | 43 | Task GetSingleAsync( 44 | Expression> predicate = null, 45 | Func, IIncludableQueryable> include = null); 46 | 47 | void Add(T toAdd); 48 | void AddAsync(T entity); 49 | T Update(T toUpdate); 50 | void Delete(T entity); 51 | void Delete(Expression> predicate); 52 | 53 | int Count(); 54 | int Count(Expression> predicate); 55 | } 56 | } -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore/RepositoryContext/GenericRepositoryContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Linq.Expressions; 4 | using System.Threading.Tasks; 5 | using Microsoft.EntityFrameworkCore; 6 | using Microsoft.EntityFrameworkCore.Query; 7 | using OfferingSolutions.GenericEFCore.BaseContext; 8 | 9 | namespace OfferingSolutions.GenericEFCore.RepositoryContext 10 | { 11 | public class GenericRepositoryContext : ContextBase, IGenericRepositoryContext where T : class 12 | { 13 | public GenericRepositoryContext(DbContext databaseContext) 14 | : base(databaseContext) 15 | { 16 | 17 | } 18 | 19 | public virtual IQueryable GetAll() 20 | { 21 | return base.GetAll(null, null, null, null, null); 22 | } 23 | 24 | public virtual IQueryable GetAll(Expression> predicate) 25 | { 26 | return base.GetAll(predicate, null, null, null, null); 27 | } 28 | 29 | public virtual IQueryable GetAll(Func, IIncludableQueryable> include) 30 | { 31 | return base.GetAll(include); 32 | } 33 | 34 | public virtual IQueryable GetAll(Expression> predicate, Func, IIncludableQueryable> include) 35 | { 36 | return base.GetAll(predicate, include, null, null, null); 37 | } 38 | 39 | public virtual IQueryable GetAll(Expression> predicate = null, 40 | Func, IIncludableQueryable> include = null, 41 | Func, IOrderedQueryable> orderBy = null, int? skip = null, int? take = null) 42 | { 43 | return base.GetAll(predicate, include, orderBy, skip, take); 44 | } 45 | public virtual IQueryable GetAll(Expression> predicate = null, 46 | Func, IIncludableQueryable> include = null, 47 | string orderBy = null, string orderDirection = "asc", 48 | int? skip = null, int? take = null) 49 | { 50 | return base.GetAll(predicate, include, orderBy, orderDirection, skip, take); 51 | } 52 | 53 | public virtual Task> GetAllAsync() 54 | { 55 | return base.GetAllAsync(null, null, null, null, null); 56 | } 57 | 58 | public virtual Task> GetAllAsync(Expression> predicate) 59 | { 60 | return base.GetAllAsync(predicate, null, null, null, null); 61 | } 62 | 63 | public virtual Task> GetAllAsync(Func, IIncludableQueryable> include) 64 | { 65 | return base.GetAllAsync(include); 66 | } 67 | 68 | public virtual Task> GetAllAsync(Expression> predicate, Func, IIncludableQueryable> include) 69 | { 70 | return base.GetAllAsync(predicate, include, null, null, null); 71 | } 72 | 73 | public virtual Task> GetAllAsync(Expression> predicate = null, 74 | Func, IIncludableQueryable> include = null, 75 | Func, IOrderedQueryable> orderBy = null, 76 | int? skip = null, int? take = null) 77 | { 78 | return base.GetAllAsync(predicate, include, orderBy, skip, take); 79 | } 80 | 81 | public virtual Task> GetAllAsync(Expression> predicate = null, 82 | Func, IIncludableQueryable> include = null, 83 | string orderBy = null, 84 | string orderDirection = "asc", int? skip = null, int? take = null) 85 | { 86 | return base.GetAllAsync(predicate, include, orderBy, orderDirection, skip, take); 87 | } 88 | 89 | public virtual T GetSingle(Expression> predicate = null, Func, IIncludableQueryable> include = null) 90 | { 91 | return base.GetSingle(predicate, include); 92 | } 93 | 94 | public virtual Task GetSingleAsync(Expression> predicate = null, Func, IIncludableQueryable> include = null) 95 | { 96 | return base.GetSingleAsync(predicate, include); 97 | } 98 | 99 | public virtual void Add(T entity) 100 | { 101 | base.Add(entity); 102 | } 103 | 104 | public virtual void AddAsync(T entity) 105 | { 106 | base.AddAsync(entity); 107 | } 108 | 109 | public virtual T Update(T toUpdate) 110 | { 111 | return base.Update(toUpdate); 112 | } 113 | 114 | public virtual void Delete(T entity) 115 | { 116 | base.Delete(entity); 117 | } 118 | 119 | public virtual void Delete(Expression> predicate) 120 | { 121 | base.Delete(predicate); 122 | } 123 | 124 | public virtual int Count() 125 | { 126 | return base.Count(); 127 | } 128 | 129 | public virtual int Count(Expression> predicate) 130 | { 131 | return base.Count(predicate); 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore/RepositoryContext/IGenericRepositoryContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Query; 2 | using System; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Threading.Tasks; 6 | 7 | namespace OfferingSolutions.GenericEFCore.RepositoryContext 8 | { 9 | public interface IGenericRepositoryContext : IDisposable where T : class 10 | { 11 | IQueryable GetAll(); 12 | IQueryable GetAll(Expression> predicate); 13 | IQueryable GetAll(Func, IIncludableQueryable> include); 14 | IQueryable GetAll(Expression> predicate, Func, IIncludableQueryable> include); 15 | IQueryable GetAll(Expression> predicate = null, 16 | Func, IIncludableQueryable> include = null, 17 | Func, IOrderedQueryable> orderBy = null, 18 | int? skip = null, int? take = null); 19 | 20 | IQueryable GetAll(Expression> predicate = null, 21 | Func, IIncludableQueryable> include = null, 22 | string orderBy = null, string orderDirection = "asc", 23 | int? skip = null, int? take = null); 24 | 25 | Task> GetAllAsync(); 26 | Task> GetAllAsync(Expression> predicate); 27 | Task> GetAllAsync(Func, IIncludableQueryable> include); 28 | Task> GetAllAsync(Expression> predicate, Func, IIncludableQueryable> include); 29 | 30 | Task> GetAllAsync(Expression> predicate = null, 31 | Func, IIncludableQueryable> include = null, 32 | Func, IOrderedQueryable> orderBy = null, 33 | int? skip = null, int? take = null); 34 | Task> GetAllAsync(Expression> predicate = null, 35 | Func, IIncludableQueryable> include = null, 36 | string orderBy = null, string orderDirection = "asc", 37 | int? skip = null, int? take = null); 38 | 39 | T GetSingle( 40 | Expression> predicate = null, 41 | Func, IIncludableQueryable> include = null); 42 | 43 | Task GetSingleAsync( 44 | Expression> predicate = null, 45 | Func, IIncludableQueryable> include = null); 46 | 47 | void Add(T toAdd); 48 | void AddAsync(T entity); 49 | T Update(T toUpdate); 50 | void Delete(T entity); 51 | void Delete(Expression> predicate); 52 | 53 | int Count(); 54 | int Count(Expression> predicate); 55 | 56 | int Save(); 57 | 58 | Task SaveASync(); 59 | } 60 | } -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore/Services/Factory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.EntityFrameworkCore; 4 | using OfferingSolutions.GenericEFCore.RepositoryBase; 5 | 6 | namespace OfferingSolutions.GenericEFCore.Services 7 | { 8 | internal class Factory 9 | { 10 | private readonly IDictionary> _factoryCache; 11 | 12 | public Factory() 13 | { 14 | _factoryCache = new Dictionary>(); 15 | } 16 | 17 | public Func GetRepositoryFactoryForEntityType() 18 | where T : class 19 | { 20 | Func factory = GetRepositoryFactoryFromCache(); 21 | if (factory != null) 22 | { 23 | return factory; 24 | } 25 | 26 | return DefaultEntityRepositoryFactory(); 27 | } 28 | 29 | public Func GetRepositoryFactoryFromCache() 30 | { 31 | Func factory; 32 | _factoryCache.TryGetValue(typeof(T), out factory); 33 | return factory; 34 | } 35 | 36 | private Func DefaultEntityRepositoryFactory() where T : class 37 | { 38 | return dbContext => new GenericRepositoryBase(dbContext); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore/Services/IRepositoryService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore; 3 | using OfferingSolutions.GenericEFCore.RepositoryBase; 4 | 5 | namespace OfferingSolutions.GenericEFCore.Services 6 | { 7 | internal interface IRepositoryService 8 | { 9 | DbContext DbContext { get; set; } 10 | 11 | IGenericRepositoryBase GetGenericRepository() where T : class; 12 | 13 | T GetCustomRepository(Func factory = null) where T : class; 14 | } 15 | } -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore/Services/RepositoryServiceImpl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.EntityFrameworkCore; 4 | using OfferingSolutions.GenericEFCore.RepositoryBase; 5 | 6 | namespace OfferingSolutions.GenericEFCore.Services 7 | { 8 | internal class RepositoryServiceImpl : IRepositoryService 9 | { 10 | public DbContext DbContext { get; set; } 11 | 12 | private readonly Factory _factory; 13 | protected Dictionary Repositories { get; private set; } 14 | 15 | public RepositoryServiceImpl() 16 | { 17 | _factory = new Factory(); 18 | Repositories = new Dictionary(); 19 | } 20 | 21 | public IGenericRepositoryBase GetGenericRepository() where T : class 22 | { 23 | Func repositoryFactoryForEntityTypeDelegate = _factory.GetRepositoryFactoryForEntityType(); 24 | return GetCustomRepository>(repositoryFactoryForEntityTypeDelegate); 25 | } 26 | 27 | public virtual T GetCustomRepository(Func factory = null) where T : class 28 | { 29 | object repository; 30 | Repositories.TryGetValue(typeof(T), out repository); 31 | if (repository != null) 32 | { 33 | return (T)repository; 34 | } 35 | return CreateRepository(factory, DbContext); 36 | } 37 | 38 | private T CreateRepository(Func factory, DbContext dbContext) 39 | { 40 | Func repositoryFactory; 41 | if (factory != null) 42 | { 43 | repositoryFactory = factory; 44 | } 45 | else 46 | { 47 | repositoryFactory = _factory.GetRepositoryFactoryFromCache(); 48 | } 49 | if (repositoryFactory == null) 50 | { 51 | throw new NotSupportedException(typeof(T).FullName); 52 | } 53 | T repository = (T)repositoryFactory(dbContext); 54 | Repositories[typeof(T)] = repository; 55 | return repository; 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore/UnitOfWork/IOsUnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using OfferingSolutions.GenericEFCore.RepositoryBase; 4 | 5 | namespace OfferingSolutions.GenericEFCore.UnitOfWork 6 | { 7 | internal interface IOsUnitOfWork : IDisposable 8 | { 9 | IGenericRepositoryBase GetRepository() where T : class; 10 | 11 | int Save(); 12 | 13 | Task SaveAsync(); 14 | } 15 | } -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore/UnitOfWork/OsUnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Microsoft.EntityFrameworkCore; 4 | using OfferingSolutions.GenericEFCore.RepositoryBase; 5 | using OfferingSolutions.GenericEFCore.Services; 6 | 7 | namespace OfferingSolutions.GenericEFCore.UnitOfWork 8 | { 9 | internal class OsUnitOfWork : IOsUnitOfWork 10 | { 11 | private readonly DbContext _dbContext; 12 | private readonly IRepositoryService _repositoryService; 13 | 14 | public OsUnitOfWork(DbContext dbContext) 15 | { 16 | _dbContext = dbContext; 17 | 18 | if (_repositoryService == null) 19 | { 20 | _repositoryService = new RepositoryServiceImpl(); 21 | } 22 | 23 | _repositoryService.DbContext = _dbContext; 24 | } 25 | 26 | int IOsUnitOfWork.Save() 27 | { 28 | return _dbContext.SaveChanges(); 29 | } 30 | 31 | Task IOsUnitOfWork.SaveAsync() 32 | { 33 | return _dbContext.SaveChangesAsync(); 34 | } 35 | 36 | void IDisposable.Dispose() 37 | { 38 | _dbContext.Dispose(); 39 | } 40 | 41 | IGenericRepositoryBase IOsUnitOfWork.GetRepository() 42 | { 43 | return _repositoryService.GetGenericRepository(); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore/UnitOfWorkContext/IOsUnitOfWorkContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Query; 2 | using System; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Threading.Tasks; 6 | 7 | namespace OfferingSolutions.GenericEFCore.UnitOfWorkContext 8 | { 9 | public interface IOsUnitOfWorkContext : IDisposable 10 | { 11 | void Add(T entity) where T : class; 12 | void AddAsync(T entity) where T : class; 13 | int Count() where T : class; 14 | int Count(Expression> predicate) where T : class; 15 | void Delete(Expression> predicate) where T : class; 16 | void Delete(T toDelete) where T : class; 17 | 18 | IQueryable GetAll() where T : class; 19 | IQueryable GetAll(Expression> predicate) where T : class; 20 | IQueryable GetAll(Func, IIncludableQueryable> include) where T : class; 21 | 22 | IQueryable GetAll( 23 | Expression> predicate = null, 24 | Func, IIncludableQueryable> include = null, 25 | Func, IOrderedQueryable> orderBy = null, 26 | int? skip = null, int? take = null) where T : class; 27 | 28 | IQueryable GetAll( 29 | Expression> predicate = null, 30 | Func, IIncludableQueryable> include = null, 31 | string orderBy = null, 32 | string orderDirection = "asc", 33 | int? skip = null, int? take = null) where T : class; 34 | 35 | Task> GetAllAsync( 36 | Expression> predicate = null, 37 | Func, IIncludableQueryable> include = null, 38 | Func, IOrderedQueryable> orderBy = null, 39 | int? skip = null, int? take = null) where T : class; 40 | 41 | Task> GetAllAsync( 42 | Expression> predicate = null, 43 | Func, IIncludableQueryable> include = null, 44 | string orderBy = null, 45 | string orderDirection = "asc", 46 | int? skip = null, int? take = null) where T : class; 47 | 48 | Task> GetAllAsync() where T : class; 49 | Task> GetAllAsync(Expression> predicate) where T : class; 50 | Task> GetAllAsync(Func, IIncludableQueryable> include) where T : class; 51 | 52 | T GetSingle(Expression> predicate = null, Func, IIncludableQueryable> include = null) where T : class; 53 | Task GetSingleAsync(Expression> predicate = null, Func, IIncludableQueryable> include = null) where T : class; 54 | int Save(); 55 | Task SaveASync(); 56 | T Update(T entity) where T : class; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /OfferingSolutions.GenericEFCore/UnitOfWorkContext/OsUnitOfWorkContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using OfferingSolutions.GenericEFCore.BaseContext; 3 | 4 | namespace OfferingSolutions.GenericEFCore.UnitOfWorkContext 5 | { 6 | public class OsUnitOfWorkContext : ContextBase, IOsUnitOfWorkContext 7 | { 8 | public OsUnitOfWorkContext(DbContext databaseContext) 9 | : base(databaseContext) 10 | { 11 | 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Generic Repository Pattern (ASP.NET Core) 2 | 3 | ![NuGet](https://img.shields.io/nuget/v/OfferingSolutions.GenericEFCore) 4 | ![Downloads](https://img.shields.io/nuget/dt/OfferingSolutions.GenericEFCore) 5 | 6 | Offering you a complete abstraction of the UnitOfWork-Pattern & Repository pattern with the basic CRUD-Operations, the Repository Pattern and extended functions like CustomRepositores all in one small lib. Made for the Entity Framework Core. 7 | 8 | See the Sample-Project how this works. 9 | 10 | ## Installation 11 | 12 | See Nuget to load this package: 13 | [Nuget](https://www.nuget.org/packages/OfferingSolutions.GenericEFCore) 14 | 15 | ``` 16 | Install-Package OfferingSolutions.GenericEFCore 17 | ``` 18 | 19 | ``` 20 | dotnet add package OfferingSolutions.GenericEFCore 21 | ``` 22 | 23 | Have fun. Hope this helps :) 24 | 25 | ## Usage 26 | 27 | ### Example for Generic Repositories 28 | 29 | ```c# 30 | interface IPersonRepository : IGenericRepositoryContext 31 | { 32 | 33 | } 34 | ``` 35 | 36 | ```c# 37 | public class PersonRepository : GenericRepositoryContext, IPersonRepository 38 | { 39 | public PersonRepository(DataBaseContext dbContext) 40 | : base(dbContext) 41 | { 42 | 43 | } 44 | } 45 | ``` 46 | 47 | Or you can add and overwrite methods 48 | 49 | ```c# 50 | interface IPersonRepository : IGenericRepositoryContext 51 | { 52 | void MyNewFunction(int id); 53 | 54 | void Add(Person toAdd); 55 | } 56 | ``` 57 | 58 | ```c# 59 | public class PersonRepository : GenericRepositoryContext, IPersonRepository 60 | { 61 | public PersonRepository(DataBaseContext dbContext) 62 | : base(dbContext) 63 | { 64 | 65 | } 66 | 67 | public void MyNewFunction(int id) 68 | { 69 | //Do Something 70 | } 71 | 72 | public override void Add(Person toAdd) 73 | { 74 | MyAdditionalAddFunction(); 75 | base.Add(toAdd); 76 | } 77 | 78 | private void MyAdditionalAddFunction() 79 | { 80 | //Do something else... 81 | } 82 | } 83 | ``` 84 | 85 | ```c# 86 | using (IPersonRepository personRepository = new PersonRepository(new DataBaseContext())) 87 | { 88 | personRepository.Add(new Person() { Name = "John Doe" }); 89 | personRepository.Save(); 90 | var receivedPerson = personRepository.GetSingle(x => x.Name == "John Doe"); 91 | Console.WriteLine(receivedPerson); 92 | 93 | // Does something good ... 94 | personRepository.MyNewFunction(6); 95 | } 96 | ``` 97 | 98 | ## Methods 99 | 100 | ### Get all entities 101 | 102 | ``` 103 | IQueryable GetAll(); 104 | Task> GetAllAsync() 105 | ``` 106 | 107 | Example: `personRepository.GetAll();` 108 | 109 | ### Gets all entities with predicate 110 | 111 | ``` 112 | IQueryable GetAll([predicate]) 113 | Task> GetAllAsync([predicate]) 114 | ``` 115 | 116 | Example: `personRepository.GetAll(x => x.Name == "John Doe");` 117 | 118 | ### Gets all entities and includes child entities 119 | 120 | ``` 121 | IQueryable GetAll([include]) 122 | Task> GetAllAsync([include]) 123 | ``` 124 | 125 | Example: `personRepository.GetAll(source => source.Include(y => y.Things));` 126 | 127 | ### Gets all entities with predicate and includes a child entity 128 | 129 | ``` 130 | IQueryable GetAll([predicate],[include]) 131 | Task> GetAllAsync([predicate],[include]) 132 | ``` 133 | 134 | Example: `personRepository.GetAll(x => x.Name == "John Doe", source => source.Include(y => y.Things));` 135 | 136 | ### Gets all entities with predicate, includes, orderby, skip & take; all nullable (orderby as lambda) 137 | 138 | ``` 139 | IQueryable GetAll([predicate],[include],[orderBy],[skip],[take]) 140 | Task> GetAllAsync([predicate],[include],[orderBy],[skip],[take]) 141 | ``` 142 | 143 | Example: `personRepository.GetAll(predicate: x => x.Name == "John Doe", source => source.Include(y => y.Things), orderBy: q => q.OrderBy(d => d.Name));` 144 | 145 | ### Gets all entities with predicate, includes, orderby (string), orderDirection (string), skip & take; all nullable 146 | 147 | ``` 148 | IQueryable GetAll([predicate],[include],[orderBy],[orderDirection],[skip],[take]) 149 | Task> GetAllAsync([predicate],[include],[orderBy],[orderDirection],[skip],[take]) 150 | ``` 151 | 152 | Example: `personRepository.GetAll(predicate: x => x.Name == "John Doe", source => source.Include(y => y.Things), orderBy: "Name", "asc", 5, 5);` 153 | 154 | ### Gets single entity with predicate and include; all nullable 155 | 156 | ``` 157 | T GetSingle([predicate],[include]); 158 | Task GetSingleAsync([predicate],[include]) 159 | ``` 160 | 161 | Example: `personRepository.GetSingle(x => x.Name == "John Doe");` or `personRepository.GetSingle(x => x.Name == "John Doe", source => source.Include(y => y.Things));` 162 | 163 | ### Adding an entity 164 | 165 | ``` 166 | void Add([entity]); 167 | void AddAsync([entity]) 168 | ``` 169 | 170 | Example: `personRepository.Add(new Person() { Name = "John Doe" });` 171 | 172 | ### Updating an entity 173 | 174 | ``` 175 | T Update([entity]) 176 | ``` 177 | 178 | Example: `personRepository.Update(changedPerson);` 179 | 180 | ### Deleting an entity 181 | 182 | ``` 183 | void Delete([entity]); 184 | void Delete([predicate]); 185 | ``` 186 | 187 | Example: `personRepository.Delete(toDelete);` or `personRepository.Delete(x => x.Id == id);` 188 | 189 | ### Count entities 190 | 191 | ``` 192 | int Count(); 193 | int Count([predicate]); 194 | ``` 195 | 196 | Example: `personRepository.Count();` or `personRepository.Count(x => x.Name == "John Doe");` 197 | 198 | ### Saving entities 199 | 200 | ``` 201 | int Save() 202 | Task SaveAsync() 203 | ``` 204 | 205 | Example: `personRepository.Save();` 206 | 207 | ## Complete Unit of Work 208 | 209 | ### Example for complete Unit of Work 210 | 211 | ```c# 212 | using (IOsUnitOfWorkContext unitOfWorkContext = new OsUnitOfWorkContext(new DataBaseContext())) 213 | { 214 | Person person = new Person() 215 | { 216 | Age = 35, 217 | Name = "Fabian", 218 | Things = new List() { 219 | new Thing() 220 | { 221 | Name = "A Thing" 222 | } 223 | } 224 | }; 225 | 226 | // Adding a new Entity, for example "Person" 227 | unitOfWorkContext.Add(person); 228 | 229 | // Savechanges 230 | unitOfWorkContext.Save(); 231 | 232 | unitOfWorkContext.SaveAsync(); 233 | 234 | // Get all Persons 235 | var persons = unitOfWorkContext.GetAll().ToList(); 236 | var personsAsync = unitOfWorkContext.GetAllAsync(); 237 | 238 | foreach (var item in persons) 239 | { 240 | Console.WriteLine(item.Name + " " + item.Age); 241 | } 242 | 243 | List allPersonsOnAge35 = unitOfWorkContext.GetAll(x => x.Age == 35).ToList(); 244 | 245 | Console.WriteLine(allPersonsOnAge35.Count); 246 | 247 | // Get all Persons with the age of 35 ordered by Name 248 | List allPersonsOnAge35Ordered = unitOfWorkContext.GetAll(x => x.Age == 35, orderBy: q => q.OrderBy(d => d.Name)).ToList(); 249 | 250 | // Get all Persons with the age of 35 ordered by Name and include its properties 251 | Func, IIncludableQueryable> include = source => source.Include(y => y.Things); 252 | 253 | List allPersonsOnAge35OrderedAndWithThings = unitOfWorkContext.GetAll( 254 | x => x.Age == 35, 255 | orderBy: q => q.OrderBy(d => d.Name), 256 | include: include) 257 | .ToList(); 258 | 259 | // Get all Persons and include its properties 260 | List allPersonsWithThings = unitOfWorkContext.GetAll(include: include).ToList(); 261 | 262 | // Find a single Person with a specific name, is null if not found 263 | Person findBy = unitOfWorkContext.GetSingle(x => x.Id == 6); 264 | var findByASync = unitOfWorkContext.GetSingleAsync(x => x.Id == 6); 265 | 266 | // Find a single Person with a specific name and include its siblings 267 | Person findByWithThings = unitOfWorkContext.GetSingle(x => x.Name == "Fabian", include: include); 268 | 269 | // Find a person by id but throws exception if not found 270 | // var personWithIdMayThrowException = unitOfWorkContext.GetSingleBy(x => x.Id == 6); 271 | // var personWithIdMayThrowExceptionASync = unitOfWorkContext.GetSingleByASync(x => x.Id == 6); 272 | 273 | // Update an existing person 274 | Person findOneToUpdate = unitOfWorkContext.GetSingle(x => x.Name == "Fabian"); 275 | findOneToUpdate.Name = "Fabian2"; 276 | 277 | unitOfWorkContext.Update(person); 278 | unitOfWorkContext.Save(); 279 | 280 | Person findOneAfterUpdate = unitOfWorkContext.GetSingle(x => x.Name == "Fabian2"); 281 | 282 | // Deleting a Person by Id or by entity 283 | unitOfWorkContext.Delete(person); 284 | } 285 | ``` 286 | -------------------------------------------------------------------------------- /azure-builds/build.yml: -------------------------------------------------------------------------------- 1 | # ASP.NET Core 2 | # Build and test ASP.NET Core projects targeting .NET Core. 3 | # Add steps that run tests, create a NuGet package, deploy, and more: 4 | # https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core 5 | 6 | trigger: 7 | - release 8 | - master 9 | 10 | pool: 11 | vmImage: 'ubuntu-latest' 12 | 13 | # name: '$(majorMinorVersion).$(semanticVersion).$(Rev:.r)' 14 | 15 | variables: 16 | buildConfiguration: 'Release' 17 | projectName: 'OfferingSolutions.GenericEFCore' 18 | 19 | steps: 20 | - task: DotNetCoreInstaller@1 21 | inputs: 22 | version: '3.0.100' # replace this value with the version that you need for your project 23 | 24 | - script: echo %Action%%BuildVersion% 25 | displayName: 'Set build version' 26 | env: 27 | Action: '##vso[build.updatebuildnumber]' 28 | BuildVersion: $(GitVersion.SemVer) 29 | 30 | - task: DotNetCoreCLI@2 31 | displayName: Restore 32 | inputs: 33 | command: 'restore' 34 | feedsToUse: 'select' 35 | vstsFeed: '3f1a8a64-d40c-4a93-be38-2a07bc7e5e44' 36 | 37 | - task: DotNetCoreCLI@2 38 | displayName: Build 39 | inputs: 40 | command: build 41 | projects: '**/*.csproj' 42 | arguments: '--configuration $(buildConfiguration)' 43 | 44 | - task: DotNetCoreCLI@2 45 | displayName: Test 46 | inputs: 47 | command: test 48 | projects: '**/*Tests/*.csproj' 49 | arguments: '--configuration $(buildConfiguration) --collect "Code coverage"' 50 | 51 | - task: DotNetCoreCLI@2 52 | displayName: 'NuGet pack' 53 | inputs: 54 | command: 'pack' 55 | configuration: $(BuildConfiguration) 56 | packagesToPack: '**/$(ProjectName).csproj' 57 | 58 | - task: NuGetCommand@2 59 | displayName: Publish to nuget.org 60 | condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/release')) 61 | inputs: 62 | command: 'push' 63 | packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/**/*.symbols.nupkg' 64 | nuGetFeedType: 'external' 65 | publishFeedCredentials: 'ExternalNugetServer' 66 | 67 | - task: PublishBuildArtifacts@1 68 | displayName: Publish Build Artifact 69 | inputs: 70 | PathtoPublish: '$(Build.ArtifactStagingDirectory)' 71 | ArtifactName: 'drop' 72 | publishLocation: 'Container' --------------------------------------------------------------------------------