ICRUDRepository interface
namespace: MvcControlsToolkit.Core.Business.Utilities
The ICRUDRepository
interface is the standard way Base controllers interact
with the business layer. You may use either its default implementation,
or classes inheriting from the default implementation,
or completely custom implementations.
It contains all CRUD operations, paged retrieval operations, single record retrieval, and methods for copying back newly created principal keys in the associated ViewModels/DTO:
public interface ICRUDRepository { void Update<T>(bool full, params T[] viewModel); void UpdateList<T>(bool full, IEnumerable<T> oldValues, IEnumerable<T> newValues); void Add<T>(bool full, params T[] viewModel); void Delete<U>(params U[] key); Task<T> GetById<T, U>(U key); Task<DataPage<T>> GetPage<T>(Expression<Func<T, bool>> filter, Func<IQueryable<T>, IOrderedQueryable<T>> sorting, int page, int itemsPerPage, Func<IQueryable<T>, IQueryable<T>> grouping=null); Task<DataPage<T1>> GetPageExtended<T1, T2>(Expression<Func<T1, bool>> filter, Func<IQueryable<T2>, IOrderedQueryable<T2>> sorting, int page, int itemsPerPage, Func<IQueryable<T1>, IQueryable<T2>> grouping = null) where T2: T1; Task SaveChanges(); void UpdateKeys(); Func<object, object> GetKey { get; } }
In all methods containing bool full
, full
set to true
declares that all viewModels/DTO contain all fields
of the corresponding DB class, so there is no need to retrieve the original DB object to apply modifications,
but it is enough to attach a new instance of the DB class to its DBSet, then copying all ViewModels/DTO properties, and finally
setting the DB object state to modified.
All methods operate with ViewModels/DTO objects in such a way to hide the DB classes to the UI layer. Important: ViewModel key type may correspond either to the same DB model type or to a possible nullable version of it.
The meaning of Update, Add, and deletes
is obvious.
GetById
retrieve a single instance given its key.
SaveChanges
save changes to the database and, if needed, copy newly created keys
back into the corresponding ViewModels.
UpdateKeys
performs just the newly created keys copy operation and is used
typically when changes to the DB context are saved by another repository.
GetKey
is for internal use, and custom ICRUDRepository
implementations
should simply return null.
The UpdateList<U>
accepts two lists of ViewModels: the original list before some CRUD modifications are applied by the user, and the version of the same list after all user modifications.
It uses these two lists to autodetect all Add, Update and Deletes performed by the user
and applies all of them to the DBSet. Typically, the unmodified version of the list is obtained by storing
the original list in the Razor View with the help of the store-model TagHelper.
GetPage
returns a page of data given the page number, the items per page, a filter to apply (expressed in terms of ViewModel properties),
chain of sorting operators and an optional grouping.
The second overload allow a different ViewModel for grouped data. Use it only if the grouping function is not null.
await Repository.GetPage<ProductViewModel>( null, q => q.OrderBy(m => m.Name), currPage, 3)
The DataPage<T;>
class is defined as:
public class DataPage<T>
{
public ICollection<T> Data { get; set; }
public int Page { get; set; }
public int TotalPages { get; set; }
public int TotalCount { get; set; }
public int ItemsPerPage { get; set; }
}
TotalCount
contains the total number of items that satisfy the query, while TotalPages
contains the total number of data pages. Data
contains the actual data composing the page.
The example below show how to use the two overloads of GetPage
when receivig OData queries
in the url:
var query = queryProvider.Parse<FoodViewModel>(); int pg = (int)query.Page; var grouping = query.GetGrouping<FoodViewModelGrouping>(); var model = new FoodListViewModel { Query = query, Products = grouping == null ? await Repository.GetPage( query.GetFilterExpression(), query.GetSorting() ?? (q => q.OrderBy(m => m.ProductName)), pg, 5) : await Repository.GetPageExtended( query.GetFilterExpression(), query.GetSorting<FoodViewModelGrouping>() ?? (q => q.OrderBy(m => m.ProductName)), pg, 5, query.GetGrouping<FoodViewModelGrouping>())