{"id":27063616,"url":"https://github.com/digipolisantwerp/dataaccess_aspnetcore","last_synced_at":"2025-04-05T16:01:49.782Z","repository":{"id":46371182,"uuid":"48684189","full_name":"digipolisantwerp/dataaccess_aspnetcore_deprecated","owner":"digipolisantwerp","description":"Generic repository/unit of work framework for ASP.NET Core with Entity Framework.","archived":false,"fork":false,"pushed_at":"2019-09-25T14:24:42.000Z","size":654,"stargazers_count":140,"open_issues_count":12,"forks_count":44,"subscribers_count":30,"default_branch":"master","last_synced_at":"2025-04-03T19:12:37.553Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/digipolisantwerp.png","metadata":{"files":{"readme":"readme.md","changelog":"changelog.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-12-28T09:10:41.000Z","updated_at":"2024-05-30T02:17:39.000Z","dependencies_parsed_at":"2022-09-22T09:10:26.291Z","dependency_job_id":null,"html_url":"https://github.com/digipolisantwerp/dataaccess_aspnetcore_deprecated","commit_stats":null,"previous_names":["digipolisantwerp/dataaccess_aspnetcore"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digipolisantwerp%2Fdataaccess_aspnetcore_deprecated","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digipolisantwerp%2Fdataaccess_aspnetcore_deprecated/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digipolisantwerp%2Fdataaccess_aspnetcore_deprecated/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digipolisantwerp%2Fdataaccess_aspnetcore_deprecated/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/digipolisantwerp","download_url":"https://codeload.github.com/digipolisantwerp/dataaccess_aspnetcore_deprecated/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247361593,"owners_count":20926641,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-04-05T16:01:36.500Z","updated_at":"2025-04-05T16:01:49.749Z","avatar_url":"https://github.com/digipolisantwerp.png","language":"C#","funding_links":[],"categories":["框架, 库和工具","Frameworks, Libraries and Tools"],"sub_categories":["应用程序框架","Application Frameworks"],"readme":"# DataAccess Toolbox\n\nThe DataAccess Toolbox contains the base classes for data access in ASP.NET Core with Entity Framework Core 1.0 using the unit-of-work and repository pattern.\n\nIt contains :\n- base classes for entities.\n- base classes for repositories.\n- generic repositories.\n- unit-of-work and repository pattern.\n(- automatic discovery of repositories -- not yet)\n\n\n## Table of Contents\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\n\n- [Installation](#installation)\n- [Configuration in Startup.ConfigureServices](#configuration-in-startupconfigureservices)\n  - [NpgSql](#npgsql)\n- [EntityContext](#entitycontext)\n- [ModelBuilder extensions](#modelbuilder-extensions)\n  - [Set all table- and field-names to lowercase](#set-all-table--and-field-names-to-lowercase)\n  - [Disable cascading deletes](#disable-cascading-deletes)\n- [Entities](#entities)\n- [UnitOfWork](#unitofwork)\n- [Repositories](#repositories)\n  - [Get and GetAsync](#get-and-getasync)\n  - [GetAll and GetAllAsync](#getall-and-getallasync)\n  - [Any and AnyAsync](#any-and-anyasync)\n  - [Add](#add)\n  - [Update](#update)\n  - [Remove](#remove)\n  - [Custom Repositories](#custom-repositories)\n- [Query](#query)\n  - [Filter](#filter)\n  - [Includes](#includes)\n  - [OrderBy](#orderby)\n- [Paging](#paging)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n## Installation\n\nAdding the DataAccess Toolbox to a project is as easy as adding it to the csproj project file:\n\n```xml\n  \u003cItemGroup\u003e\n    \u003cPackageReference Include=\"Digipolis.DataAccess\" Version=\"4.0.0\" /\u003e\n  \u003c/ItemGroup\u003e\n``` \n\nor if your project still works with project.json :\n\n\n``` json\n \"dependencies\": {\n    \"Digipolis.DataAccess\":  \"4.0.0\"\n }\n```\n\n**For netcoreapp2.0-projects a package version \u003e= 4.0.0 must be used.\nFor netcoreapp1.x-projects use a package version \u003c 4.0.0. A separate branch (netstandard_1_6) has been created to apply changes for the older version if necessary.**\n\nMake sure you have our Nuget feed configured (https://www.myget.org/F/digipolisantwerp/api/v3/index.json.).\n\nAlternatively, it can also be added via the NuGet Package Manager interface.\n\n## Configuration in Startup.ConfigureServices\n\nThe DataAccess framework is registered in the _**ConfigureServices**_ method of the *Startup* class.\n\n\n``` csharp\nservices.AddDataAccess\u003cMyEntityContext\u003e();\n```\n\nNext to this registration you will need to register entity framework separately.\n\n### NpgSql\n\nIf you use NpgSql, you can for example use this entity framework configuration:\n\n``` csharp\nvar connection = @\"Server=127.0.0.1;Port=5432;Database=TestDB;User Id=postgres;Password=mypwd;\";\nservices.AddDbContext\u003cMyEntityContext\u003e(options =\u003e options.UseNpgsql(connection));\n```\n\nCheck the [Entity Framework documentation](https://ef.readthedocs.io/en/latest/) for more info on the configuration possibilities.\n\n\n## EntityContext\n\nYou inherit a DbContext object from the EntityContextBase class in the toolbox. This context contains all your project-specific DbSets and custom logic.\nThe constructor has to accept an DbContextOptions\u0026lt;TContext\u0026gt; as input parameter, to be passed to the base constructor and where TContext is the type of your context.\nThe EntityContextBase is a generic type with your context as type parameter. This is necessary in order to pass the generic DbContextOptions object to the underlying DbContext constructor.\n\nFor example :\n\n``` csharp\npublic class EntityContext : EntityContextBase\u003cEntityContext\u003e\n{\n    public EntityContext(DbContextOptions\u003cEntityContext\u003e options) : base(options)\n    { }\n\n    public DbSet\u003cMyEntity\u003e\n    MyEntities { get; set; }\n    public DbSet\u003cMyOtherEntity\u003e\n    MyOtherEntities { get; set; }\n\n    protected override void OnModelCreating(DbModelBuilder modelBuilder)\n    {\n        // optional, see Entity Framework documentation\n    }\n}\n```\n\n## ModelBuilder extensions\n\nSometimes you want more control over the way the database structure is layed out (e.g. you are bound by rules set by the database administrators), other times you might already have a database in place and you can't change the structure. \nThe EF ModelBuilder allows you to control the mapping of the CLR types to the database schema. The following extensions give you extra possibilities that are not included in the standard Entity Framework libraries.\n\n### Set all table- and field-names to lowercase \n\n```csharp\nprotected override void OnModelCreating(ModelBuilder modelBuilder)\n{\n    base.OnModelCreating(modelBuilder);\n\n    modelBuilder.LowerCaseTablesAndFields();\n}\n```  \n\n### Disable cascading deletes\n\n```csharp\nprotected override void OnModelCreating(ModelBuilder modelBuilder)\n{\n    base.OnModelCreating(modelBuilder);\n\n    modelBuilder.DisableCascadingDeletes();\n}\n```  \n\n## Entities\n\nYour Entities are inherited from the base class EntityBase in the toolbox :\n\n``` csharp\npublic class MyEntity : EntityBase\n{\n    public string MyProperty { get; set; }\n}\n```\n\nThe EntityBase class already contains an int property, named Id that can be used as primary key.\n\n## UnitOfWork\n\nThe toolbox contains a UnitOfWork class and IUnitofWork interface that encapsulates the DbContext and that you use in your business classes to separate the data access code from business code.\nThe IUnitOfWork is instantiated by the IUowProvider.\n\nFirst inject the IUowProvider in your business class :\n\n``` csharp\npublic class BusinessClass\n{\n    public BusinessClass(IUowProvider uowProvider)\n    {\n        _uowProvider = uowProvider;\n    }\n\n    private readonly IUowProvider _uowProvider;\n}\n```\n\nThen ask the IUowProvider for a IUnitOfWork :\n\n``` csharp\nusing ( var uow = _uowProvider.CreateUnitOfWork() )\n{\n    // your business logic that needs dataaccess comes here\n}\n```\n\nYou can pass in false if you don't want the **change tracking** to activate (better performance when you only want to retrieve data and not insert/update/delete).\n\nNow access your data via repositories :\n\n``` csharp\nvar repository = uow.GetRepository\u003cMyEntity\u003e();\n// your data access code via the repository comes here\n```\n\nThe UnitOfWork will be automatically injected in the repository and used to interact with the database.\n\nTo persist your changes to the database, call the SaveChanges or SaveChangesAsync method of the IUnitOfWork :\n\n``` csharp\nuow.SaveChanges();\n```\n\n## Repositories\n\nThe toolbox registers generic repositories in the ASP.NET Core DI container. They provide the following methods :\n\n### Get and GetAsync\n\nRetrieve a single record by id, optionally passing in an IncludeList of child entities that you also want retrieved :\n\n``` csharp\nusing (var uow = _uowProvider.CreateUnitOfWork())\n{\n    var repository = uow.GetRepository\u003cMyEntity\u003e();\n\n    // retrieve MyEntity with id = 5\n    var entity = repository.Get(5);\n\n    // retrieve MyEntity with id 12 and its child object\n    var includeList = new IncludeList\u003cMyEntity\u003e(e =\u003e e.Child);\n    var entity2 = repository.Get(12, includes: includeList);\n}\n```\n\n### GetAll and GetAllAsync\n\nRetrieves all records, with or without child records.\n\n``` csharp\nusing (var uow = _uowProvider.CreateUnitOfWork(false))\n{\n    var repository = uow.GetRepository\u003cMyEntity\u003e();\n    var entities = repository.GetAll(includes: includes);\n}\n```\n\n### Any and AnyAsync\n\nChecks if at least one record exists with the provided filter.\n\n``` csharp\nusing (var uow = _uowProvider.CreateUnitOfWork(false))\n{\n    var repository = uow.GetRepository\u003cMyEntity\u003e();\n    bool exists = repository.Any(filter: filter);\n}\n```\n\n### Add\n\nAdds a record to the repository. The record is persisted to the database when calling IUnitOfWork.SaveChanges().\n\n``` csharp\nusing (var uow = _uowProvider.CreateUnitOfWork())\n{\n    var repository = uow.GetRepository\u003cMyEntity\u003e();\n    repository.Add(newEntity);\n    uow.SaveChanges();\n}\n```\n\n### Update\n\nUpdates an existing record.\n\nImportant note! When you update an entity with children objects, these child objects will also be updated. There is no need to update al the child objects separately.\nThis is a new behaviour from the entity framework core **update** method on the DbSet.\n\n``` csharp\nusing (var uow = _uowProvider.CreateUnitOfWork())\n{\n    var repository = uow.GetRepository\u003cMyEntity\u003e();\n    repository.Update(updatedEntity);\n    await uow.SaveChangesAsync();\n}\n```\n\n### Remove\n\nYou can call this method with an existing entity :\n\n``` csharp\nusing (var uow = _uowProvider.CreateUnitOfWork())\n{\n    var repository = uow.GetRepository\u003cMyEntity\u003e();\n    repository.Remove(existingEntity);\n    await uow.SaveChangesAsync();\n}\n```\n\nOr with the Id of an existing entity :\n\n``` csharp\nusing (var uow = _uowProvider.CreateUnitOfWork())\n{\n    var repository = uow.GetRepository\u003cMyEntity\u003e();\n    repository.Remove(id);\n    uow.SaveChangesAsync();\n}\n```\n\n### Custom Repositories\n\nWhen you need more functionality in a repository than the generic methods, you can create our own repositories by inheriting from the repository base classes.\n\nTo make a repository that is tied to 1 entity type, you inherit from the _**EntityRepositoryBase**_ class :\n\n``` csharp\npublic class MyRepository\u003cMyEntity\u003e : EntityRepositoryBase\u003cMyDbContext, MyEntity\u003e , IMyRepository\n{\n    public MyRepository(ILogger logger) : base(logger, null)\n    { }\n}\n```\n\nThis base class already contains the generic Add, Update, Delete, Get and Query methods.\n\nIf you just want to start with an empty repository or a repository that is not tied to 1 type of entity, inherit from the _**RepositoryBase**_ class :\n\n``` csharp\npublic class MyRepository : RepositoryBase, IMyRepository\n{\n    public MyRepository(ILogger logger) : base(logger, null)\n    { }\n}\n```\n\n**Don't forget to register your own repositories in the DI container at startup :**\n\n``` csharp\nservices.AddTransient\u003cIMyRepository, MyRepository\u003e();        // or any other scope (Scoped, Singleton).\n```\n\n## Query\nThese helpers help generating queries:\n\n### Filter\nA Filter holds the requested filter (WHERE) values.\n\n``` csharp\nList\u003c`Participant`\u003e participants = null;\n\nusing (var uow = _uowProvider.CreateUnitOfWork(false))\n{\n    Filter\u003cEntities.Participant\u003e\n    filter = new Filter\u003cEntities.Participant\u003e\n    (null);\n\n    filter.AddExpression(e =\u003e idList.Contains(e.Id));\n\n    var repository = uow.GetRepository\u003cIRepository\u003cParticipant\u003e\u003e();\n\n    participants = (await repository.QueryAsync(filter.Expression, includes:includes)).ToList();\n}\n```\n\n### Includes\nHolds the parameters to generate the Include part of the query.\n\n``` csharp\n\nvar includes = new Includes\u003cBuilding\u003e(query =\u003e\n{\n    return query.Include(b =\u003e b.Appartments)\n                    .ThenInclude(a =\u003e a.Rooms);\n}); \n\nbuildings = await repository.GetAllAsync(null, includes.Expression);\n\n```\n\n### OrderBy\nHolds the parameters to generate the OrderBy part of the query.\n\n``` csharp\n\nvar orderBy = new OrderBy\u003cEntities.Participant\u003e(string.IsNullOrEmpty(paging.Sort) ? \"Reservation.DateOfReservation\" : paging.Sort, paging.Descending);\n\n```\n\n## Paging\n\nWhen working with large collections of data you'll want to keep your application performant. Instead of retrieving all records, you can serve your data\nto the consumer in pages.\n\nThe repositories have methods that can be used with paging systems. You can also inject a IDataPager object in your classes to retrieve paged data :\n\n``` csharp\npublic class MyBusinessClass\n{\n    public MyBusinessClass(IDataPager\u003cMyEntity\u003e pager)\n    {\n        _pager = pager;\n    }\n\n    private readonly IDataPager\u003cMyEntity\u003e _pager;\n}\n```\n\nand call its methods to retrieve paged data :\n\n``` csharp\nvar pageNumber = 1;\nvar pageLength = 10;\n\nvar data = _pager.Get(pageNumber, pageLength);\n\nvar filter = new Filter\u003cMyEntity\u003e(e =\u003e e.AProperty == true);\n\nvar filteredData = _pager.Query(pageNumber, pageLenght, filter);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigipolisantwerp%2Fdataaccess_aspnetcore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdigipolisantwerp%2Fdataaccess_aspnetcore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigipolisantwerp%2Fdataaccess_aspnetcore/lists"}