L2S DataContext不同步:未找到或更改行

时间:2010-12-22 10:49:58

标签: asp.net-mvc linq-to-sql service repository-pattern asp.net-mvc-3

Psssst ...!

请继续阅读。但我可以在这里告诉你,这个问题与DataContext无关,而是与依赖注入有关。我已经提出了这个问题,因为它记录了一个可能的问题,即“未找到或未更改的行”与现实世界的并发冲突无关。

似乎问题是由编写错误的依赖注入引起的。或者说,我开始相信,默认情况下我使用的DI容器进行生命周期管理。

问题是我使用DataContext作为Ninject提供的构造函数参数。似乎默认行为是缓存此DataContext,导致各种意外行为。我会就此问一个单独的问题。

无论如何,接下来是我的原始问题,正如您将看到的那样,错过了一英里问题的真正原因......

问题

我收到一些错误,暗示DataContext,或者更确切地说,我使用DataContext的方式不同步。

db.SubmitChanges()发生错误,其中db是我的DataContext实例。错误是:

未找到或更改行。

问题只是间歇性地发生,例如,添加一行然后删除它。如果我停止开发服务器并重新启动,添加的行就在那里,我可以删除它没问题。

也就是说,问题似乎与DataContext丢失了已添加的行的跟踪有关。

重要:

在任何人投票关闭此帖子之前,基于它是重复的,我检查了sql server profiler并且SQL中没有“Where 0 = 1”。

我还重新创建了dbml文件,因此我对数据库模式与dbml文件所代表的模式同步感到满意。

即,没有不匹配的可空列/不可空列等的情况

我的诊断(值得):

问题似乎(对我而言)与我如何使用DataContext有关。我是MVC,存储库和服务模式的新手,所以怀疑我把错误连接起来了。

设置

简单的电子教学应用程序处于早期阶段。学生需要能够在他们的用户课程中添加和删除课程(课程表)。

为此,我有一个服务,它将一个特定的DataContext实例依赖注入到它的构造函数中。

服务类构造函数:

public class SqlPupilBlockService : IPupilBlockService
{
    DataContext db;
    public SqlPupilBlockService(DataContext db)
    {
        this.db = db;
        CoursesRepository = new SqlRepository<Course>(db);
        UserCoursesRepository = new SqlRepository<UserCourse>(db);
    }
// Etc, etc
}

CoursesRepository和UserCoursesRepository都是服务类的私有属性,属于IRepository类型(只是一个简单的通用存储库接口)。

SqlRepository代码:

public class SqlRepository<T> : IRepository<T> where T : class
    {
        DataContext db;
        public SqlRepository(DataContext db)
        {
            this.db = db;
        }

        #region IRepository<T> Members

        public IQueryable<T> Query
        {
            get { return db.GetTable<T>(); }
        }

        public List<T> FetchAll()
        {
            return Query.ToList();
        }

        public void Add(T entity)
        {
            db.GetTable<T>().InsertOnSubmit(entity);
        }

        public void Delete(T entity)
        {
            db.GetTable<T>().DeleteOnSubmit(entity);
        }

        public void Save()
        {
            db.SubmitChanges();
        }

        #endregion
    }

添加和删除UserCourses的两种方法是:

添加和删除用户课程的服务方法:

public void AddUserCourse(int courseId)
{
    UserCourse uc = new UserCourse();
    uc.IdCourse = courseId;
    uc.IdUser = UserId;
    uc.DateCreated = DateTime.Now;
    uc.DateAmended = DateTime.Now;
    uc.Role = "Pupil";
    uc.CourseNotes = string.Empty;
    uc.ActiveStepIndex = 0;
    UserCoursesRepository.Add(uc);
    UserCoursesRepository.Save();
}

public void DeleteUserCourse(int courseId)
{
    var uc = (UserCoursesRepository.Query.Where(x => x.IdUser == UserId && x.IdCourse == courseId)).Single();
    UserCoursesRepository.Delete(uc);
    UserCoursesRepository.Save();

}

的Ajax

我通过Ajax.BeginForm

使用Ajax

我认为这不相关。

ASP.NET MVC 3

我使用的是mvc3,但不认为这是相关的:错误与模型代码有关。

2 个答案:

答案 0 :(得分:1)

  

问题只是间歇性地发生,   例如,然后添加一行   删除它。如果我停止开发服务器   并重新启动,添加的行就在那里   我可以删除它没问题。

您的代码未显示添加的行与删除/更新之间的链接。您的Add()不返回对象引用。

我认为你缺少一个刷新(即插入后重新加载对象)。您的IdCourse也是表中的PK吗?

答案 1 :(得分:0)

编辑:

进一步的研究表明问题在于依赖注入。

问题与依赖注入如何管理它创建的项目有关。谷歌在IoC或DI中进行“生命周期管理”。从本质上讲,DI缓存了我注入的DataContext构造函数参数。

有关使用工厂模式解决此问题的方法,请参阅此主题: Ninject caching an injected DataContext? Lifecycle Management?

接受的答案解决了这一切。