0

I am writing a Blazor (server side) app and have come to the conclusion that I want change tracking on for CrUD operations and off for cRud operations.

Should I create two DbContext classes, one that returns a DbContext with change tracking on and the other with it off? This would have both pointing to the same DB.

Or is it better to have a single DbContext class that has change tracking on. And then when I need data just to display it, I use context.Books.AsNoTracking()... to turn it off for that query.

Why

I figure change tracking makes sense for CrUD operations for two reasons. First, because that will avoid bugs due to my forgetting to call Add() someplace where needed. Second, because Update() is heavy handed re-writing everything while change tracking only writes what has changed.

I figure no tracking makes sense for cRud operations because it removes the overhead of change tracking when nothing is going to change. And it's safe as I will do this only for web pages that are essentially read only views of information.

So keep it safe & simple while gaining performance for the cRud case.

Two DbContext

I haven't tried it yet but I assumed I can make the following call and somehow then select the context I want. I don't know if this is possible and that's part of what I'm asking here.

builder.Services.AddDbContextFactory<LouisHoweDbContext>( options =>
    options.UseSqlServer( builder
        .Configuration
        .GetConnectionString("LouisHoweDb")
    )
    .EnableSensitiveDataLogging()
);
    
builder.Services.AddDbContextFactory<LouisHoweDbContext>( options =>
    options.UseSqlServer( builder
        .Configuration
        .GetConnectionString("LouisHoweDb")
    )
    .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
    .EnableSensitiveDataLogging()
);
David Thielen
  • 28,723
  • 34
  • 119
  • 193
  • _"and have come to the conclusion that I want change tracking on for CrUD operations and off for cRud operations."_ - I'd like to know how you came to that conclusion... – Dai Mar 24 '23 at 18:02
  • _"Should I create two DbContext classes, one that returns a DbContext with change tracking on and the other with it off?"_ - A `DbContext` cannot "return" a `DbContext` - do you mean something like `IDbContextFactory`? – Dai Mar 24 '23 at 18:02
  • you can use the same DB context, make a Base class that implements CRUD operations for both read-only and read/write, and use each of them in the place you want, you can add `.AsNoTrack()` for each query that you only want to read via and the others without it. – odaiwa Mar 24 '23 at 20:00
  • @Dai I added to the question to answer your two questions. Please let me know if/where I am off base. TIA – David Thielen Mar 24 '23 at 23:41
  • What do you mean by this: _"Second, because `Add()` is heavy handed re-writing everything while change tracking only writes what has changed."_? What makes you think `DbSet.Add` is expensive? – Dai Mar 24 '23 at 23:49
  • Your posted code (with `AddDbContextFactory`) won't work: you can't register multiple factories for a single service type. – Dai Mar 24 '23 at 23:52
  • @Dai Sorry, I meant `Update()`, not `Add()`. I'll fix it. – David Thielen Mar 24 '23 at 23:52
  • @Dai Ok, so only one DbContext then. But I'm confused, if I create the Blazor template with it putting in all the Authentication & Authorization code, isn't it adding a 2nd DbContext for its user & roles database? – David Thielen Mar 24 '23 at 23:54
  • @DavidThielen Can you link to an example of the authX (authentication+authorization) code that you're seeing in the template? – Dai Mar 25 '23 at 00:01
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/252762/discussion-between-david-thielen-and-dai). – David Thielen Mar 25 '23 at 00:07
  • If you want to have 2 DbContexts: https://stackoverflow.com/questions/75349449/ef-core-multiple-dbcontext-with-one-database/75351587#75351587 – spyros__ Mar 25 '23 at 12:50
  • @spyros__ If you post that as an answer, I'm happy to select it. And I think this question differs a bit from the one you referenced as that was about extending to add in the security data. And the answer here (I assume) would be two DbContext's, not use AsNoTracking(). Thank you for the help. – David Thielen Mar 25 '23 at 19:17
  • @DavidThielen You are welcome! Exactly, the solution would be to have 2 DbContexts, so you can have the default AsNoTracking to one of them. Also, with that approach you can also have different models for the reads, if that's something that helps you in another part of your application. Tell me if i should include the above to my answer, so it will be completed if someone has a similar question and comes here. – spyros__ Mar 26 '23 at 17:30
  • @spyros__ Please do write all of this up in an answer and I will be happy to accept it. Thanks. – David Thielen Mar 26 '23 at 17:59

1 Answers1

0

You can use 2 DbContexts: EF Core: Multiple DbContext with one Database so you can have the default AsNoTracking to one of them. Also, with that approach you can also have different models for the reads, if that's something that helps you in another part of your application.

spyros__
  • 1,311
  • 6
  • 8