GrayMP

DOC Repository 1.0.2 readme

May 13th, 2018
181
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.07 KB | None | 0 0
  1. Welcome to DI-aware flexible DbContext wrapper!
  2.  
  3. Entry points:
  4.     - IBasicRepository - contains generic methods to access any table or view under context
  5.     - IBasicTableRepository - same, but methods are limited to single table or view under context.
  6.  
  7.     You can find them at DevOvercome.EntityFramework.Repository.RepositoryFactory
  8.     This is basically DI-container helper, in case if your container doesnt see internal classes.
  9.     Also, this factory can be inherited in order to return your custom repositories. Just in case.
  10.  
  11. // TODO: move to wiki.
  12. Simple example for ASP.NET with Ninject
  13. (Note that I ommited a lot of code, to point important parts)
  14.  
  15.     NinjectWebCommon.cs must contain this directive:
  16.         kernel.Bind(x =>
  17.         {
  18.             // Have only ONE implementation of ONE interface.
  19.             // Like we used to UserManager : IUserManager.
  20.             // Please follow this rule and you will be fine
  21.             try
  22.             {
  23.                 x.FromAssembliesMatching("*")
  24.                     .IncludingNonPublicTypes()
  25.                     .SelectAllClasses()
  26.                     .BindDefaultInterface();
  27.             }
  28.             catch(ReflectionTypeLoadException rex)
  29.             {
  30.                 // cant reproduce locally
  31.                 throw rex.LoaderExceptions[0];
  32.             }
  33.         });
  34.  
  35.     See my list of ninject-packages where it works:
  36.       <package id="Ninject" version="3.3.4" targetFramework="net471" />
  37.       <package id="Ninject.Extensions.Conventions" version="3.3.0" targetFramework="net471" />
  38.       <package id="Ninject.Extensions.Factory" version="3.3.2" targetFramework="net471" />
  39.       <package id="Ninject.MVC5" version="3.3.0" targetFramework="net471" />
  40.       <package id="Ninject.Web.Common" version="3.3.0" targetFramework="net471" />
  41.       <package id="Ninject.Web.Common.WebHost" version="3.3.0" targetFramework="net471" />
  42.  
  43.     Now, when you have DI-container, you can just ask for repository in Controller constructor just like that:
  44.         public HomeController(
  45.             IBasicTableRepository<vw_someView> viewRepository,
  46.             IBasicTableRepository<table1> table1Repository)
  47.         {
  48.             this.viewRepository = viewRepository;
  49.         }
  50.  
  51.         and call the internal INTERFACE property which has been initialized by IMPLEMENTATION
  52.  
  53.         // see get
  54.         public ActionResult GetView()
  55.         {
  56.             var res = viewRepository
  57.                 .BuildFetch()
  58.                 .AddFilter(x => x.type = 'someType')
  59.                 .AddFilter(x => x.dateCreated >= DateTime.Now) // whatever
  60.                 // not required, but you can sort. only once.
  61.                 .AddSorting("id", SortDirectionEnum.Asc)
  62.                 .Fetch(); // or FetchAsync in async actions
  63.         }
  64.  
  65.         // see get with paging
  66.         public ActionResult GetView(int pageIndex, int pageSize)
  67.         {
  68.             var res = viewRepository
  69.                 .BuildFetch()
  70.                 .AsPagingBuilder()
  71.                 .SetPaging(pageIndex, pageSize)
  72.                 .FetchPaging(); // or FetchPagingAsync
  73.  
  74.             // res is PagingResult class
  75.             return res.Items; // actual items
  76.         }
  77.  
  78.         // see save
  79.         public ActionResult AddItem(table1 item){
  80.             table1Repository
  81.                 .AddItem(item)
  82.                 .Save(); // or SaveAsync
  83.         }
  84.  
  85.         // see get with includes!
  86.         public ActionResult GetItemWithCategories(int id)
  87.         {
  88.             var res = table1Repository
  89.                 .BuildFetch()
  90.                 .Include(x => x.table2)
  91.                 .AddFilter(x => x.id == id)
  92.                 .FetchOne(); // or fetch one async
  93.  
  94.             // object is in context, you can update it
  95.             res.dateLastViewed = DateTime.UtcNow;
  96.             table1Repository
  97.                 .UpdateItem(res)
  98.                 .Save();
  99.         }
  100.  
  101.         // force context loading!
  102.         public ActionResult BulkUpdate(string status, int[] ids)
  103.         {
  104.             table1Reposisotry
  105.                 .BuildFetch()
  106.                 .AddFilter(x => ids.Contains(x.id))
  107.                 .SetNoTracking(false)
  108.                 .Fetch()
  109.                 .ForEach(x =>
  110.                 {
  111.                     x.status = status;
  112.                     table1Repository.UpdateItem(x);
  113.                 });
  114.  
  115.             table1Repository.BuildSave().Save();
  116.         }
  117.  
  118.     Please note that
  119.     - multiple results like Fetch or PagingFetch forces NoTracking=true.
  120.     - single results like FetchOne forces NoTracking=false.
  121.     You can override it in any particular query, as shown above.
  122.  
  123.     This is a basic usage.
  124.  
  125. Advanced repositories
  126.     The situation, where DAL must work with couple of table as one, can be very often occured.
  127.     In order to encapsulate that in single class,
  128.     feel free to introduce your own repository,
  129.     with your own methods,
  130.     with NO FOLLOWING IBasicRepository pattern.
  131.     How? A wrapper!
  132.  
  133.     // your name could be different, of course. Just follow this pattern
  134.     // also I strongly advise to follow INTERFACE-IMPLEMENTATION pattern - better for DI-container, testable, and with no sweat.
  135.     public class CoupledRepository : ICoupledRepository
  136.     {
  137.         public CoupledRepository(
  138.             IBasicRepository wholeContext,  // way too abstract. Dont recommend to abuse it - makes your repo's contract blurry. However, it works like sharm for tiny cases.
  139.             IBasicTableRepository<table1> justTable1Repository,  // good way to keep your class's contract clear.
  140.             IBasicTableRepository<table2> justTable2Repository,
  141.             )
  142.             {
  143.                 // initialization ommited
  144.             }
  145.         public void DoWork(table1 t1, table2 t2, table3 t3){
  146.             justTable1Repository.Update(t1);
  147.             justTable2Repository.Update(t2);
  148.  
  149.             wholeContext<table3>
  150.                 .Update(t3)
  151.                 .Save(); // you can call Save at any time, on any repository, since DbContext behind them is singleton per request
  152.         }
  153.     }
  154.  
  155.  
  156.  
  157.  
  158.  
  159. Guides and best practices
  160.     WARNING!
  161.     Please, be adviced - you can face the situation when constructor contains too much dependencies.
  162.     It is not fine! But you actually can live with that.
  163.     Hovewer, the repository wrappers (see above) are strongly recommended.
  164.  
  165.     IBasicRepository vs IBasicTableRepository
  166.     I strongly recommend to use IBasicTableRepository in order to keep contract and class's responsibility clear.
  167.     Hovewer, there is still a place for IBasicRepository
  168.         - if class should invoke just one operation for one of dozens tables
  169.         - this is the case where I personally prefer blurry single object that dozens specific noisy TableRepositories
  170.  
  171.     Keep in mind that you are free to make any complicated dependencies without bothering for wiring.
  172.     All implementations will be shared per request.
  173.  
  174. This concludes Welcome.txt.
  175. Feel free to explore further opportunities which DevOvercome.Repository offers!
  176. It is designed to serve wide range of cases (mean, less restrictions)
Advertisement
Add Comment
Please, Sign In to add comment