我继承了一个使用实体框架和仓储模式的解决方案。在这个解决方案中,之前的开发人员忘记了实现多对多关系,所以现在我必须代替他们来完成。
我对EF和这个模式都不太熟悉,所以我就不能让我尝试实际工作的功能起作用,那就是插入到多对多关系中。我可以让EF在数据库中创建关系表,但是无论如何我都无法插入数据。
我看过类似于此问题的其他问题,但没有一个与这里实现的模式完全匹配,而且我对所有内容都不熟悉,所以无法理解它。
请有人看一下代码并查看我错过了什么吗?(代码已经简化了一点,并且这不是真正的Student/Course项目,但我正在使用这些名称,因为它们在以前的示例中已使用)
这是我的代码。非常简单,没有成千上万的接口。这个运行得很好,没有异常。当我在“Main”类中调试并快速观察studentUow
时,Students.Courses集合确实包含一个值,但它从未保存到数据库中。此外,它只包含一个值,尽管它应该包含多个课程。
实体类
public class Student { // This class already existed
public int StudentId { get; protected set; }
public virtual ICollection<Course> Courses { get; set; } // I added this property
}
public class Course { // This class already existed
public int CourseId { get; protected set; }
public virtual ICollection<Student> Students { get; set; } // I added this property
}
代码库
public class StudentRepository {
protected DbContext DbContext { get; private set; }
protected DbSet<Student> DbSet { get; private set; }
public StudentRepository(DbContext dbContext) {
DbContext = dbContext;
DbSet = dbContext.Set<Student>();
}
public virtual void AddOrUpdate(Student entity) {
if (Exists(entity)) {
Update(entity);
} else {
Add(entity);
}
}
public virtual void Update(Student entity) {
var dbEntityEntry = DbContext.Entry(entity);
if (dbEntityEntry.State == EntityState.Detached) {
DbSet.Attach(entity);
}
dbEntityEntry.State = EntityState.Modified;
}
public virtual Student Add(Student entity) {
var dbEntityEntry = DbContext.Entry(entity);
if (dbEntityEntry.State != EntityState.Detached) {
dbEntityEntry.State = EntityState.Added;
} else {
return DbSet.Add(entity);
}
return null;
}
public IQueryable<Student> Queryable() {
return DbSet;
}
public bool Exists(Student entity) {
var objContext = ((IObjectContextAdapter)DbContext).ObjectContext;
object existingEntity;
var exists = objContext.TryGetObjectByKey(GetEntityKey(entity), out existingEntity);
if (exists) objContext.Detach(existingEntity);
return exists;
}
private EntityKey GetEntityKey(Student entity) {
var objContext = ((IObjectContextAdapter)DbContext).ObjectContext;
var objSet = objContext.CreateObjectSet<T>();
var entityKey = objContext.CreateEntityKey(objSet.EntitySet.Name, entity);
return entityKey;
}
}
工作单元
public class StudentUow : UnitOfWork<MyDbContext> {
public StudentRepository Students { get { return CreateRepository<StudentRepository>(); } }
public CourseRepository Courses { get { return CreateRepository<CourseRepository>(); } }
}
public class UnitOfWork<TContext> where TContext : System.Data.Entity.DbContext {
private readonly TContext _dbContext;
private IRepositoryProvider _repositoryProvider;
protected UnitOfWork(IRepositoryProvider provider) {
_repositoryProvider = provider;
}
protected TRepository CreateRepository<TRepository>() {
return _repositoryProvider.Create<TRepository>(_dbContext, "default");
}
public void Commit() {
_dbContext.SaveChanges();
}
}
[Export(typeof(IUnitOfWorkProvider))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class UnitOfWorkProvider {
[Import] private IRepositoryProvider _repositoryProvider;
public StudentUow GetStudentUow() {
return new StudentUow(_repositoryProvider);
}
}
[Export(typeof(IRepositoryProvider))]
public class MyRepositoryProvider {
public MyRepositoryProvider() {
Register<RepositoryFactory<IProductRepository, StudentRepository>>();
}
public TRepository Create<TRepository>(DbContext dbContext, string conntextKey)
{
var type = typeof (TRepository);
if (!_factories.ContainsKey(type))
throw new UnknownFactoryException(type);
return (TRepository)_factories[type].Create(dbContext);
}
public void Register<TRepositoryFactory>() where TRepositoryFactory : IRepositoryFactory, new()
{
var factory = new TRepositoryFactory();
if (_factories.ContainsKey(factory.Type)) throw new FactoryTypeAlreadyRegisteredException(factory.Type);
_factories[factory.Type] = factory;
}
}
"Main" class
public class MyClass {
public AddCourse(int studentId, List<int> courses) {
using (var studentUow = new StudentUow()) {
foreach (int courseId in courses) {
Student s = studentUow.Student.Queryable().First(x => x.StudentId == studentId);
Course c = studentUow.Course.Queryable().First(x => x.CourseId == courseId);
s.Courses.Add(c);
studentUow.Student.AddOrUpdate(s);
}
studentUow.Commit();
}
}
}
如果您缺少某些功能,请留下评论,我会添加它或让您知道它在哪里。