Unit of Work & Repository Framework with ASP.NET MVC 5, Entity Framework 6 & Unity 3 (Quick-Start Video)

Update: 08/12/2014 – Please refer to https://genericunitofworkandrepositories.codeplex.com/documentation for latest documentation. There have been breaking changes released since this recording was published.

Update: 02/24/2014 – v3.2 released, improved API and reusable queries with the Object Query Pattern. Breaking change: Framework now ships returning all things TEntity or IEnumberable for compartmentalization, you will need to change the Repository.cs (see below, what methods signatures to change) if IQueryable is preferred over IEnumerable, IEnumerable is preferred as a best practice (http://genericunitofworkandrepositories.codeplex.com/documentation).

Update: 01/06/2014 – When viewing please configure your YouTube
player to 1080p for clear viewing of the coded demos.

https://genericunitofworkandrepositories.codeplex.com/documentation

Hope everyone had a wonderful New Years holiday, with the new year starting wanted to fulfill a high request, which was a quick start video on the Unit of Work and Repository Frameworks in ASP.NET MVC with Unity for IoC and DI.

This video will touch on the following topics:

  • Entity Framework Power Tools
  • Uow & Repo Framework
  • Generating EF Mappings and POCO’s
  • Upgrading the stack to EF 6.2
  • Basic Customer CRUD Use Case with MVC Scafolding Template w/ Async
  • Refactoring the CustomerController to use UoW & Repo Framework w/ Async
  • Why the ICustomerService Approach?
  • Why Commit Unit of Work Outside the Service vs. versa
  • Quick Examples with Eager Loading, Filter, and Sorting

Sample application download: https://skydrive.live.com/redir?resid=949A1C97C2A17906%216769
(Please enable Nuget Packages Restore at the Solution Level)

Questions and/or comments please tweet @LeLong37.

Note:

1. Although the quick start video, takes the approach of committing the unit of work outside the ICustomerService exampled, whether you choose to do this inside your services or manage this outside, there is no right or wrong, this is totally team preference.

2. Also all use cases demonstrated in the CustomerController could have been satisfied by using the UnitOfWork out of the box without the need to implement the ICustomerService, however as mentioned, this is the preferred best practice.

Using ICustomerService in CustomerController


[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit([Bind(Include = "CustomerID,CompanyName,ContactName,ContactTitle,Address,City,Region,PostalCode,Country,Phone,Fax")] Customer customer)
{
    if (ModelState.IsValid)
    {
        customer.ObjectState = ObjectState.Modified;
        _customerService.Update(customer);
        await _unitOfWork.SaveAsync();
        return RedirectToAction("Index");
    }
    return View(customer);
}

Without ICustomerService and using IUnitOfWork out of the box in the CustomerController


[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit([Bind(Include = "CustomerID,CompanyName,ContactName,ContactTitle,Address,City,Region,PostalCode,Country,Phone,Fax")] Customer customer)
{
    if (ModelState.IsValid)
    {
        customer.ObjectState = ObjectState.Modified;
        _unitOfWork.Repository<Customer>().Update(customer);
        await _unitOfWork.SaveAsync();
        return RedirectToAction("Index");
    }
    return View(customer);
}

In this case it is preferred that the IRepository return IEnumerable vs. IQueryable.

HAVING THE REPOSITORY RETURN ALL THINGS IEnumerable or IList is a best practice and preferred approach. Down the line, if you were to ever switch out your back-end, you won’t be bound to the requirements that the back-end implements IQueryable e.g. moving from EF to pure REST services.

Question? Why does the Repository in the framework return IQueryable?

Answer: Because most devs have been spoiled with ORM’s (e.g. nHibernate.Linq, Linq to Sql, Entity Framework) returning IQueryable and I received to many requests and complaints when the Repository layer in the Framework was returning IEnumerable or IList. Another caveat is that you can’t definitively tell what SQL queries are happening in your application by looking at the Repository layer, because you haven’t truly compartmentalized them in this layer; developers are more than able to modify the query plan before the query is actually executed.

For teams that prefer all things returned as IEnumerable from Repository layer, this would require three lines of code to be changed in the framework, here’s how:

  1. Repository.IRepositoryQuery.cs

    
    IEnumerable<TEntity> Get();
    
    
  2. Repository.RepositoryQuery.cs

    
            public IEnumerable<TEntity> Get()
            {
                return _repository.Get(_filter, _orderByQuerable, _includeProperties, _page, _pageSize);
            }
    
    
  3. Repository.Repository.cs

    
            internal IEnumerable<TEntity> Get(
                Expression<Func<TEntity, bool>> filter = null,
                Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
                List<Expression<Func<TEntity, object>>> includeProperties = null,
                int? page = null,
                int? pageSize = null)
            {
                IQueryable<TEntity> query = _dbSet;
    
                if (includeProperties != null)
                    includeProperties.ForEach(i => query = query.Include(i));
    
                if (filter != null)
                    query = query.Where(filter);
    
                if (orderBy != null)
                    query = orderBy(query);
    
                if (page != null && pageSize != null)
                    query = query
                        .Skip((page.Value - 1) * pageSize.Value)
                        .Take(pageSize.Value);
    
                return query;
            }
    
    
    

Additional references: http://blog.longle.net/2013/05/11/genericizing-the-unit-of-work-pattern-repository-pattern-with-entity-framework-in-mvc/

Sample application download: https://skydrive.live.com/redir?resid=949A1C97C2A17906%216769

CodePlex download for the framework: https://genericunitofworkandrepositories.codeplex.com/

Happy coding…! :)

About these ads

144 thoughts on “Unit of Work & Repository Framework with ASP.NET MVC 5, Entity Framework 6 & Unity 3 (Quick-Start Video)

  1. Hi Le I’m following the instructions in your video , I’m using VS 2013 update 3 , when trying to add the scaffolded controller I’m getting the next issue

    “There was an error running the selected code generator: ‘A configuration for type ‘Northwind.Data.Models.Category’ has already been added. To reference the existing configuration use the Entity() or ComplexType() methods.’

    I would appreciate a lot if you could help me with this

    Thanks

    Jose

    Like

  2. Error 1 The type ‘Northwind.Data.Models.Customer’ cannot be used as type parameter ‘TEntity’ in the generic type or method ‘Repository.IRepository’. There is no implicit reference conversion from ‘Northwind.Data.Models.Customer’ to ‘Repository.EntityBase’. F:\MVC Project\Unit of Work & Repository Framework with ASP.NET MVC 5, Entity Framework 6 & Unity 3 (Quick-Start Video)\Northwind.Service\CustomerService.cs 13 48 Northwind.Service

    Like

    • public class CustomerService : ICustomerService
      {
      private readonly IRepository _customerRepository;

          public CustomerService(IRepository customerRepository)
          {
              _customerRepository = customerRepository;
          }
      
          public Task<IEnumerable> GetAsync()
          {
              return _customerRepository.Query().GetAsync();
          }
      

      Like

  3. Pingback: Unit of Work & Repository Framework – Review | 7thSunSoftware

  4. Hi Le,

    This is my second question.
    What is the best way to execute stored procedures in this framework?

    I am doing it through repository.SqlQuery(..).

    Problem is that the output resultset of stored procedure is mapped as “Complex Type” in Entity.edmx files and its classes, and thus throwing various issues.

    How do I get result in Entity type and no in complex type? I keep on getting this error
    ” The Set method, DbSet objects, and DbEntityEntry objects can only be used with entity types, not complex types.”

    Here is my sample method declaration in service layer:
    public IQueryable ExecuteSpWork(…)
    {
    _repository.SqlQuery(..).;
    }

    Is there any simple way to execute stored procedure and grab there output result set?

    Like

  5. I see a lot of interesting posts on your page. You have to spend a
    lot of time writing, i know how to save you a lot of time, there is a tool that creates unique, google friendly posts in couple of minutes, just search in google –
    laranita’s free content source

    Like

  6. Pingback: [RESOLVED]Repository | ASP.NET MVC

  7. Pingback: [RESOLVED]Repository | ASP Web Form Data Control

  8. Pingback: [RESOLVED]Repository | ASP Questions & Answers

  9. Hey Le, Awesome job with the uow and repo framework. I was re-enacting the unit testing you had for ProductRepositoryTest.cs using the uow fakedbcontext/fakedbtest. Everything worked well except when i tried to do insert on one or more related entity (based on FK), It returned nothing. My first guess is probably because the dbcontext is under a disconnected environment. Do i need to still specify the relationships under OnModelCreating for the fake dbcontext?

    Thanks in advance

    Like

  10. Thank you Le for your great efforts. Still I can not use “batch: true” in kendo grid with your framework. The key is always null because :
    url: function (data) {
    return svcUrl + ‘(‘ + data.ID + ‘)';
    },

    should be some how overridden. I tried to work with parameterMap or override the above update function with no luck.

    Can you help me to get ID for each updated record in the batch. Many thanks in advance.

    Like

  11. Overall this looks like a great repository / unit of work framework. It has been a bit frustrating over the past couple days though. I like many developers have a pretty full day, and I was looking for a solution like yours for a new project, this all mixed in with the other 50 things I need to get done. I was hoping to jump in and have your generic repository up and running in little time, but that has not been the case. Maybe there is an earlier post I am missing, but I’m struggling getting this implemented. Maybe I’m just being dense, but it seems to be lacking some pretty “basic” steps to get your solutions going. Your video talked about packages that are needed, and you reference the separation, and list your solutions structure, all good, but seems to completely fail in showing that does/does not need to be referenced. Then looking at the sample code, it does not match the articles code, making it even harder to set up. Given that I seem to be the only person commenting on this, I assume I a missing something.:) Do you have some sort of a “quick start” guild that you can point out to me and others that might be in the same boat?

    Thanks!

    Like

    • @LoveDev – I ran into the same thing here – the video didn’t match the codeplex which didn’t match the blog posts. I have it up and running for retrieving data, but zero luck on inserting a new entity to the DB. Posted over on the codeplex forum to no avail. Seems it is lacking a few fundamental and basic setup guides or is for someone who may be very familiar with the patterns already (who could then write their own repository and unit of work frameworks).

      I had to basically pull the framework from the 3.3 release, figure out the implementation because the video is for a much previous version, and now I am stuck.

      My entity is added via form – tracks through everything and the Object State is set to added, but when I call save changes – nothing. No error, no row insert, no nothing. Just returns the object as it was, doesn’t resync the state or anything.

      Seems to me unless you are implementing it exactly as it is on this project (with Kendo, WebAPI, oData) it just doesn’t implement and work.

      At this point, I’ve wasted too much time to get a simple damn insert working with this pile I am at my wits end. If it actually provided some form of error on failure to insert I’d at least have a starting point, but I don’t. I have a big fat empty insert with a big fat empty response.

      Like

    • Inserts and Updates are fundamental use cases the framework has working since it’s inception. Please make sure the following requirements have been met:

      • Make sure the same “instance” DataContext is being used when setting ObjectState and when invoking save or save.async.If this is a web app, please make sure that IDataContext is has singleton behavior for the lifecycle of the http request for the user.

      • Make sure make sure you are setting the ObjectState e.g. Added, Modified, Deleted, etc. for the appropriate action are trying to perform.

      • Might be a good idea to download the sample application from CodePlex and make sure that inserts and updates are working and use this is a baseline example to compare from.

      Like

    • @southplatte,

      As for videos and documentation, the release cycle for the framework has been fairly rapid over the past few months, therefore there will be a considerable amount of “drift” in terms of current features and implementation and the supporting artifacts e.g. this blog post. The most recent and current documentation is on CodePlex (https://genericunitofworkandrepositories.codeplex.com/documentation).

      Since video is a few releases behind, and from it sounds like, somewhat confusing devs, we’ve removed it.

      Like

    • @le thanks for the update. It would be cool to see an updated video tutorial, but I know that takes time, been there, done that.

      @tshiloh88 I know the entity state is set correct, as I’ve checked that. As for the sample app, it doesn’t seem to be a full example, as I couldn’t find the insert/update code for reference and I pulled the latest 3.3 for ref. I am not sure on the same instance of the data context and that’s a good catch as I may not be the same running through a web app into service layer. As well not sure of the singleton behavior so thanks for that suggestion as well.

      Thanks for the suggestion I will keep digging. I like what it has and does so far, just got frustrated with a few things.

      Like

    • @southplatte,

      Here is Update working in the sample application (see: “Put” Web Api method):

      https://genericunitofworkandrepositories.codeplex.com/SourceControl/latest#main/Sample/Northwind.Web/Api/CustomerController.cs

      This is the same sample (live demo) that is currently deployed and running in Windows Azure (with Update working) http://longle.azurewebsites.net/#/customer.

      Here is where we configure Unity to inject the same instance of IUnitOfWork (Singleton behaivor bound to the lifecycle of the HTTP request).

      https://genericunitofworkandrepositories.codeplex.com/SourceControl/latest#main/Sample/Northwind.Web/App_Start/UnityConfig.cs

      Like

    • @Le I think I may not have the singleton instance proper in the Unity config – I had a bad time getting Unity up and running as well. I think due to this, it isn’t adding the entity to actually perform the update on the UofW savechanges() call. I will be working through this more over the next couple of days and repost back my findings.

      Thank you so much for the follow-up!

      Like

    • @Le Still no love on the insert. Adjusted my Unity config to match your sample, builds and runs fine and I can still retrieve data, but on the inserts SQL isn’t even getting generated according to Glimpse. At a complete loss. I am setting the entity state to Added, calling the repository Insert method and using unit of work to sync, which in turn is using the _dataContext to sync the changes.

      I see no errors at all during the process, can see the entity through the entire process until I call the unit of work savechanges(), but Glimpse shows zero SQL generating and I am not getting any insert performed and absolutely no feedback via logging methods employed either to pinpoint the failure.

      I’m either really stupid or it just doesn’t work how I have things configured.

      Like

    • @Le Got it figured out – thanks for all the help. I may take this experience and do up a beginner tutorial for others that have struggled with this. It was all due to 2 incorrect steps.

      1) Unity config was not providing the proper singleton instance (I had a completely different config I think based on earlier version and had no PerRequestLifeTimeManager() on the data contexts or unit of work contexts after updating it).

      2) I had used async in the service layer but not controller layer and somehow mashed the calls to work without error, but without success as well (I liken to to likely late night coding error on my part).

      Again, thanks for the feedback and direction. Working great now.

      Like

  12. Hi Le,

    I’m trying to do deep updates on associated collections.

    I’ve used Graphdiff successfully before where DbContext is exposed at a high level but not sure how I could add it to your UOW & Repository pattern.

    http://blog.brentmckendrick.com/introducing-graphdiff-for-entity-framework-code-first-allowing-automated-updates-of-a-graph-of-detached-entities/

    Maybe you know of a better way to manage records in a many-to-many table in EF6?

    I’ve used CreateLink and DeleteLink to manage single records but don’t think it works so well for multiple records at once.

    Thanks

    Like

    • If anyone is interested this works …

      IDbContext.cs and IRepository.cs

      void AttachObjectGraph(T entity, Expression<Func<IUpdateConfiguration, object>> mapping = null) where T : class, new();

      DbContextBase.cs

      public void AttachObjectGraph(T entity, Expression<Func<IUpdateConfiguration, object>> mapping = null) where T : class, new()
      {
      this.UpdateGraph(entity, mapping);
      }

      Repository.cs

      public void AttachObjectGraph(T entity, Expression<Func<IUpdateConfiguration, object>> mapping = null) where T : class, new()
      {
      _context.AttachObjectGraph(entity, mapping);
      }

      AsyncEntitySetController

      protected override async Task UpdateEntityAsync(int key, Client update)
      {
      if (update == null)
      throw new HttpResponseException(HttpStatusCode.BadRequest);

      if (key != update.ClientId)
          throw new HttpResponseException(Request.CreateODataErrorResponse(HttpStatusCode.BadRequest, new ODataError { Message = "The supplied key and the Client being updated do not match." }));
      
      try
      {
          update.ObjectState = ObjectState.Modified;
          _unitOfWork.Repository().AttachObjectGraph(update, m =&gt; m.AssociatedCollection(i =&gt; i.Issues));
          //_unitOfWork.Repository().Update(update);
          var x = await _unitOfWork.SaveAsync();
      }
      catch (DbUpdateConcurrencyException)
      {
          throw new HttpResponseException(HttpStatusCode.BadRequest);
      }
      return update;
      

      }

      Like

  13. Ive implemented your framework by following the video above. Amazing work. Ive ran into a problem when trying to implement an odatacontroller. Ive injected a service and your unitofworkasync into that controller as in the video but when I goto insert a record using the post action the service and the unitofwork are using separate instances of dbcontext and so calling SaveChangesAsync does not commit the changes (the new record)

    public async Task Post(User user)
    {
    if (!ModelState.IsValid)
    {
    return BadRequest(ModelState);
    }

            user.ObjectState = ObjectState.Added;
            user.User_ID = Guid.NewGuid();
            _userService.Insert(user);
    
            try
            {                
                await _unitOfWorkAsync.SaveChangesAsync();
            }
            catch (DbUpdateException)
            {
                if (UserExists(user.User_ID))
                {
                    return Conflict();
                }
                else
                {
                    throw;
                }
            }
    
            return Created(user);
        }
    

    Like

    • You need to make sure that your DI/IoC framework is injecting the same instance. In Unity this is done with it’s PerRequestLifetimeManager object for ASP.NET MVC.

      e.g.

      Note the how PerRequestLifeTimeManager is used to configure IDataContext so that it has Singleton like behavior for the lifecycle of the users “Http Request” and not Singleton like behavior for the life cycle of the application.

      
       container
                      .RegisterType<IDataContextAsync, NorthwindContext>(new PerRequestLifetimeManager())
                      .RegisterType<IUnitOfWorkAsync, UnitOfWork>(new PerRequestLifetimeManager())
                      .RegisterType<IRepositoryAsync<Customer>, Repository<Customer>>()
                      .RegisterType<IRepositoryAsync<Product>, Repository<Product>>()
                      .RegisterType<IProductService, ProductService>()
                      .RegisterType<ICustomerService, CustomerService>()
                      .RegisterType<INorthwindStoredProcedures, NorthwindContext>(new PerRequestLifetimeManager())
                      .RegisterType<IStoredProcedureService, StoredProcedureService>();
      
      

      Like

  14. Hi Le,

    Thanks for the amazing architecture.
    One query: How to update only modified columns/properties?

    Thanks,
    Manish

    Like

    • You will need to use the Patch (action/verb).

      
      //// PATCH: odata/Customers(5)
      [AcceptVerbs("PATCH", "MERGE")]
      public async Task<IHttpActionResult> Patch([FromODataUri] string key, Delta<Customer> patch)
      {
      	if (!ModelState.IsValid)
      	{
      		return BadRequest(ModelState);
      	}
      
      	Customer customer = await _customerService.FindAsync(key);
      
      	if (customer == null)
      	{
      		return NotFound();
      	}
      
      	patch.Patch(customer);
      	customer.ObjectState = ObjectState.Modified;
      
      	try
      	{
      		await _unitOfWorkAsync.SaveChangesAsync();
      	}
      	catch (DbUpdateConcurrencyException)
      	{
      		if (!CustomerExists(key))
      		{
      			return NotFound();
      		}
      		throw;
      	}
      
      	return Updated(customer);
      }
      
      

      https://genericunitofworkandrepositories.codeplex.com/SourceControl/latest#main/Sample/Northwind.Web/Api/CustomerController.cs

      Like

  15. Can i use this pattern with Database First model using EDMX files. What modification is needed in the the repository project . Let me know Thanks

    Kunal Deshmukh
    India

    Like

    • I know of teams that are using this with the EDMX, from what I understand they did make a small modification to the T4 templates so that the Entities are generated to inherit Entity.cs from the framework as well as the generated DbContext to inherit DataContext.cs from the framework.

      Like

  16. Hi Le,
    I have an architectural question in relation to your example in this blog.
    When I consume a web service, for example Pay Pal or Bing. Would you implement a service that communicates direct with the proxy or would you go another step further and create a repository and service?
    I am especially looking at your high level diagram in another blog ( http://blog.longle.net/2013/06/13/modern-web-application-layered-high-level-architecture-with-spa-mvc-web-api-ef/) entry of you and found it interesting that you put the yellow “Communication” over several layers.
    Any tips/advice is very appreciated.

    Thanks,
    Perry

    Like

    • I’ve placed PayPal in Services, due to it’s nature that once your using their API’s almost all of it is entrenched around business logic e.g. payments, ACH holds, charges (usually only after items have tracking number or shipped which again is business logic), the amount of logic that handles the different types of rejects or declines, etc. You may want to wrap PayPal e.g. PaymentService and expose PaymentService and not PayPal API’s to all the other services in the case you switch to another payment provider. This will help minimize your surface area for refactoring as well as shielding yourself to a certain degree of any API changes PayPal may have which will allow you to update a large systems to accommodate their changes at your own pace. This was proven extremely beneficial when we made the unplanned switch from Versign Payment Services to PayPal in the past, again, most of the refactoring was done in our PaymentService vs. every place that used needed to do any online payment transactions.

      As for Bing, depends on which Bing services and the use case, without knowing these, my initial response would still be to also put these in services as well.

      Like

  17. Hi Le, thanks for your post and video. I am learning a lot about this topics news for me. I follow step by step.

    I was wondering if you could give me some help.

    I want to know the way to reference in a console application.

    this code was my try.

    static void Main(string[] args)
    {

            IUnityContainer container = new UnityContainer();
            container
                .RegisterType &lt; IUnitOfWork, UnitOfWork &gt;(new PerResolveLifetimeManager())
                .RegisterType &lt; IDataContext, NorthwindContext &gt;(new PerResolveLifetimeManager())
                .RegisterType &lt; IRepository&lt;Product&gt;, Repository &lt; Product &gt;&gt;(new PerResolveLifetimeManager());
    
            using(var context = container.Resolve&lt;IDataContext &gt;())
            using (var unitOfWork = container.Resolve&lt;IUnitOfWork &gt;())
            {
                var some = unitOfWork.Repository&lt;Product &gt;().Query().Select().ToList();
            }            
        }
    

    Like

    • Please take a look at Northwind.Test project from the CodePlex download, this is how you would wire up your console application.

      Like

  18. Hi Le, thanks for your post and video. I am learning a lot about this topics news for me. I follow step by step.

    I was wondering if you could give me some help.

    I want to know the way to reference in a console application.

    this code was my try.

    static void Main(string[] args)
    {

            IUnityContainer container = new UnityContainer();
            container
                .RegisterType(new PerResolveLifetimeManager())
                .RegisterType(new PerResolveLifetimeManager())
                .RegisterType&lt;IRepository, Repository&gt;(new PerResolveLifetimeManager());
    
            using(var context = container.Resolve())
            using (var unitOfWork = container.Resolve())
            {
                var some = unitOfWork.Repository().Query().Select().ToList();
            }            
        }
    

    thanks for your post

    Like

    • We have no guidance for using this with MOQ, however there are teams that are using MOQ to mock test with the framework.

      Like

  19. Hi Lee, what a scenario like the one below:

    public class Transfer : EntityBase
    {
        public Guid TranferId { get; set; }
        public decimal Requested { get; set; }
        public decimal Value { get; set; }
        public DateTime TransferDate { get; set; }
        public string Direction { get; set; }
        public Guid UserId { get; set; }
        public Guid CashId { get; set; }
        public virtual User User { get; set; }
        public virtual CashDrawsMony CashDrawsMony { get; set; }
    }
    

    I’m try to figure out a way of using what you have talked about above but you cannot .Include(something).Include(Something else). This is not possible atm and this (http://stackoverflow.com/questions/13812386/use-include-method-in-repository) is close but no cigar.

    Can you help at all?

    Like

    • This is what worked for me the end:

          public List GetAllTransfersNew(int take)
          {
              return BaseRepository.Include(x =&gt; x.CashDrawsMony.User)
                  .Where(y =&gt; y.User.OrgId == _organizationId)
                  .OrderBy(z =&gt; z.TransferDate)
                  .Take(take)
                  .ToList();
          }
      

      I understand the relationships between the objects and snooping around, the above does indeed fill out the .User property and .CashDrawsMony property also. Now sure how it does this.

      Below is what I was kind of expecting to work but does not:

          public List GetAllTransfersNew(int take)
          {
              return BaseRepository.Include(x =&gt; x.User)
                   .Include(x =&gt; x.CashDrawsMony)
                  .Where(y =&gt; y.User.OrgId == _organizationId)
                  .OrderBy(z =&gt; z.TransferDate)
                  .Take(take)
                  .ToList();
          }
      

      Like

  20. Hi,
    How can I get entities implementing IObjectState interface?
    I’ve used Entity Framework Power Tools to generate POCO objects but generated entities do not implement above mentioned interface.
    And it is requirement for using IRepository from UoW & Generic Repository framework.
    Any help will be apprieciated.
    Best regards,

    Like

  21. HI, It is a great UOW implementation. Where and how would you add AsNoTracking for the queries?

    Code snippet will help me a lot as I am new to EF

    Like

  22. Hi Le,

    Greate article once again, you never fails! Thanks for sharing.

    I’ve got a question for you.

    In this example above:

    public async Task DeepLoadCustomerWithOrders(string id)
    {
    var customer = await _customerRepository
    .Query()
    .Filter(t => t.CustomerID == id)
    .Include(t => t.Orders.Select(u => u.OrderDetails))
    .GetAsync();

    return customer.FirstOrDefault();
    

    }

    It’s OK for me but,…

    How can I filter by specific OrderId for example, after include the table Order in my query? (The table “Orders” is ICollection defined on the class Customer.

    Like

  23. That’s weird. I actually can’t find Repository.IRepositoryQuery.cs or any of those other files in the source. Is this from an older version of the framework?

    Like

  24. Hi Le.. This is the best UOW / generic repo implementation I have seen.

    One question – How would you handle nested unitofworks?
    For example, a CustomerService is injected with an IUnitOfWork and some also injected with other service, ie LoggingService, which also gets a unitofwork. By design both services will have the same unitofwork instance (per http request).
    Any UnitOfWork.Saves that occur within the LoggingService will automatically commit pending updates from the CustomerService, which is not desirable. The only way around this I can think of is to define a second unitofwork interface (INestedUnitOfWork : IUnitOfWork) for the LoggingService that is injected with a different unitofwork instance.
    What are your thoughts?

    Thanks

    Like

    • Michael,

      There has been a lot of debate about unit of work scope like what you’re asking about. If your unit of work scope is at an http request level then it should only be committed at the end of the http request and not a second sooner, this is easily had with an action filter that automatically grabs the current unit of work and saves it.

      This approach doesn’t work for all however. If you intend to send back a response hinging on the result of said unit of work then you need to scope it to the service level such that each service receives its own unit of work to work with. This can have other side effects of course that I won’t go into to detail. If this is the approach you desire then you should be able to leverage your favorite di container to scope unit of work instances accordingly.

      Like

  25. Hi Le,

    I posted an answer to my post on March 14 on Friday, but my answer seems to have disappeared?

    Also, can you go into more in depth on the Object Query Pattern?

    Like

    • Hi Patrick, first and foremost, thanks for posting your implementation, I’m sure this will be valuable to other readers including myself.

      Over simplification of the Object Query Pattern implementation in the framework is reusable and chain-able query logic (predicates) leveraging predicate builder in LinqKit, here is a sample.

      Let me know if you have any specific questions.

      Like

  26. What are the advantages of using this framework? can anyone help me on how to understand the big idea? since the entity framework implement both “Unit of work” and ” repository pattern” … Thanks in advance.

    Like

    • EntityFramework, nHibernate, and pretty much all the ORM technologies out there usually implement their own flavor of the Unit Of Work and Repository Pattern, these patterns are almost required to build an ORM.

      Reasons listed here are high level, I won’t get into low level details because there is literally a ton of documentation out there for reasons why.

      • Minimize the surface are of your ORM technlogy in your application. When comes to to refactor you can do this in your repository later instead of everywhere in your application, service, Workflow, etc.
      • Address separation of concerns, CRUD should be in it’s own layer e.g. Repository
      • OOP 101, promote re-usability and portability. If all your CRUD is your presentation layer using EF directly, how is this reusable or consumable in anything else? e.g. If your building a front-end e-commerce application, and have a separate back-end to manage order fulfillment and this back-end is an ASP.NET or WPF app, you can’t re-use.
      • Compartmentalization, you don’t know where all your CRUD is in your system.
      • Abstraction, if you change a system-wide CRUD statement, you will need to refactor this everywhere it’s being used e.g. application, windows services, WPF, WorkFlow, etc.

      I can go on and on, however, again, there’s plenty of artifacts out there for this question.

      Abstracting from an ORM is a pattern or best practice, it’s up to you to decide whether or not to leverage it depending on your architectural use cases.

      Like

  27. Hi,

    Le, thank you for this great article! In my .NET projects, I have been using IRepository, IService, and UnitOfWork patterns. I usually have my UofW.Commit() called from within my Controller to logically batch changes.

    I was wondering if you could give me some advice for the following situation.

    1) Suppose your Update method if your Customer Service looked like this:

    public void Update(Customer entity)
    {
    _customerRepository.Update(entity);

    //remove key with matching key
    Cache.Remove(“customer_” + entity.Id.ToString());

    //update lucence index
    _luceneService.UpdateIndex(entity)
    }

    2) Supposed in your Controller, your Edit method looked like this

    ActionResult Edit(int id, CustomerModel model)
    {
    //grab customer entity from DB and update with properties from model
    var customer = …….

    _customerService.Update(customer);
    _someOtherService.DoSomething(); //some other service that will alter the database
    _unitOfWork.Commit();
    }

    Suppose that _someOtherService.DoSomething() causes an exception on Commit() and thus, the Customer changes are rolled back.

    However, the Cache Key has been already cleared out and Lucene has replaced the Customer Index with the altered values. Thus, the Lucene index has incorrect values and the Cache for this key was cleared out even though it didn’t need to be.

    In this situation, is it best to call _unitOfWork.Commit() within my services? Or is there a better solution?

    I would like to make my _unitOfWork.Commit() from within the Controller so that I have more control on when the Commit should occur.

    Thanks!

    Like

    • Hi Patrick,

      Most projects, we make it a design/pattern requirement that are Controllers are injected with IServices* and/or IUnitOfwork, none are injected with IRepository or IRepositoryAsync. This helps with business logic leaking into the presentation layer over time.

      Some teams like passing off “work” to the Services and it handle building up the work, when and where to commit. Other teams, prefer that the consumer of the different services manage building up the work, when and where to commit. I wouldn’t say there’s a wrong and right pattern, given a scenario, I’m sure one could justify why one of these patterns would make more sense than the other. Generally, I prefer the ladder, which is managing the unit of work outside the services, this gives the developer fine grained control of managing the unit of work, specially when dealing with batching (you mentioned), transactions and round trips to SQL Server.

      Like

    • Hi Le,

      I totally agree with you and prefer the latter, where the unit of work is managed outside the service. Given my code example above, how would you solve the issue that the Lucene index could be indexing the updated values even though the transaction was rolled back because of an exception during the commit?

      Like

    • Hi Patrick,

      Looking at this you may want to look at a simple implementation of the Memento Pattern (http://www.dofactory.com/Patterns/PatternMemento.aspx#_self1), this way you can revert to whatever the previous values that were in Lucene.

      Wrap the stuff your doing in your Action in a Try Catch (obviously make sure your Services throw exceptions if something goes wrong in any of them), in the catch you can have _unitOfWork.Rollback(); and this is where you might want to leverage the Momento Pattern, and have the CareTaker restore the previous Lucene cached entity in the catch.

      Like

    • Hi Le,

      I took a look at the Momento Pattern you suggested and although it would do the job, it would require quite a undertaking to implement in my current framework. So I decided to go a different route and hopefully I am recommending is a good solution.

      Given that the actions I want to perform after a commit don’t involve the database and just need to run, I decided to create a PostCommitManager that will be invoked after the _context.SaveChanges command in my UnitOfWork.Save function. This also assumes that I am using IOC to ensure that the PostCommitManager is the same instance for the HTTP request.

      Here is a quick implementation.

      1) public class PostCommitManager : IPostCommitManager
      {
      private Queue queue;

          public PostCommitManager()
          {
              queue = new Queue<Action>();
          }
      
          public void AddAction(Action action)
          {
              queue.Enqueue(action);
          }
      
          public void ProcessQueue()
          {
              try
              {
                  while (queue.Count != 0)
                  {
                      Action action = queue.Dequeue();
                      action();
                  }
              }
              catch {
                   //log exception
              }
          }
      }
      

      2) Within my CustomService, suppose

      public void Update(Customer entity)
      {
      _customerRepository.Update(entity);

      postCommitManager.AddAction(new Action( () =>Cache.Remove(“customer” + entity.Id.ToString())));

      _postCommitManager.AddAction(new Action( () => _luceneService.UpdateIndex(entity)));

      }

      3) From within a Controller, suppose

      ActionResult Edit(int id, CustomerModel model)
      {
      //grab customer entity from DB and update with properties from model
      var customer = …….

      _customerService.Update(customer);
      _someOtherService.DoSomething(); //some other service that will alter the database
      _unitOfWork.Save();
      }

      4) Within my UnitOfWork

      public void Save()
      {
      _context.SaveChanges();
      _postCommitManager.ProcessQueue();
      }

      Like

  28. Only one question let`s say that i make a deep loading of customer with all orders and then i want to save back the customer. How would you save the hole graph? I had problems with this, approuch the update method is updating the customers but adds duplicates of orders.
    Are you familiar with this problem? Thanks and great work.

    Like

  29. Hey Le, before everything thanks for what you have done in this framework, is awesome and a lot of time saving.
    I am using your work, but I am having an issue with the seed method in the configuration file for the migrations. In that seed method, I am using the AddOrUpdate extension method of the context, but base on that my entities inherit from the Entity class in the framework, same with my dbContext(inherits from DataContext), I have to set and ObjectState in order for the method seed to do something in the database, is there any work around with this?

    Like

    • Hi Daniel,

      Setting the IObjectState for every entity is a requirement for every entity in the graph, since we are abstracting from EF.

      Like

  30. How would I implement .Join in your repository? I see the .Include(), but I would also like .Join().

    Like

    • the repository is for only one entity by joining you create another entity type. Joining should be abstracted by relations and navigation properties.

      Like

    • Using Include will result in an outer join, and there are times when I want an inner join. So with include you already have multiple entities albeit relations. But join implies relations correct? I just need help adding the join method to the repository.

      Like

  31. Hello, there is an error in the code of the 3.2 version:

    public IEnumerable SelectPage(int page, int pageSize, out int totalCount)
    {
    totalCount = _repository.Select(_expression).Count();
    return _repository.Select(_expression, _orderBy, _includes, page, page);
    }

    should be:

    public IEnumerable SelectPage(int page, int pageSize, out int totalCount)
    {
    totalCount = _repository.Select(_expression).Count();
    return _repository.Select(_expression, _orderBy, _includes, page, pageSize);
    }

    I post a Issue in codeplex.

    Like

  32. Great work Le.

    Would really like to see an example of how you would manage “many to many” relationships in this scenario.
    Say, for example, with an existing Employee and an existing Territory – how would you manage inserting and removing records in the “EmployeeTerritory” table. What would you need in the Employee or Territory controller and how would you call that from the client?

    I use Kendo front end but don’t believe their framework has this functionality built-in.

    Thanks.

    Like

  33. Le,

    Great work here man, I really like how quickly it allows me to start working with the data. Your write ups and updates are even better it is great to see this is actively being worked on. I found this post when I was in search of a quick configure repository and I refer it to everyone I know now.

    I was wondering what your suggested implementation for working with the IdentityDbContext that comes with MVC 5 and its user tables. I edited the DbContextBase to inherit from the IdentityDbContext but things aren’t working as expected I am assuming due to the lack of IObjectState being implemented. Should I just keep the user context separate?

    Thanks, keep up the great work :)

    Like

    • I see you asked for example of code with something like this. I explained my setup, so here is a snippet of code I am using in my Seed method to create a user using the UserManager. It will not allow me to create the user because the IdentityUser does not implement IObjectState,

      protected override void Seed(MyContext context)
      {
      var userManager = new UserManager(new UserStore(new MyContext()));
      var roleManager = new RoleManager(new RoleStore(context));

              var tony = new ApplicationUser()
              {
                  UserName = "Tony",
                  Joined = DateTime.Now,
              };
      
              if (!roleManager.RoleExists("Admin"))
                  roleManager.Create(new IdentityRole("Admin"));
      
              if (!roleManager.RoleExists("User"))
                  roleManager.Create(new IdentityRole("User"));
      
              userManager.Create(tony, "password");
      
              context.Set<ProductCategory>().AddOrUpdate(new ProductCategory[]
              {
                  new ProductCategory(){ Id=1, Category = "House Hold"}, 
                  new ProductCategory(){ Id=2, Category = "Electronic" }, 
                  new ProductCategory(){ Id=3, Category = "Garage Sale" }
              });
      
              context.SaveChanges();
          }
      

      Like

    • I would also like to know about how this is done. By the default, MVC 5 template created this:
      public class ApplicationUser : IdentityUser
      {
      }

      public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
      {
          public ApplicationDbContext()
              : base("DefaultConnection")
          {
          }
      }
      

      Thanks :)

      Like

    • Hi Lee, you are doing a really great job!

      I have tried to integrate the suggested implementation with ASP.NET Identity but I have not been successful.

      I edited the ApplicationUser to implement IObjectState:

      public class ApplicationUser : IdentityUser, IObjectState {
      ……
      [NotMapped]
      public ObjectState ObjectState { get; set; }
      }

      Also, I modified my ApplicationDBContext:

      public class ApplicationDBContext : IdentityDataContext
      {
      static ApplicationDBContext ()
      {
      Database.SetInitializer(null);
      }

          public ApplicationDBContext () 
              : base("DefaultConnection") 
          { 
          }
      

      }

      public class IdentityDataContext : IdentityDbContext, IDataContext
      {
      // The same methods of DataContext
      }

      Like

    • Yes, will have all code checked-in (will full working coded ASP.NET MVC 5 example) with these patterns in place sometime tomorrow, a write-up of this shortly after.

      Like

  34. This is great!
    Good work. I have one question though. How can we effectively use asp.net Identity with this set up?
    Where to keep the identityModel.cs? in web.api project or move it to Data project?
    Because I am planning to have 2 projects, MVC5 as website and web api 2 for my rest services. So I dont want to duplicate the authentication module in both projects so I want to see if there is any good way to approach this

    Like

    • I have that question too. I am already busy with a project with the intention to use it as an example for all our ASP.NET MVC 5 projects within our company. At the moment I have put the ASP.NET Identity question on hold and first get used to the framework. But I would love to use ASP.NET Identity because the principles are exactly what I support.

      Like

    • Could one of you guys be so kind to post some code, in terms of the questions about how Identity will integrate with the framework?

      Like

    • I will try to make some time free this week to explain how it could integrate and what the current problem(s) are.

      Like

  35. Hi Le, I’m always looking to understand various perspectives. You’re approach seem to “just make sense” to me. I’ve implemented Julie Larman’s approach a al her pluralsight videos using bounded contexts and such.

    I love observing discourse and responses. I was wondering what you could provide with regards to Philip Haydon’s blog entry http://www.philliphaydon.com/2014/01/if-youre-going-to-use-repositories-dont-have-generic-or-base-repositories/ and compare his thoughts to what you’ve implemented.

    For me two big questions are, i have tables that do have composit keys or no keys at all (i.e., views), how do i handle that in your framework?

    The other is how/where would I make use of stored procedures(SPs)? In EF5 the work around was to make a custom class. I’ve read that EF6 is to make it easier but I haven’t need to apply that just yet but I do have a lot of SPs available for use.

    Hope this make sense and thanks for you’re material and look forward to more! Twitter: josequinonesii

    Like

    • Yes, there are definitely a lot of opinions out there on repos, so for v3.0 we are going to introduce a few features back by some common repo strategy patterns 1. CRUD commands with the Command Pattern, Queries with the Object Query Pattern and Queries with a variation of the Command Pattern as well.

      In my opinion, there are no absolute wrong and right in any of the variations (including the generic approach). Each of them bring their own goodness and caveats, therefore, were going to build them into the framework. For which ever pattern you prefer, generic or not, the framework will provide the means for you to select based on your use case and preferred architecture. This has been slated for for v3.x release, stay tuned!

      Like

  36. Hi Le,
    Thank you for the excellent post. I am trying the Generic Unit of Work and Repositories framework for a new project. i followed the steps in the video and it works prefect. Now I am changing a few views to Telerik Kendo UI Grid with Inline Editing. When editing an column value and press update I get in Repository.Update at _dbSet.Attach(entity) the error “An object with the same key already exists in the ObjectStateManager.”
    I know this happens when the Object is still tracked. But I don’t understand why in this case this is happening because when I do it via the Edit View (the one scaffolded) it works perfect.

    Is there a way i can get this fixed so i can work with Inline Editing in Kendo Grid?

    Thanks,
    Perry

    Like

    • The action code to Update in the Controller is:
      [AcceptVerbs(HttpVerbs.Post)]
      public async Task EditingInline_Update([DataSourceRequest] DataSourceRequest request, RawMaterialStock rawMaterialStock)
      {
      if (rawMaterialStock != null && ModelState.IsValid)
      {
      rawMaterialStock.ObjectState = ObjectState.Modified;
      _rawMaterialStockService.Update(rawMaterialStock);
      await _unitOfWork.SaveAsync();
      }

              return Json(new[] { rawMaterialStock }.ToDataSourceResult(request, ModelState));
          }
      

      Like

    • Hi Perry, could you be so kind to zip the solution up with database (could just be junk data) and upload to SkyDrive, Google Drive, Box or whatever you use. Because from what I can see, this use case definitely works, and has been implemented hundreds of time here at the company I’m at as well as other teams in the community. The only difference I can see is the Kendo UI DataSourceRequest attribute (which shouldn’t make a difference), we’ve always implemented this with straight raw REST calls or with OData.

      Like

    • I was already busy to make a little solution just to separate the problem from the whole project.
      It seems this was a good idea to do and I should have done it earlier, because as you expected, it just works also with the DataSourceRequest attribute. Even when I have an entity deeploading several other entities!

      So I went back to my project and starting to look from the beginning of this Controller and found a stupid mistake:
      My RawMaterialStock entity has a relation to a Source. I wanted to make that selectable in inline edititing via a combobox. I made a private async void PopulateSources() to load the Sources into ViewData[“sources”] and added this method in my constructor to load. When I remove the PopulateSources() call from ctor inline editing just works.
      I have to figure out how to get the selection via combobox working in inline editing but I am so very happy the basics work.

      Thank you very much for the support.

      Like

  37. Hi Le,

    How we can return a new anonymous type? I am using the following code.

    var childTypes = _unitOfWork.Repository()
    .Query()
    .OrderBy(o => o
    .OrderBy(ob => ob.ChildTypeID)
    .ThenBy(tb => tb.Name))
    .Filter(f => f.IsActive && f.ParentTypeID == parentTypeId && !string.IsNullOrEmpty(f.Name))
    .Select(i => i.ChildTypeID, i.Name)
    .Get();

            return childTypes;
    

    I need to select only ChildTypeID and Name.

    Thaks

    Like

    • This should be no different from how you do it in LINQ, think you are missing the “new” keyword, to new up the anonymous type.

      
      var childTypes = _unitOfWork.Repository()
      .Query()
      .OrderBy(o => o
      .OrderBy(ob => ob.ChildTypeID)
      .ThenBy(tb => tb.Name))
      .Filter(f => f.IsActive && f.ParentTypeID == parentTypeId && !string.IsNullOrEmpty(f.Name))
      .Select(i => new { ChildTypeId = i.ChildTypeID, Name = i.Name })
      .Get()
      
      

      Like

  38. I am following the steps in this tutorial and I get below error when I go to service project and try to create Service Class.

    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Clean.Data.Models;
    using Repository;

    namespace Clean.Service
    {
    public class OrderDetailService
    {
    private IRepository _OrderDetailRepository;
    public ClientService(IRepository oderDetailRepository)
    {
    _OrderDetailRepository = oderDetailRepository;
    }
    }
    }

    Error 2 The type ‘Clean.Data.Models.OrderDetail’ cannot be used as type parameter ‘TEntity’ in the generic type or method ‘Repository.IRepository’. There is no implicit reference conversion from ‘Clean.Data.Models.OrderDetail’ to ‘Repository.EntityBase’. C:\Users\aniketh\documents\visual studio 2012\Projects\TestSolution\Clean.Service\ClientService.cs 13 42 Clean.Service

    Like

    • Thanks!

      One question. so what is the best practice/steps when we make changes to database and want our models and mappers to get updated?

      Like

    • Not sure I have a recommendation for a best practice, however I can share what I and other teams have leveraged: T4 templates. T4 templates have been leveraged to generate POCOS (with inheriting EntityBase.cs), DTO’s, and even stubbed general base services.

      Like

    • The best practice I follow for model changes is to ensure my domain model and db model are ad close as possible in terms of naming conventions. I can then use an auto mapper that uses reflections to auto Map similar properties by convention. With that in place I can then just scaffold EF migration changes to make for an easy model change process.

      Of course this is little consolation for times when the db model has to diverge from the domain model. In such a case I will either decide to make a custom mapper implementation for the one type or the one new convention that will either map all elements of the model type or serve as a supplement to the auto mapper mentioned above.

      Like

    • Yes Le, If you can share your practice then I am at point give this approach a shot for one of my project :)

      Like

  39. Do you think that is correct to use return await query.ToArrayAsync(); in the GetAsync method?

    Like

    • Hi Carlos, I don’t know enough about your use case, for now, I don’t see why it wouldn’t be correct if you wanted to leverage async.

      Like

  40. Hi there. Since you moved the data-related folders around at the beginning of the video, what happens if the database metadata changes, and you have to update your POCO classes? Why not just update the T4 template to reflect these changes?

    Like

  41. Hi Le,

    How do I use GetPage() ??
    I tried
    var data = _unitOfWork.Repository().Query().GetPage(1, 10, out totalCount);

    but this will error out saying

    The method ‘Skip’ is only supported for sorted input in LINQ to Entities. The method ‘OrderBy’ must be called before the method ‘Skip’.

    Then i tried adding orderby before getpage but your orderby is Func<IQueryable, IOrderedQueryable> which means the input is iqueryable and cannot select a property.

    am i doing something wrong?

    Thanks
    zm

    Like

  42. thanks for your great article – how to use the repository to filter with more than one parameter plz give example, thanks in advance

    Like

  43. 不能在Youtube上观看你的Quick-Start Video,你能把这个Quick-Start Video文件放到你的Skydrive上面吗?这样我就可以下载观看了。谢谢!

    Like

  44. Hey, great article, thanks. I have the same error mentioned above when following the video about DataContext not being found. I have added the reference to Repository.Providers.EntityFramework but it can’t find it in there (resharper keeps trying to add a using for some linq library). I see in your downloadable sample it’s changed dramatically so I am trying to avoid this (as I am trying to learn by watching the video). Any advice?

    Like

    • Just to add some extra information – I didn’t download anything from your sky drive, I used the links you posted on the video and got my Repository project from that download (about 64mb).

      Like

    • Thanks for the positive feedback webnoob, and glad you got it working. I’ll update the CodePlex download to the latest version as well, thanks for the catch.

      Like

  45. Hello Le. Great of you to make a video, catering to the requests – cudos!

    I’ve been failing in my attempts at the below challenge, maybe you’ll have a clever thing or two to say about it:

    I’m recursively iterating a complex domain object, with nested domain objects and collections of nested domain objects, to take a look at setting the object states. Basically I’m looking at the objects and comparing them with a cached version.

    The recursive method takes a type DomainBaseObject. In reality it’ll receive a DomainClientObject or DomainCustomerObject or what have you.

    If the object is not in the cache, I’ll need to look for it in the repositories. So I’m doing this:

    public void SetObjectState(DomainBaseObject domainObject)
    {
    var foundObject = null;
    if (domainObject is DomainClientObject )
    {
    foundObject = unitOfWork.Repository().FindById(domainObject’s ID value);
    }
    else if (domainObject is DomainCustomerObject )
    {
    foundObject = unitOfWork.Repository().FindById(domainObject’s ID value);
    }
    else if (
    etc. etc. etc.

    That seems rather tedious; I have hundreds of different domain-objects. Is there a way I could call on a repository dynamically?

    Like

    • Thanks for harleydk for the positive feedback, to short answer to this is we think there maybe a solution to this, I’ve had a few quick chats with Tony Sneed in this regard https://twitter.com/LeLong37/status/401467254224601089, using his Trackable Entities Framework http://blog.tonysneed.com/2013/11/05/trackable-entities-version-1-0-released/ (video: http://vimeo.com/79489300) if you would like to get started first please keep us updated on the outcome.

      Like

    • Hello Le,
      alas I’m not working within a web context, Seems like a neat project, though.

      What would solve my issue – but that I’m not hardcore enough to dial in myself – would be a GetRepository(Type t) on the Unit of Work, so that one could call, for example, ‘Unit_of_work.GetRepository(DomainCustomerObject).

      I’m currently doing this to solve the issue, in my project which instantiates the unit of work …:

      private object FindInDatabase(DomainEntityBase domainObject, int idValue)
      {
      Type[] domainObjectType = { domainObject.GetType() };

      var repositoryType = typeof(Repository);
      IDbContext ctx = unitOfWork.GetContext(); // my own addition to the uow
      object p = Activator.CreateInstance(repositoryType.MakeGenericType(domainObjectType), ctx);

      Type t = p.GetType();

      MethodInfo method = t.GetMethod(“FindById”);
      Object retVal = method.Invoke(p, new Object[] { idValue });

      return (retVal == null ? true : false);
      }

      … but really it’s far-fetched, and feels far-fetched to look at, and steps on the toes of the unit of work.

      Like

    • So retrieving a Repository generically by passing in a domain entity is already implemented in the Framework.

      Reference:

      https://genericunitofworkandrepositories.codeplex.com/SourceControl/latest#main/Repository/UnitOfWork.cs

      
              public IRepository<TEntity> Repository<TEntity>() where TEntity : EntityBase
              {
                  if (_repositories == null)
                  {
                      _repositories = new Hashtable();
                  }
      
                  var type = typeof (TEntity).Name;
      
                  if (_repositories.ContainsKey(type))
                  {
                      return (IRepository<TEntity>) _repositories[type];
                  }
      
                  var repositoryType = typeof (Repository<>);
                  _repositories.Add(type, Activator.CreateInstance(repositoryType.MakeGenericType(typeof (TEntity)), _context));
      
                  return (IRepository<TEntity>) _repositories[type];
              }
      
      

      Example, finding by ID:

      
      var customer = _unitOfWork.Repository<Customer>().Find(id);
      
      

      Obviously I’m missing something here, could you be so kind to elaborate a bit more on the details of your use case?

      Like

    • Pseudo code (taken from your post):

      Not sure why you would need to do this, however here’s how it would look:

      
      private TEntity FindInDatabase<TEntity>(int idValue)
      {
      
          var repository = _unitOfWork.Repository<TEntity>();
          var entity = repository.Find(idValue)
      
          return entity;
      }
      
      

      Like

    • Hi Le,

      “Obviously I’m missing something here, could you be so kind to elaborate a bit more on the details of your use case?”

      I’d be happy to, and I’d like to thank you for your considerate nature,,

      I’m working on part of a project which involves a very complex database, big and with a huge set of relations. A couple of services might deliver into my project a complex domain-object, but with the caveat that it’s not possible to say, in advance, which number and of what kind the nested objects, and even collections of nested objects, will be.

      So I’m dealing with these complex objects recursively, to avoid having to maintain a huge set of conditions. The cost-benefit in performance is worth it. However; as I cannot tell in advance which type of domain entity I’ll be dealing with, I won’t be able to do…

      _unitOfWork.Repository().Find(id);

      … as I won’t know in advance that I’ll be dealing with the Customer entity. I do know it’ll be of a certain domain-base type.

      Perhaps it’s really simple and I’m just not seeing the forest for all the trees.

      Like

    • Gotcha, if this is the case, you may have already come up with the best solution. You may want to:

      1. Copy and paste Repository.cs and re-implement all the methods this way (with reflection vs generics with TEntity) by passing in and additional parameter in the constructor of type EntityBase or DomainEntityBase, for the reflection work you’ll have to do for each of the methods (just as you did for you FindInDatabase method), this way you’ll have all the Repository methods available as well.

      2. Add something like this to the UnitOfWork

      
              public object Repository(EntityBase entity)
              {
                  if (_repositoriesNonGeneric == null)
                      _repositoriesNonGeneric = new Hashtable();
      
                  var type = entity.GetType().Name;
      
                  if (_repositoriesNonGeneric.ContainsKey(type))
                      return _repositories[type];
      
                  _repositoriesNonGeneric.Add(type, Activator.CreateInstance(typeof(RepositoryNonGeneric), _context, entity));
      
                  return _repositoriesNonGeneric[type];            
              }
      
      

      Example:

      
      var entity = _unitOfWork.Repository(customer).Find(id);
      
      //or
      
      var repository = _unitOfWork.Repository(customer);
      var entity = repository.Find(id);
      
      

      Like

    • Thanks Le for the feedback, I’ll continue down the path of reflection methinks. Do you have a paypal donate thing, I wanted to send you a beer but would rather send you money for a beer! :)

      Like

    • I’ve added a PayPal donate button to the blog, thanks in advance for the beer, will definitely that to good use. If your ever in Dallas, TX, let’s grab a beer in person. I’ll also be at Microsoft Build 2014 in San Francisco, CA (http://www.buildwindows.com), maybe we can catch one there if you go.

      Like

  46. Le,

    the solution in the zipfile
    [ Unit of Work & Repository Framework with ASP.NET MVC, Entity Framework & Unity v3.0 (Quick-Start Video).zip ]

    doesn’t contain Repository project. can you please update the solution and upload?

    Thanks
    zm

    Like

  47. Happy New Year Le. Thanks for the video. It has been very helpful since all this is new to me. One thing I’ve tried to figure out unsuccessfully is how to refactor the DeepLoadCustomerWithOrders example to use the repository with Async. Can you give some advice on that and is it a best practice to do so?

    Like

    • Hi Hiep, happy belated New Years to you as well.

      This should get you started.

      
              public async Task<Customer> DeepLoadCustomerWithOrders(string id)
              {
                  var customer = await _customerRepository
                      .Query()
                      .Filter(t => t.CustomerID == id)
                      .Include(t => t.Orders.Select(u => u.OrderDetails))
                      .GetAsync();
      
                  return customer.FirstOrDefault();
              }
      
      

      Like

    • thanks for the help. i also owe you a beer. if you ever come down to new orleans, i’ll buy you a few

      Like

  48. Pingback: Lindermann's Blog | Unit of Work & Repository Framework with ASP.NET MVC 5, Entity Framework 6 & Unity 3

  49. Thanks for taking the time to make this video, Le. I especially enjoyed seeing the new IUnitOfWork object. I think it’s exactly what has been missing from EF (still waiting on an IDbContext interface!) and I know I’ll be using it from now on to separate persistence concerns from the repository layer, without awkward service layer manipulation.

    Like

  50. Pingback: Generically Implementing the Unit of Work & Repository Pattern with Entity Framework in MVC & Simplifying Entity Graphs | Long Le's Blog

Comments are closed.