locked
Good design pattern or approach when not using proxy classes RRS feed

  • Question

  • User-1833980242 posted

    We have an MVC project that has separate layers for the EF data layer, middle tier  and UI.  It uses ViewModels and the Repository Pattern, probably very typical.  Each section is it's own partial view that's getting data using asynchronous java script calls.  This application uses Entity Framework's Proxy Classes to get a lot of the data.  This is having a negative affect on the application because of the amount of data being returned to display a very small number of things.  

    For example, there is one grid that gets 3 values, each from a separate table.  These are essentially 3 strings being displayed in the grid - nothing complex.  I recently set a break point to see all of the data the proxies were returning.  There were around four hundred records being pulled by the proxy classes to get the 3 string values for each of the 7 records being displayed.  This is one example, but the same issue is probably very prevalent through out the application which accumulates to a lot of unnecessary data being pulled for each partial view.  Turning off the proxy classes breaks things because it's so dependent on them though.  I think this is essentially doing a lot of stuff that exceeds each unit of work for each partial view.

    There are probably a lot of places where linq projections could be used to only get the data that's needed.  There are also other small tweaks that can be done to improve things in the current application as well.  I want to know a better approach that could've been used from the onset that would've prevented this though.

    For example, if was to redo it, I've thought it would be better to not use the proxy classes and uses POCOs that defined everything instead.  This way I would have granular control over everything.  The idea of doing a domain driven design seems like it would offer similar benefits that would allow me to control things more.

    What are some of the common approaches used with Entity Framework, such as POCO's and Domain Driven Design, when the proxy classes aren't being used?  

    Monday, April 18, 2016 9:37 PM

Answers

  • User-821857111 posted

    There were around four hundred records being pulled by the proxy classes to get the 3 string values for each of the 7 records being displayed.
    If you were using plain ADO.NET, would you even consider writing "SELECT * From MyTable" to obtain data for this example? No? Nor would I. But it sounds like you are doing the equivalent behind the shield of an ORM. The vast majority of my EF queries use projections. And the first thing I do when starting a new EF-based web project is to disable proxies. There is no role for  lazy-loading in web applications.

    The idea of doing a domain driven design seems like it would offer similar benefits that would allow me to control things more.
    I don't use any formal approach like DDD. IMO, this is just a question of understanding your tools and what they are doing behind the scenes.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, April 19, 2016 7:19 AM
  • User-821857111 posted

    If you have a performance issue, it is not likely to be related to the use of Proxies per se, but more likely to result from sub-optimal SQL queries (e.g. fetching way too much data). You should use a profiling tool like the free Prefix which I wrote about a couple of weeks or so ago: Exploring Prefix: A Free ASP.NET Profiling Tool. It will help you narrow down the likely cause of performance bottlenecks much better than guess work. 

    Have you had situations where refactoring to use projections has created significant or at least very noticeable performance improvements? 
    I take a pragmatic approach to this. I create POCO classes for projections where the subset of fields I need from the table is quite a bit smaller than I would get by doing a SELECT *. If I need most of the fields, I don't bother projecting, unless doing that returns me nvarchar(max) or varbinary(max) fields that I don't intend to use. I can't remember the last time I had a performance issue related to data retrieval.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, April 19, 2016 10:06 AM
  • User-821857111 posted

    I put ViewModels in the UI layer. I use EF, so I don't create repositories. I have a service (business) layer that calls the context and contains LINQ queries. It  doesn't go into the UI layer. It is it's own layer. The Services interfaces also belong in that layer. They are the definition of (contract for) each service so that's why I feel they belong there. The ProductService, OrderService etc are implementations of the contracts. My data layer consists of the DbContext class, migrations and mapping classes for the context.     

    I have a Domain layer. That's where all my business entities and POCOs for projections go. 

    And, yes - I use AutoMapper.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, April 19, 2016 8:27 PM

All replies

  • User-821857111 posted

    There were around four hundred records being pulled by the proxy classes to get the 3 string values for each of the 7 records being displayed.
    If you were using plain ADO.NET, would you even consider writing "SELECT * From MyTable" to obtain data for this example? No? Nor would I. But it sounds like you are doing the equivalent behind the shield of an ORM. The vast majority of my EF queries use projections. And the first thing I do when starting a new EF-based web project is to disable proxies. There is no role for  lazy-loading in web applications.

    The idea of doing a domain driven design seems like it would offer similar benefits that would allow me to control things more.
    I don't use any formal approach like DDD. IMO, this is just a question of understanding your tools and what they are doing behind the scenes.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, April 19, 2016 7:19 AM
  • User-1833980242 posted

    You're exactly right about what's happening behind the shield of an ORM.  The developer that created this didn't consider the impact of this.  

    Are there other reasons besides the issues I face with proxies that you say "There is no role for  lazy-loading in web applications"?

    I don't use any formal approach like DDD. IMO, this is just a question of understanding your tools and what they are doing behind the scenes.

    Point taken about understanding your tools.  LINQ and projections are new to me and it sounds like I should put some effort into learning them.  Conceptually, the POCOs approach just seemed to make sense, possibly because of my background.

    I don't want to redo the data access layer and other parts of the application unnecessarily, but I also don't want to spend a lot time on an approach that doesn't solve the problem sufficiently.  Sharpening my skills with LINQ and projections to refine the queries may provide sufficient performance improvements.  I know the following is a very open ended question that's subject to a particular situation and not all situations are the same, but I want to get your opinion on the following.  

    The database used for this project really isn't all that big and there aren't a lot of users (1 - 4 users current max) for the application, so I suspect a lot of the issues come from the proxy classes.  There are more things that are going to be added to the application which is why I'm trying to figure this out now.  I want to have a good understanding of my options before jumping in head first with a solution though.  Have you had situations where refactoring to use projections has created significant or at least very noticeable performance improvements? 

    Tuesday, April 19, 2016 8:41 AM
  • User-821857111 posted

    If you have a performance issue, it is not likely to be related to the use of Proxies per se, but more likely to result from sub-optimal SQL queries (e.g. fetching way too much data). You should use a profiling tool like the free Prefix which I wrote about a couple of weeks or so ago: Exploring Prefix: A Free ASP.NET Profiling Tool. It will help you narrow down the likely cause of performance bottlenecks much better than guess work. 

    Have you had situations where refactoring to use projections has created significant or at least very noticeable performance improvements? 
    I take a pragmatic approach to this. I create POCO classes for projections where the subset of fields I need from the table is quite a bit smaller than I would get by doing a SELECT *. If I need most of the fields, I don't bother projecting, unless doing that returns me nvarchar(max) or varbinary(max) fields that I don't intend to use. I can't remember the last time I had a performance issue related to data retrieval.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, April 19, 2016 10:06 AM
  • User-1833980242 posted

    Thanks for the insight on your approach and suggestion for the free profiling tool.  I've been wanting to find a free one that's decent and will check it out. 

    I really appreciate your help and would like to get your opinion on a few more things.

    1. Where would you put the POCOs in the architecture below?
    2. Should the View Models be in the UI layer?
    3. Does the architecture below look good, other than the View Models possibly being in wrong layer?
    4. Do you use AutoMapper?

    Our app's layers are as follows:

    • Core (Data Layer)
      • EF Data Model
      • Repository Interfaces
    • Infrastructure (Middle Layer)
      • ViewModels
        • I think these are typically in the UI layer?
        • Put here to be closer to the data layer
          • The developer's personal preference was the reason for this location
      • Repository Classes
        • Inherits from Core Repository Interfaces
      • Services Interfaces 
    • MVC UI 
      • Services
        • Inherits from Infrastructure Services Interfaces
        • Business logic
        • Uses instances of the Infrastructure repository classes for CRUD operations
      • Controllers
        • Primarily just orchestrating work to be done by other classes
          • Serving up data from the services to the views
        • A very small amount of work is done in them 
          • Probably not ideal becuase it muddies the separations a little
      • Views

    Thanks again for your help!

    Tuesday, April 19, 2016 3:24 PM
  • User-821857111 posted

    I put ViewModels in the UI layer. I use EF, so I don't create repositories. I have a service (business) layer that calls the context and contains LINQ queries. It  doesn't go into the UI layer. It is it's own layer. The Services interfaces also belong in that layer. They are the definition of (contract for) each service so that's why I feel they belong there. The ProductService, OrderService etc are implementations of the contracts. My data layer consists of the DbContext class, migrations and mapping classes for the context.     

    I have a Domain layer. That's where all my business entities and POCOs for projections go. 

    And, yes - I use AutoMapper.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, April 19, 2016 8:27 PM
  • User-1833980242 posted

    Thanks for your help! I'm going to try a similar architecture to what you use on my next project.

    I'm curious about the your comment below and what type of application would be a good fit for lazy loading.

    "There is no role for  lazy-loading in web applications."

    Friday, April 22, 2016 1:12 PM