1

I'm using the repository pattern as the way to access the DbContext in my C# application, however, I have a report that generates an expensive query (actually several queries) because of relationships (and poorly written code).

Then I created a Stored Procedure that returns exactly what the report needs, without any extra field, so I can fill the current entities and navigation properties.

In this case, what should be the way to go? Create a new entity/repository just for this report?

2
  • The repository pattern is an in-memory representation of your business domain. Is this a good fit for what you're trying to do? (Offhand, I don't see why you would treat this any differently than your other data access operations) – Robert Harvey Aug 12 '16 at 14:30
  • The stored procedure gives you a report. Treat it like a report. Read it, display it. Don't try to make changes to it and get it updated. If that's what you want to do you need to load up your model and make your changes in that. – candied_orange Aug 12 '16 at 15:20
1

Create a new entity/repository just for this report?

New entities, yes, repository, no. But I come to this answer from a slightly different perspective:

I think it's always a good idea to have a separate DbContext subtype for reporting. This specialized context can be optimized for performance by making it read-only:

  • Turn off lazy loading and creation of proxies:

    context.Configuration.ProxyCreationEnabled = false;
    
  • Turn off change detection:

    context.Configuration.AutoDetectChangesEnabled = false;
    
  • (Maybe) turn off validation:

    context.Configuration.ValidateOnSaveEnabled = false;
    

    But that would only be useful if there's a chance that inadvertent SaveChanges calls will be made.

  • Disable saving changes by overriding the SaveChanges method without calling base.SaveChanges.

Besides that, if the context also exposes DbSet<T> properties, you should use them with AsNoTracking(), which will prevent entities from being change tracked.

If you have such a context, it's more obvious to use it with specialized entities, not the entities that belong to the other, business-related context(s). This can be entities that exactly capture the result of a stored procedure. It's also possible to populate multiple entities by one stored procedure.

W.r.t. repositories -- I'm not a fan of them anyway. Repositories, when used with EF, should be generic repositories. Generic repositories don't contain any type-specific methods, so they always end up being a thin (i.e. virtually useless) wrapper around DbSets. You may as well work with DbSets directly (or with the output of stored procedures).

One other thing to mention: even with these optimizations, EF is not the fastest tool to read data from a database. You may want to look at Dapper.

5
  • Just don't optimize before it is necessary. EF leads to infinitely more maintainable code. Use Dapper sparingly, and only then after substantial benchmarking. – Aluan Haddad Apr 7 '17 at 17:06
  • @AluanHaddad I happened to return here after a long time and I wonder what you mean. The idea of EF is to have a very small amount of maintainable code. You say "more", but it's not clear as compared to what. – Gert Arnold Jun 17 '20 at 7:30
  • I meant that it is easier to write maintainable code when using Entity Framework as compared to Dapper. – Aluan Haddad Jun 17 '20 at 19:27
  • Ah, the subtleties of adjectives and adverbs! – Gert Arnold Jun 17 '20 at 19:31
  • Indeed. Syntax can not resolve such an ambiguity. Looking back at the topic at hand, I should clarify that I feel that it is perfectly possible to write maintainable code using Dapper but one has to be careful and deliberate to do so. – Aluan Haddad Jun 17 '20 at 19:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.