I have a problem with EF not returning the newest data in a 3 layered WPF application, and I suspect it has something to do with how I handle the lifetime of my context. This is the scenario:
There are several repositories wrapped inside a UnitOfWork. There is also one service (MyService), which uses the UnitOfWork. This UnitOfWork must also be called from the UI directly, without passing through a service.
In the ViewModel of my main window at some point I create a new window (using ViewModel first):
var dialog = new DialogViewModel(_eventAggregator, _unitOfWork, Container.Resolve<CarService>());
This main window ViewModel has a UnitOfWork, which has been injected in the constructor, and that is passed to the DialogViewModel.
CarService's constructor also needs a UnitOfWork, which is also injected in its constructor:
public CarService(IUnitOfWork unitOfWork){
_unitOfWork = unitOfWork;
}
When CarService is used in DialogViewModel to make a query to retrieve some data and make some updates, it works fine the first time. However, when the same query is made the next time to retrieve that data, instead of returning the newest modified one it returns the old/cached one. The query using UnitOfWork (inside CarService) looks like this:
var values = _unitOfWork.GarageRepository.GetSomeValues();
_unitOfWork.GarageRepository.MakeSomeChangesToTheValuesUsingStoredProcedure();
The second time this is called, values doesn't contain the newest version of the data; however it has been updated successfully in the DB.
I'm doing DI using Unity, and this is how my container looks like:
public class Container
{
public static UnityContainer Container = new UnityContainer();
// Called once in the AppBoostraper, as soon as the GUI application starts
public void BuildUp()
{
Container.RegisterType<IUnitOfWork, UnitOfWork>();
Container.RegisterType<ICarService, CarService>();
}
}
Why isn't the right data being returned, and how can I fix it?
I finally found the problem, which had to do with my management of the unitOfWork/dbcontext lifecycle.
I was loading some entities, then updating them with a stored procedure (so the entities in the code were not up to date anymore), and then loading the queries again; at this point EF was getting the values from the cache rather than from the DB.
I found two ways of fixing this:
A rather "hacky" one, force the entities to reload:
Context.Entry(entity).Reload();
Encapsulate the unitOfWork usage with a using, so that the context is disposed at the end of each transaction and thus getting fresh data the next time. I think this is more in line with what the UnitOfWork is meant for and feels more robust to me. I've also wrapped the UnitOfWork in a factory, so now that gets injected in the constructors.
using (var uOw = new unitOfWorkFactory.GetNew())
{
// make the queries
}
The default LifetimeManager for Unity is the TransientLifetimeManager, which means you get a new instance each time it resolves (including when injected). So given your registrations, you'll get a new CarService, with a new instance of a UnitOfWork each time you call Resolve(), and a new, different instance injected into your main window ViewModel.
So your ViewModel gets a UoW, the CarService gets a separate UoW, and updating one will mean the other is now out of date due to caching.
What you need to do is set up a LifetimeManager for the context that has appropriate scope, or defer to a factory. Unity doesn't have that many LMs built in, but the LifetimeManager class is basically a glorified map (has a Set, Get, and Remove method essentially).
I don't know enough about WPF and its lifetimes to suggest an implementation. Maybe it can be singleton (which will keep the same context the entire time the program is running), maybe it can be backed by a thread's CallContext.
Your other option is to pass along the UoW instance when you resolve the CarService by calling Container.Resolve<CarService>(new ParameterOverride("unitOfWork", _unitOfWork)). That'll keep the lifecycle management tied to the lifetime of the main window ViewModel. However, this approach has problems because your VM class knows a little too much about the CarService (notably, that it has a UoW in it).
Related
I want to use same technology to access my database both from ASP.NET MVC and WPF and decided to use EF Core.
In ASP.NET I can inject DbContext(UnitOfWork, AppBLL etc) into Controller and its lifecycle is scoped to request/response operation. As I understood the scope is created behind the scenes using ASP.NET middleware pipeline.
In WPF however scope must be defined based on the app use case which is completely logical since some times there is need for long operation (for example using DbSet.Local.ToObservableCollection() and DataGrid) and sometimes operation is more trivial (for example update one entity).
I want to achieve somewhat similar behavior to ASP.NET MVC in WPF, basically I want to inject DbContext into ViewModel constructor and then each method to be its own scope thus have different short-lived DbContext each method call.
I use Microsoft.Extensions.DependencyInjection and CommunityToolkit.MVVM for DI and add DbContext using AddDbContext. This makes it scoped but without defining the scopes it is effectively singleton. I do not want to define scope with using(var scope = ...) and GetRequiredService each time I make a db operation since it will pollute my code.
As I said I want it to be sleek like in ASP.NET.
So I tried aspect oriented programming with PostSharp but feels kinda dull to add attributes to each method that uses DbContext also there are concerns about testability.
I tried implementing abstract class which has methods to which lambda with operation is passed and lambda is created inside a using(var scope = ...) expression and thus uses scoped DbContext. At the disposal of the scope DbContext is automatically disposed with it.
These approaches however are still distant from ASP.NET mechanism and
I want DbContext lifecycle to be managed smarter.
If I define DbContext as transient then it is only created on injection into ViewModel and not re-created for methods.
By the way, do I understand correctly that in ASP.NET when DbContext is injected into Controller it is disposed right after the construction, since the scope is finished?
EDIT:
Here is a link to example project Github repository
https://github.com/anguzo/ef-core-in-wpf-example
WpfApp project is example of the problem - you can't update same entity twice since it's already being tracked.
Other WPF projects demonstrate different solutions to this problem I came up with.
The closest to the ASP.NET behavior is using PostSharp custom attribute. It requires attribute to be applied to ViewModel class and modifies each method(excluding "special methods": getters, setters and consturctors).
I am still lost since official Microsoft documentation and other materials on the Internet do not describe proper solution to this problem.
The dependency injection container is an instance class.
With mvc there is a request pipeline that provides the parameters of anything instantiated by it from that container.
The difference between mvc and wpf is that with wpf you don't have that pipeline so you need to provide the container instance somehow whenever you instantiate a class you want anything injected to.
It's covered pretty well here:
https://learn.microsoft.com/en-us/windows/communitytoolkit/mvvm/ioc
You do not want everything to be a singleton and you do not want to resolve the entire object graph as you crank up your application.
As you spotted, that's impractical anyhow because you want some things to be transient.
Passing the DI container around is a nuisance. You might have any number of layers down to your dbcontext.
What is usual is to make the injection container available throughout the app.
In the code there, they've added a property to App to stash that instance in:
public sealed partial class App : Application
{
public App()
{
Services = ConfigureServices();
this.InitializeComponent();
}
/// <summary>
/// Gets the current <see cref="App"/> instance in use
/// </summary>
public new static App Current => (App)Application.Current;
/// <summary>
/// Gets the <see cref="IServiceProvider"/> instance to resolve application services.
/// </summary>
public IServiceProvider Services { get; }
App.Services is your dependency injection container. The magic bag you grab your instances out of.
Where these services are registered they're all singletons there, but your dbcontext should be
services.AddTransient<IMyDbContext, MyDbContext>();
And your repository would take an IMyDbContext in it's constructor which would be supplied out the container.
You need to reference that container exposed by App to resolve an instance:
var repo = App.Current.Services.GetService<IRepository>();
Because it's on App.Current, everywhere in your code will be able to reference it. So long as you have a regular wpf entry point.
Your repository would get an instance of dbcontext via injection and you'd so whatever you're doing with that repository. Once it goes out of scope the repository and dbconnection would be ready for garbage collection so long as they're both Transient.
Transients will be disposed after they go out of scope. Hence if you pass a transient dbcontext down from a mvc controller then it will stay in scope until the response is sent from the controller. It's only going to be torn down after the controller's returned it's result and goes out of scope.
The aspect of the code which I would change is to add an abstracted facade around the di container. You want to be able to moq whatever grabs a class instance out that container if you use it within any classs. If you use app.current in unit testing then you need to instantiate an application object.
What Andy outlines is pretty much what I use, it's commonly referred to as a Service Locator pattern, and has a bit of a reputation as an anti-pattern, but for WPF it is pretty effective if you have some discipline within your team about where and how it is allowed to be used.
I'd recently written a quick snippet on using the ServiceLocator pattern and lazy dependency properties with Autofac which can provide some ideas on how the pattern can be applied:
private readonly IContainerScope _scope;
private ISomeDependency? _someDependency = null;
public ISomeDependecy SomeDependency
{
get => _someDependency ??= _scope.Resolve<ISomeDependency>()
?? throw new ArgumentException("The SomeDependency dependency could not be resolved.");
set => _someDependency = value;
}
public SomeClass(IContainer container)
{
if (container == null) throw new ArgumentNullException(nameof(container));
_scope = container.BeginLifetimeScope();
}
public void Dispose()
{ // TODO: implement proper Dispose pattern.
_scope.Dispose();
}
This gives you a pattern gives you a default lifetime scope for the life of a top-level dependency which could be a MVVM ViewModel, and/or navigation provider, etc. so your dependencies can be managed by Transient, Singleton, or PerLifeTimeScope. (Suited to something like the EF DbContext) So for instance when a form is loaded the DbContext instance can be resolved for the lifetime of that form.
I call the pattern a lazy property pattern as the actual dependency is resolved only if/when it is accessed via the property. The advantage of this is when writing unit tests with classic constructor injection, you need to mock every dependency for every test, where with "lazy" properties you use the Setter for just the dependencies you need. The initialization of the class under test accepts a mocked container that simply throws an exception to fail the test if it's Resolve<T> method is called. (No need to build a functional mock container for tests to resolve mocked dependencies or other such complexity)
The caveat of this pattern, and one suggestion to work with the team on to check is that the _scope reference should only be accessed from the dependency properties, not willy-nilly through the code to resolve dependencies ad-hoc. For instance if a new dependency is needed, declare the property accessor to resolve via the scope rather than just writing a _scope.Resolve<NewDependency>() in the code. While you can still test around such code, you'd need to set up your tests to provide a _scope capable of resolving a Mock, which is honestly messy. Following the property pattern makes testing a lot simpler to provide the expected dependency via the Setter and getting an exception/failure if an unexpected dependency happens to get accessed.
It's not proper-C#-Lazy, though I do use a proper Lazy dependency pattern for injected dependencies, and web projects where the lifetime scope is conveniently managed:
private readonly Lazy<ISomeDependency>? _lazySomeDependency = null;
private ISomeDependency? _someDependency = null;
public ISomeDependency SomeDependency
{
get => _someDependency ??= _lazySomeDependency?.Value
?? throw new ArgumentException("SomeDependency dependency was not provided.");
set => _someDependency = value;
}
public SomeClass(Lazy<ISomeDependency>? someDependency = null)
{
_lazySomeDependency = someDependency;
}
Autofac does support lazy initialization so this pattern means that for normal execution, Autofac provides the properties as Lazy references which will resolve if/when they are accessed. For unit tests, you just initialize with an empty constructor and use the Setters to set the dependencies you expect to actually be used. The above example with 1 dependency doesn't really demonstrate the value of that, but picture a test suite for a class that has 8 or 12 dependencies where a method under test will likely only touch a couple of them.
I am using Ninject
I have a class which I am using to hold & build some cached data if needed. It is set up in my Niject binding as follows
kernel.Bind<IConsistencyCheckCacheHelper>().To<ConsistencyCheckCacheHelper>().InSingletonScope();
The Class has some required dependencies injected into it the first time that the class is created, then that same instance is inject every time.
But in the case that the data needs to be rebuild I need run time dependency injected.
I am using this as a application wide cache,
Any ideas how to do this?
The Class has some required dependencies injected into it the first time that the class is created, then that same instance is inject every time.
The class has been registered with Ninject as a singleton. That means that the first time Ninject resolves an IConsistencyCheckCacheHelper it will create an instance of ConsistencyCheckCacheHelper, and then it will use that same instance over and over again.
So Ninject isn't injecting the same instance of a dependency into ConsistencyCheckCacheHelper over and over. It's only creating one instance of ConsistencyCheckCacheHelper, so whatever instance of the dependency gets injected into it won't change either.
If you want the dependency within used by ConsistencyCheckCacheHelper to change each time it's resolved then you can't register it as a singleton. You would need to use a different scope.
.InTransientScope() (the default) means that every time a type is resolved a new instance is created.
.InRequestScope() means that a new instance is created for every web request.
It's still a tiny bit more complicated than that. For example, if ConsistencyCheckCacheHelper is registered as transient, a new instance is created each time. But if it depends on something else and that dependency is registered as a singleton, each new instance of ConsistencyCheckCacheHelper will receive the same singleton instance of that dependency.
It's often recommended that we start off with transient dependencies. Unless we specifically need to reuse an instance, the cost of creating new objects likely isn't that great. For a web application, InRequestScope is likely safe. I'd only use singleton scope if I'm sure that I can safely reuse one instance of that class along with one instance if its dependencies and their dependencies and so on.
Ninject object scopes
This may not be the best way to do this but it works, Create 2 Interfaces that represent the same class
public interface DepInterfaceOne
{
int MethodWithCachedData();
void InfoRequiredForAtRunTime(object RunTimeObject);
}
public interface DepInterfaceTwo: IConsistencyCheckCacheHelper
{
}
And Set up your binding in this way
kernel.Bind<DepInterfaceOne>().To<DepInterfaceOneClass>().InSingletonScope();
kernel.Bind<DepInterfaceOneTwo>().ToMethod(a =>
{
DepInterfaceOne toReturn = kernel.Get<DepInterfaceOne>();
toReturn.InfoRequiredForAtRunTime(HttpContext.Current.Session["InfoRequired"]);
return toReturn;
});
I am trying to figure out how to get a new lifetime scope each time I resolve an instance from the container. I would like to do this without the depending component needing to know about Autofac.
I'm creating a .NET Core server application (console app) which has a "master server" (IMasterServer) component and zero or more "session server" (ISessionServer) components. Both the master and the session servers have their own IMessageBroker dependency. The master server will create a new session server whenever it gets a message from the message broker.
The catch is that each session server instance needs its own IMessageBroker, and I don't think I can use InstancePerDependency() because other sub-components of ISessionServer will also need to access the IMessageBroker so the message broker needs to be single instance within the scope of a session. So my thinking is that when the master server spawns a new session, it should do so within a new lifetimescope, and I can register the IMessageBroker dependency using InstancePerLifetimeScope().
So, the question is, how can I inject an ISessionServer factory into IMasterServer such that each time that factory is called, a new lifetime scope is created for the resulting ISessionServer instance? And how can this be done such that none of the components need to know about Autofac?
These two SO questions both suggest using the Owned<T> relationship:
Can I create an implicit Lifetime scope within a factory?
Is it possible to create a new scope whenever a component is resolved?
However, unless I'm missing something, that means that the component into which the dependency will be injected (IMasterServer in my case) needs to know about Autofac, because its ctor signature must include the Owned<T> type.
What I have so far:
using Autofac.Features.OwnedInstances;
class MasterServer : IMasterServer
{
private IMessageBroker mMessageBroker;
private Func<Owned<ISessionServer>> mSessionServerFactory;
public Master(
Func<string, IServerMessageBroker> messageBrokerFactory,
Func<Owned<ISessionServer>> sessionServerFactory
)
{
mMessageBroker = messageBrokerFactory("master");
mSessionServerFactory = sessionServerFactory;
}
}
class SessionServer : ISessionServer
{
private IMessageBroker mMessageBroker;
private string mId;
public SessionServer(
Func<string, IMessageBroker> messageBrokerFactory
)
{
mId = Guid.NewGuid().ToString();
mMessageBroker = messageBrokerFactory(mId);
}
}
You can see that the MasterServer concrete class needs to use the Autofac.Features.OwnedInstances namespace in order to define the session factory using the Owned<T> relationship type.
How can I use Autofac to create a new lifetime scope each time ISessionServer is resolved through the factory injected into the MasterServer, without the components needing to know anything about the specific DI container in use?
I always felt that letting Autofac-specific code slip onto factory classes is the less of two evils.
So, if I was in you, I would just use the Owned<T> class, call it a day and move on. It's an excellent solution and keeps all the disposing of every component automagical as always with Autofac.
Just remember to call Dispose or your owned SessionServer when needed, or you will leak resources.
AFAICT the Autofac approach doesn't let you write 100% DI free code. So you need to reference it, someway, somewhere.
A single reference to include Owned<T> seems a pretty acceptable trade off.
Let me point out a problem in your design (or in the part you included): there is no simple way to link a ISessionServer into a disposable scope.
E.g: you expose a factory class, and then the SessionServer is out on his own.
Managing scopes in this way becomes hard.
A cleaner approach is to use a Disposable into a using statement:
using (var sessionServer = sessionFactory.GetServer())
{
// do something with sessionServer.
}
I have the basics down of dependency injection but where I'm struggling is trying to put it together properly in an MVC API C# application using Unity. The issue I have is that I will have a controller that has a method, and in that method it will have say two objects. One of these objects will have a dependency on a data access layer and the other doesn't. I'm not quite sure on exactly how to set this up.
Lets say I have a controller with the following method that gets users from a search object. It also uses a SearchParameters object to perform the search. If you search with no name you get all results, or if you put a name you get any users with that name.
public Users[] GetUsers(string name) {
Company.SearchParameters searchParams = new Company.SearchParameters(name);
Company.UserSearchService searchService = new Company.UserSearchService(searchParams);
return searchService.Search();
}
This is of course a super simplified version but in this case UserSearchService in the Search method is doing an explicit database call. So I know that is a dependency I'd have to give it. SearchParameters really is just a class that holds data.
Here is where I'm not sure on exactly what to do next. The Controller itself doesn't have a dependency but since UserSearchService does I'm not sure how using unity I properly set that up and take into account runtime values for the constructor. I'm also not sure if SearchParameters is supposed to be considered a dependency or not.
Additionally SearchParameters and UserSearchService do not have any sort of backing interface if that matters and there are other methods on this controller that interact with other classes that have a similar need of a data access layer dependency such as perhaps Company.UserAccount.
The search parameters shouldn't be part of constructor; it should be part of the "Search" method. The SearchParameter object should not even be known outside of the UserSearchService class (Encapsulation). There should be some refactoring as neleus suggested. At the very least, to get things going, it should be refactored to something similar this:
public Users[] GetUsers(string name) {
// Or however you end up with your UserSearchService object.
// Ideally as an interface and an injected dependency...
Company.UserSearchService searchService = new Company.UserSearchService();
return searchService.Search(name);
}
Company.UserSearchService:
public Users[] Search(string name) {
// A factory would be a better option. This should also be an interface.
Company.SearchParameters searchParams = new Company.SearchParameters(name);
// Your logic here
}
I see here two tasks. The first is a refactoring where static dependencies have to be replaced with interfaces. The second task is to register your stuff in IoC container.
For the first task a minimum you need is to replace all references to Database in your UserSearchService with IDatabase interface (so that it can also be mocked) and allow it to be passed to constructor (constructor injection). To be able to provide an instance of IDatabase to the service you have to create the same dependency for the controller (again constructor injection). Then register the IDatabase implementation as shown in this post.
Update
I agree that dependency has to be removed from the controller. As you #Topojijo have suggested a factory for the UserSearchService can be used in this case. Guessing you have several cervices you need to make a factory for each and there may be an overhead if their count is large. In such case it's better to resolve the service directly from Unity container and move the searchParams to Search method:
public Users[] GetUsers(string name) {
Company.SearchParameters searchParams = new Company.SearchParameters(name);
Company.UserSearchService searchService = container.Resolve<Company.UserSearchService>();
return searchService.Search(searchParams);
}
Currently we have implemented a repository pattern at work. All our repositories sit behind their own interfaces and are mapped via Ninject. Our project is quite large and there are a couple quirks with this pattern I'm trying to solve.
First, there are some controllers where we need upwards of 10 to 15 repositories all in the same controller. The constructor gets rather ugly when asking for so many repositories. The second quirk reveals itself after you call methods on multiple repositories. After doing work with multiple repositories we need to call the SaveChanges method, but which repository should we call it on? Every repository has one. All repositories have the same instance of the Entity Framework data context injected so picking any random repository to call save on will work. It just seems so messy.
I looked up the "Unit Of Work" pattern and came up with a solution that I think solves both problems, but I'm not 100% confident in this solution. I created a class called DataBucket.
// Slimmed down for readability
public class DataBucket
{
private DataContext _dataContext;
public IReportsRepository ReportRepository { get; set; }
public IEmployeeRepository EmployeeRepository { get; set; }
public IDashboardRepository DashboardRepository { get; set; }
public DataBucket(DataContext dataContext,
IReportsRepository reportsRepository,
IEmployeeRepository employeeRepository,
IDashboardRepository dashboardRepository)
{
_dataContext = dataContext;
this.ReportRepository = reportsRepository;
this.EmployeeRepository = employeeRepository;
this.DashboardRepository = dashboardRepository;
}
public void SaveChanges()
{
_dataContext.SaveChanges();
}
}
This appears to solve both issues. There is now only one SaveChanges method on the data bucket itself and you only inject one object, the data bucket. You then access all the repositories as properties. The data bucket would be a little messy looking since it would be accepting ALL (easily 50 or more) of our repositories in its constructor.
The process of adding a new repository would now include: creating the interface, creating the repository, mapping the interface and repository in Ninject, and adding a property to the data bucket and populating it.
I did think of an alternative to this that would eliminate a step from above.
public class DataBucket
{
private DataContext _dataContext;
public IReportsRepository ReportRepository { get; set; }
public IEmployeeRepository EmployeeRepository { get; set; }
public IDashboardRepository DashboardRepository { get; set; }
public DataBucket(DataContext dataContext)
{
_dataContext = dataContext;
this.ReportRepository = new ReportsRepository(dataContext);
this.EmployeeRepository = new EmployeeRepository(dataContext);
this.DashboardRepository = new DashboardRepository(dataContext);
}
public void SaveChanges()
{
_dataContext.SaveChanges();
}
}
This one pretty much eliminates all the repository mappings in Ninject because they are all instantiated in the data bucket. So now the steps to adding a new repository include: Create interface, create repository, add property to data bucket and instantiate.
Can you see any flaws with this model? On the surface it seems much more convenient to consume our repositories in this way. Is this a problem that has been addressed before? If so, what is the most common and/or most efficient approach to this issue?
First, there are some controllers where we need upwards of 10 to 15 repositories all in the same controller.
Say hello to Abstract factory pattern. Instead of registering all repositories in Ninject and injecting them to controllers register just single implementation of the factory which will be able to provide any repository you need - you can even create them lazily only if the controller really needs them. Than inject the factory to controller.
Yes it also has some disadvantages - you are giving controller permission to get any repository. Is it problem for you? You can always create multiple factories for some sub systems if you need or simply expose multiple factory interfaces on single implementation. It still doesn't cover all cases but it is better than passing 15 parameters to constructor. Btw. are you sure those controllers should not be split?
Note: This is not Service provider anti-pattern.
After doing work with multiple repositories we need to call the SaveChanges method, but which repository should we call it on?
Say hello to Unit of Work pattern. Unit of Work is logical transaction in your application. It persists all changes from logical transaction together. Repository should not be responsible for persisting changes - the unit of work should be. Somebody mentioned that DbContext is implementation of Repository pattern. It is not. It is implementation of Unit of Work pattern and DbSet is implementation of Repository pattern.
What you need is central class holding the instance of the context. The context will be also passed to repositories because they need it to retrieve data but only the central class (unit of work) will offer saving changes. It can also handle database transaction if you for example need to change isolation level.
Where should be unit of work handled? That depends where your logical operation is orchestrated. If the operation is orchestrated directly in controller's actions you need to have unit of work in the action as well and call SaveChanges once all modifications are done.
If you don't care about separation of concerns too much you can even combine unit of work and factory into single class. That brings us to your DataBucket.
I think you are absolutely right to use the Unit of Work pattern in this case. Not only does this prevent you from needing a SaveChanges method on every repository, it provides you a nice way to handle transactions from within code rather than in your database itself. I included a Rollback method with my UOW so that if there was an exception I could undo any of the changes the operation had already made on my DataContext.
One thing you could do to prevent weird dependency issues would be to group related repositories on their own Unit of Work, rather than having one big DataBucket that holds every Repository you have (if that was your intent). Each UOW would only need to be accessible at the same level as the repositories it contained, and other repositories should probably not depend on other UOWs themselves (your repositories shouldn't need to use other repositories).
If wanted to be an even bigger purist of the pattern, you could also structure your UOWs to represent just that, a single Unit of Work. You define them to represent a specific operation in your domain, and provide it with the repositories required to complete that operation. Individual repositories could exist on more than one UOW, if it made sense to be used by more than one operation in your domain.
For example, a PlaceCustomerOrderUnitOfWork may need a CustomerRepository, OrderRepository, BillingRepository, and a ShippingRepository
An CreateCustomerUnitOfWork may need just a CustomerRepository. Either way, you can easily pass that dependency around to its consumers, more fine grained interfaces for your UOW can help target your testing and reduce the effort to create a mock.
The notion of every repository having a SaveChanges is flawed because calling it saves everything. It is not possible to modify part of a DataContext, you always save everything. So a central DataContext holder class is a good idea.
Alternatively, you could have a repository with generic methods that can operate on any entity type (GetTable<T>, Query<T>, ...). That would get rid of all those classes and merge them into one (basically, only DataBucket remains).
It might even be the case that you don't need repositories at all: You can inject the DataContext itself! The DataContext by itself is a repository and a full fledged data access layer. It doesn't lend itself to mocking though.
If you can do this depends on what you need the "repository" do provide.
The only issue with having that DataBucket class would be that this class needs to know about all entities and all repositories. So it sits very high in the software stack (at the top). At the same time it is being used by basically everything so it sits at the bottom, too. Wait! That is a dependency cycle over the whole codebase.
This means that everything using it and everything being used by it must sit in the same assembly.
What I have done in the past was to create child injection containers (I was using Unity) and register a data context with a ContainerControlledLifetime. So that when the repositories are instantiated, they always have the same data context injected into them. I then hang on to that data context and when my "Unit of Work" is complete, I call DataContext.SaveChanges() flushing all the changes out to the database.
This has some other advantages such as (with EF) some local caching, such that if more than one repository needs to get the same entity, only the first repository actually causes a database round trip.
It's also a nice way to "batch up" the changes and make sure they execute as a single atomic transaction.