Giter VIP home page Giter VIP logo

easyrepository.efcore's Introduction

Gitmoji


Give a Star ๐ŸŒŸ

If you liked the project or if EasyRepository.EFCore helped you, please give a star.


Purpose

Easy Repository For EF Core provides implementation generic repository pattern on Entity Framework Core


What is Generic Repository Pattern

The generic repository pattern implements in a separate class library project. ... The repository pattern is intended to create an Abstraction layer between the Data Access layer and Business Logic layer of an Application. It is a data access pattern that prompts a more loosely coupled approach to data access.


Documentation

Visit Wiki page for documentation.

Star History

Star History Chart

easyrepository.efcore's People

Contributors

furkandeveloper avatar jeffward01 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

easyrepository.efcore's Issues

โœจ [FEATURE] UnitOfWork --> EfCore Transactions and Rollbacks?

Summary

I am not sure if there is a reason why this is not implemented, perhaps you have done some tests and its not as simple as it looks.

Is there any reason why Transactions and Rollback is not implemented?

Is this something that you'd like me to add?

Is there any particular feature or way you would like this to be implemented?

Reading

โœจ [FEATURE[ Introduce IAsyncEnumerable methods or remove IEnumerable<> as a parameter and change to ICollection<>

Summary

I propose we change IEnumerable<TEntity> to ICollection<TEntity> on the methods which have the entities.ToList()

image

My thoughts are:

Solutions:
1.) Change to IAsynEnumerable
or
2.) Use ICollection instead if IEnumerable

Which do you think would be better?

  • For the non-async methods, option 2 is the only solution
  • For the async methods, both option 1 and 2 can be applied

Should I make these changes? What are your thoughts on option 1 or 2?

โœจ[FEATURE] Implement Abstractions Layer

Summary

The end user (developer) should be able to operate both on their own assets and on the base entity assets provided on EasyRepository.

This should be considered when applying the Abstraction of Repository pattern.

When the end user wants to use the library, he should simply use it without making any changes in his own application.

If the end user wants to use fields such as PrimaryKey, CreateDate, UpdateDate, DeleteDate and IsDeleted automatically, they should be able to use these features with a base entity by EasyProfiler.

The Abstraction of Repository must be supported in two operations on the pattern.

For Example for EasyBaseEntity

public abstract class EasyBaseEntity<TPrimaryKey> : IEasyEntity<TPrimaryKey>, IEasyCreateDateEntity, IEasyUpdateDateEntity, IEasySoftDeleteEntity
{
    public virtual DateTime CreationDate { get; set; }
    public virtual TPrimaryKey Id { get; set; }
    public virtual DateTime? ModificationDate { get; set; }
    public virtual DateTime? DeletionDate { get; set; }
    public virtual bool IsDeleted { get; set; }
}
/// <summary>
/// Abstraction of Entity
/// </summary>
internal interface IEasyEntity<TPrimaryKey>
{
    TPrimaryKey Id { get; set; }
}
public interface IEasyCreateDateEntity
{
    public DateTime CreationDate { get; set; }
}
public interface IEasyUpdateDateEntity
{
    public DateTime? ModificationDate { get; set; }
}
public interface IEasySoftDeleteEntity
{
    public DateTime? DeletionDate { get; set; }

    public bool IsDeleted { get; set; }
}

โœจ [FEATURE] Pagination / filtering re-implementation

Summary

I was working with Pagination, and I found the way it was currently implemented to be restricting. I found (1) bug, and (1) major improvement that could be made.

For my own projects, this is a reason why I would not use this library (no offense). Many people need pagination to return:

Standard Pagination Response Object:
https://stackoverflow.com/questions/12168624/pagination-response-payload-from-a-restful-api

{
  "_metadata": 
  {
      "page": 5,
      "per_page": 20,
      "page_count": 20,
      "total_count": 521,
      "Links": [
        {"self": "/products?page=5&per_page=20"},
        {"first": "/products?page=0&per_page=20"},
        {"previous": "/products?page=4&per_page=20"},
        {"next": "/products?page=6&per_page=20"},
        {"last": "/products?page=26&per_page=20"},
      ]
  },
  "records": [
    {
      "id": 1,
      "name": "Widget #1",
      "uri": "/products/1"
    },
    {
      "id": 2,
      "name": "Widget #2",
      "uri": "/products/2"
    },
    {
      "id": 3,
      "name": "Widget #3",
      "uri": "/products/3"
    }
  ]
}

Something like this^^

The key is to get this back as a JSON response object:

 {
      "page": 5,
      "per_page": 20,
      "page_count": 20,
      "total_count": 521,
      "Links": [
        {"self": "/products?page=5&per_page=20"},
        {"first": "/products?page=0&per_page=20"},
        {"previous": "/products?page=4&per_page=20"},
        {"next": "/products?page=6&per_page=20"},
        {"last": "/products?page=26&per_page=20"},
      ]
  }

or at the minimum return this as a JSON response object:

 {
      "page": 5,
      "per_page": 20,
      "page_count": 20,
      "total_count": 521,      
  }

Current Pagination Bugs

  • You use the library AutoFilterer to implement filtering and pagination
  • When you work with filtering and pagination, you eliminate any Pagination Object to be returned. See Code below
    public List<TEntity> GetMultiple<TEntity, TFilter>(EfTrackingOptions asNoTracking, TFilter filter)
        where TEntity : class
        where TFilter : FilterBase
    {
        return this.FindQueryable<TEntity>(asNoTracking)
            .ApplyFilter(filter)
            .ToList();
    }

What is currently implemented (This is the bug):

  • There is an DBO Entity, just something in the database
  • You apply the pagination style filtering to it
  • Then you return the DBO Entity instead of the Pagination Response Object
  • This means if the user has some pagination properties such as Total Pages, Current Page, Total Results, etc... These will not be returned to the user. Only the DBO Entity will be returned.

Proposed Changes

I propose (2) things:

  1. Remove the filtering and pagination from the current library, create a new extension library called EasyRepository.EfCore.AutoFilterer -- This will allow us to implement new filter implementation using Gridify, Sieve and others, instead of currently we are 'married' to AutoFilterer

This is the improvement I mentioned in the beginning of my post.

  1. On Filtered and Paginated Methods, return the TFilter object instead of the TEntity Object. This will be a 'breaking change' as it involves changing what currently implemented methods return.
  • Perhaps, to avoid the breaking change, instead we add a suffix of Paged or Filtered to the method. I prefer the suffix of Paged as mostly all Filtered use-cases for UI's will also be Paged.

Closing Statement

To be honest, I need these methods in my own implementation, so I will get started on this. If you reject this proposal I 100% understand, and I will keep the code to myself.

If you think this is helpful and useful, I will add my code and create a pull-request so that our branches can be 'in-sync'.

What are your thoughts? Please make any changes or suggestions as you see fit.

โœจ [FEATURE] Would like to migrate to 'file scoped' namespaces

Summary

I would like to remove all namespace scoped brackets, in favor of file-scoped namespaces.

No code changes will be required, as currently each file only uses one namespace - so this is a perfect scenerio to change to file scoped namespaces

Advantage

  • Cleaner code.
  • Currently, every file only has 1 namespace as it is, so it makes sense to use 'file-scoped namespaces'
  • No need for more brackets as it makes clutter

Additional context

Additional Reading topics

โœจ [FEATURE] Enable Nullable Reference Types, add null exceptions, add null checks

Summary

Basically this Feature request is to enable: Nullable Reference Types

If approved, I can implement this change

Advantage

In favor of being explicit, nullable reference types will highlight and throw errors when null is returned when it is not expected. Such as:

image

    private Expression<Func<TEntity, bool>> GenerateExpression<TEntity>(object id)
    {
        
        // Type might be null
        var type = this._context.Model.FindEntityType(typeof(TEntity));
        
        
        // Type might be null.. If this is not 'caught' then it will throw NullReference Error.
        // Instead... We can 'catch' the Null Reference Error and then throw an error such as:
        // EasyRepositoryTypeNotFoundException : Exception
        // Message: The Type TypeOf(TEntity).Name was not found, please ensure it exists within the DBContext model as a registered
        // DbSet<TEntity>.
        //---- This is a change in favor of being 'explicit'.
        var pk = type.FindPrimaryKey()
            .Properties.Select(s => s.Name)
            .FirstOrDefault();
        
        
        // Type might also be null here
        var pkType = type.FindPrimaryKey()
            .Properties.Select(p => p.ClrType)
            .FirstOrDefault();

        // PkType might be null here also
        var value = Convert.ChangeType(id, pkType, CultureInfo.InvariantCulture);

        var pe = Expression.Parameter(typeof(TEntity), "entity");
        var me = Expression.Property(pe, pk);
        var constant = Expression.Constant(value, pkType);
        var body = Expression.Equal(me, constant);
        var expression = Expression.Lambda<Func<TEntity, bool>>(body, pe);

        return expression;
    }

Further Reading of advantages:

Proposed Changes

  • Enable Nullable Reference Types
  • Add EasyRepositoryTypeNullException and other exception types for EasyRepository such as EasyRepositoryPrimaryKeyNotFoundException, and others
  • Add Null checks for when null can be returned, yet, EasyRepository does not expect null to be returned. Then we would throw an exception instead of .NET xxx throwing a NullReferenceTypeException

Additional context

Personally, I like to be explicit in code, it helps prevent and diagnose errors. I think Nullable Reference types will lower the likely-hood of future bugs, and also help the developer user (consumer of EasyRepository library) diagnose bugs.

I can add this feature if approved

โœจ [FEATURE] Unit Of Work

Summary

What is Unit Of Work?

Unit of Work is the concept related to the effective implementation of the Repository Pattern. To understand this concept in better it is important to understand the concept of the Repository Pattern. We will not get into the details of the Repository Pattern in this discussion. But a small idea of this concept is necessary to proceed further.

Advantage

  • Decouple Business code from data Access. As a result, the persistence Framework can be changed without a great effort
  • Separation of Concerns
  • Minimize duplicate query logic
  • Testability

โœจ [FEATURE] Add 'Enum.AsNoTracking' to all methods instead of using bool values

Summary

I would like to add an overload that takes Enum.AsNoTracking to all of the methods. For example, currently there might be a method such as this:

image

I would like to add an overload that takes an enum instead of bool

image

In this enhancement I suggest we:

  • Add the overload parameter, and eventually in later versions remove the bool parameter
  • Add the overload parameter and also remove the bool parameter

What do you suggest?

Advantage

Explicit parameters help the developer. using a bool of true or false can mean anything. The developer must look at the xml notes in order to see "Ah yes... this is for change tracking"

Here are some articles about it:

Additional context
I will need your advice and suggestions on naming the classes and properties.

I suggest these, please let me know your input and feel free to rename or re-design

Enum

public enum EfTrackingOptions
{
        
    /// <summary>
    /// Disables EfCore change tracking
    /// </summary>
    AsNoTracking,
            
    /// <summary>
    /// Enables EfCore Change Tracking
    /// </summary>
    WithTracking
}

Extension Method

internal static class EfTrackingOptionExtensions
{
    public static bool HasNoTracking(this EfTrackingOptions options)
    {
        return options == EfTrackingOptions.AsNoTracking;
    }
}

Outstanding Questions & Input required

  1. Should we do option 1 of add the overload, and not remove the bool, or option 2 of add the overload and remove the bool parameter
  2. Naming suggestions of enum class name and property names
  3. Naming suggestions of extension method class name and method name

โœจ [FEATURE] Specification pattern must be supported (Ardalis.Specification)

Summary

EasyRepository.EFCore must be support DDD based specification model.

Advantage

One Domain-Driven-Design solution to the problem of where to place querying, sorting, and paging logic is to use a Specification. The Specification design pattern describes a query in an object. So to encapsulate a paged query that searches for some products, one might create a PagedProduct specification which would take in any necessary parameters (pageSize, pageNumber, filter). Then one of your repository methods (usually a List() overload) would accept an ISpecification and would be able to produce the expected result given the specification. There are several benefits to this approach. The specification has a name (as opposed to just a bunch of LINQ expressions) that you can reason about and discuss. It can be unit tested in isolation to ensure correctness. And it can easily be reused if you need the same behavior (say on an MVC View action and a Web API action, as well as in various services). Further, a specification can also be used to describe the shape of the data to be returned, so that queries can return just the data they required. This eliminates the need for lazy loading in web applications (bad idea) and helps keep repository implementations from becoming cluttered with these details.

Additional context
There is no need to make a native implementation. Ardalis.Specification library should be supported by default.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.