0

我有一个 CRUD 存储库作为休耕:

public class CrudRepository<T> : ICrudRepository<T>
        where T : class, IUnique
    {
        static DataContext db = new DataContext();

        protected DataContext DataContext { get { return db; } }

        public virtual IQueryable<T> GetAll()
        {
            return db.GetTable<T>();
        }

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

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

        public virtual T Get(int id)
        {
            return GetAll().FirstOrDefault(t => t.Id.Equals(id));
        }
    }

我为所有实例关闭存储库使用静态数据上下文。我想更改外键实体,所以我尝试休闲解决方案:

CrudRepository<Employee> employeeRepository = new CrudRepository<Employee >();
Employee employee = employeeRepository.Get(employeeId)
employee.OfficeId = officeId;
employeeRepository.Save();

但它抛出了休闲异常:

ForeignKeyReferenceAlreadyHasValueException

所以我尝试使用第二种解决方案:

CrudRepository<Employee> employeeRepository = new CrudRepository<Employee >();
Employee employee = employeeRepository.Get(employeeId)
employee.Office = new CrudRepository<Office>().Get(officeId);
employeeRepository.Save();

但它会抛出异常消息:

已尝试附加或添加一个不是新的实体,可能是从另一个 DataContext 加载的

我能做些什么?问题是什么?

4

1 回答 1

1

三件事突然出现在我身上。

employee.OfficeId = officeId; 

如果 Employee 类具有 OfficeId 属性和 Office 属性,则必须使用 Office 属性进行更改。Office 属性是从 linq 设计器中的关系自动生成的。

如果您想改用基于 Id 的操作,请在设计器中删除员工和办公室之间的关系(注意:这不会更改数据库,它只会更改代码生成器使用的映射)。

new CrudRepository<Employee >();  
new CrudRepository<Office>().Get(officeId); 

每个 Crud 存储库都有自己的数据上下文。从不同数据上下文加载的对象不允许混合。假设它们被允许混合 - 当您调用 SubmitChanges 时,哪个 DataContext 负责保存?

最终,这意味着如果您想继续使用 LinqToSql,您的 CrudRepository 实现将成为您想要摆脱的东西。在单个类上支持 Crud 操作并没有那么有用。至少它只是直通调用,并且很容易被直接的 DataContext 方法调用替换。

static DataContext db = new DataContext(); 

这是该死的。DataContext 不是线程安全的。

于 2010-02-17T16:05:53.660 回答