Asp.net MVC——工作单元&x2013;重复记录问题

Asp.net MVC——工作单元&x2013;重复记录问题,asp.net,asp.net-mvc,unit-of-work,Asp.net,Asp.net Mvc,Unit Of Work,我正在做这个项目,我们有一个表单保存一个实体,在保存它之前,我们通过检查数据库中实体的唯一属性来检查记录是否不存在 这可以很好地工作,除了在我们多次快速按下SubmitForm按钮的情况下。在这种情况下,数据库检查不起作用,它会在数据库中创建多个记录条目 我认为这是应用程序的一个设计问题,但我对工作单元模式还不熟悉,我不明白为什么不工作 这是我们在服务层上执行的检查: IEnumerable<Story> Stories = _unitOfWork.StoryReposito

我正在做这个项目,我们有一个表单保存一个实体,在保存它之前,我们通过检查数据库中实体的唯一属性来检查记录是否不存在

这可以很好地工作,除了在我们多次快速按下SubmitForm按钮的情况下。在这种情况下,数据库检查不起作用,它会在数据库中创建多个记录条目

我认为这是应用程序的一个设计问题,但我对工作单元模式还不熟悉,我不明白为什么不工作

这是我们在服务层上执行的检查:

    IEnumerable<Story> Stories = _unitOfWork.StoryRepository.Get(s => e.GUID.Equals(GUID));
    if (Stories.Count() > 0)
    {
        _unitOfWork. StoryRepository.Insert(newStory);
        _unitOfWork.Save();
    }
我的UnitOfWork类声明为:

public class UnitOfWork : Disposable, IUnitOfWork
DatabaseFactory.cs:

public class DatabaseFactory : Disposable, IDatabaseFactory
{
    private myContext _dataContext;
    private readonly object _door = new object();

    public myContext Get()
    {
        lock (_door)
        {
            return _dataContext ?? (_dataContext = new myContext());
        }
    }

    protected override void DisposeCore()
    {
        if (_dataContext != null)
            _dataContext.Dispose();
    }
}

我是否应该像Pluc建议的那样,每次调用服务的方法时都创建UnitOfWork的实例?

很可能,您创建工作单元太早了。你的工作单元应该是可识别的,这样你就可以在你需要的时候使用它,然后马上把它扔掉。在这种情况下,使用语句变得非常好:

using(var unitOfWork = new UnitOfWork())
{
    IEnumerable<Story> Stories = unitOfWork.StoryRepository.Get(s => e.GUID.Equals(GUID));
    if (Stories.Count() > 0)
    {
        unitOfWork.StoryRepository.Insert(newStory);
        unitOfWork.Save();
    }
}
使用(var unitOfWork=new unitOfWork())
{
IEnumerable Stories=unitOfWork.StoryRepository.Get(s=>e.GUID.Equals(GUID));
如果(Stories.Count()>0)
{
unitOfWork.StoryRepository.Insert(newStory);
unitOfWork.Save();
}
}
如果您的UnitOfWork创建得很早,并且StoryRepository提前用于其他场合,那么故事已经加载。如果你点击提交两次,这取决于页面加载速度,那么你就有了一个很好的竞争条件,如果你从请求的UnitOfWork#1在请求之前没有保存他的上下文#2延迟加载他的上下文,那么两个请求都会有完全相同的故事列表,并且这一条件对两个都会通过

如果按需要创建UnitOfWork,它甚至不会加载故事,因此,唯一可以进行坏条件测试的窗口是.Get()存储库方法和UnitOfWork.Save()之间的0.001ms


始终记住,一个工作单元是通过一次批处理所有查询来优化数据访问。它不是一个数据缓存工具。创建它,使用它,转储它。在一个web请求中创建两次或两次以上都没有坏处。

在本文描述的操作方法之前,此UnitOfWork是否在任何地方使用过?我建议您使用SQL Profiler查看执行的查询(如果您有访问权限的话)。问题在于,StoryRepository获取其故事列表的时刻与插入其故事的时刻相差太远。这意味着StoreRepository已经加载了他的数据。也许延迟加载已关闭?或者在提出问题之前做其他事情?这是我在atm机上看到的仅有的两个选项。问题是,这个问题只有在我反复单击submit按钮时才会发生。它工作正常,否则…这就是我要说的。该过程工作正常,只是请求处理太长,在插入新故事之前,第二个请求已经获得了UnitOfWork的实例,并且已经使用StoryRepository收集故事列表(或者UnitOfWork/Repository在延迟加载方面没有正确完成)。要使用Using过程,我相信您可以将UnitOfWork注入属性(甚至是字段,但出于测试目的,您希望避免这样做,因为您将无法手动注入测试UnitOfWork)。只需将[注入]放在您的财产前面。
using(var unitOfWork = new UnitOfWork())
{
    IEnumerable<Story> Stories = unitOfWork.StoryRepository.Get(s => e.GUID.Equals(GUID));
    if (Stories.Count() > 0)
    {
        unitOfWork.StoryRepository.Insert(newStory);
        unitOfWork.Save();
    }
}