You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF MVVM架构下多设备如何同步UnitOfWork数据库上下文?

问题解决方案

核心原因

Entity Framework的DbContext内部默认维护一级缓存,一旦查询过数据就会将实体缓存起来。你的ViewModel是单例模式,绑定的UnitOfWork和DbContext长期存活,这种情况下上下文不会自动感知数据库中其他客户端新增的数据。

具体解决方案

1. 手动刷新上下文缓存

在需要获取最新数据时,主动清空本地缓存或刷新实体:

清空DbSet本地缓存后重新查询

在UserRepository中添加获取最新数据的方法:

public async Task<List<User>> GetAllFreshAsync()
{
    // 清空上下文缓存中的所有User实体
    _context.Users.Local.Clear();
    return await _context.Users.ToListAsync();
}

之后在ViewModel中调用这个方法,就能拿到数据库中的最新用户列表。

刷新单个已知实体

如果知道要刷新的用户ID,可单独重载实体数据:

var targetUser = await _unitOfWork.Users.GetByIdAsync(targetUserId);
if (targetUser != null)
{
    await _context.Entry(targetUser).ReloadAsync();
}

2. 使用无跟踪查询绕过缓存

如果只是读取数据不需要修改,用无跟踪查询直接从数据库拉取最新数据:

// 在UserRepository中实现
public async Task<List<User>> GetAllNoTrackingAsync()
{
    return await _context.Users.AsNoTracking().ToListAsync();
}

这种方式每次查询都会直接访问数据库,不会使用上下文缓存,适合只读场景。

3. 调整UnitOfWork生命周期(推荐)

当前设计中ViewModel单例导致UnitOfWork和DbContext长期存活,可改为让UnitOfWork按需创建、用完即销毁:

1. 修改依赖注入配置

在Prism的Bootstrapper或模块中,将IUnitOfWork注册为瞬态:

containerRegistry.Register<IUnitOfWork, UnitOfWork>(new TransientLifetimeManager());

2. 通过工厂模式创建UnitOfWork

定义工厂接口和实现:

public interface IUnitOfWorkFactory
{
    IUnitOfWork Create();
}

public class UnitOfWorkFactory : IUnitOfWorkFactory
{
    private readonly Func<MyDbContext> _contextFactory;

    public UnitOfWorkFactory(Func<MyDbContext> contextFactory)
    {
        _contextFactory = contextFactory;
    }

    public IUnitOfWork Create()
    {
        return new UnitOfWork(_contextFactory());
    }
}

3. ViewModel中使用工厂获取新实例

public class UsersViewModel : BindableBase
{
    private readonly IUnitOfWorkFactory _uowFactory;

    public UsersViewModel(IUnitOfWorkFactory uowFactory)
    {
        _uowFactory = uowFactory;
    }

    public async Task LoadLatestUsers()
    {
        using(var uow = _uowFactory.Create())
        {
            var latestUsers = await uow.Users.GetAllAsync();
            // 更新UI绑定的用户集合
        }
    }
}

每次创建新的UnitOfWork都会使用全新的DbContext,自然能获取到数据库最新数据,同时也能避免长期存活的上下文导致的内存泄漏问题。

4. 实时数据推送(即时感知场景)

如果需要第二台电脑立刻感知第一台的新增操作,可引入实时通信机制(比如SignalR):

  • 第一台提交数据后,通过SignalR通知服务器
  • 服务器向所有在线客户端推送更新通知
  • 客户端收到通知后,调用上述刷新方法获取最新数据

注意事项

  • 长期存活的DbContext不仅会有缓存问题,还可能因缓存大量实体引发内存泄漏,桌面应用中尽量避免这种设计。
  • 无跟踪查询获取的实体无法直接修改提交,若要修改需重新通过有跟踪查询获取实体,或手动附加到上下文。

内容的提问来源于stack exchange,提问作者Stormhead

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 20:37:11