使用单个dbcontext作为服务层中的工作单元

时间:2016-12-30 10:25:10

标签: entity-framework asp.net-mvc-4

我尝试实现业务层(服务层)以及存储库层。所以我的项目有以下层EF< --- Repository< --- Service< --- Controller< --- View。

我的上下文类看起来像:

public class ToDoContext : DbContext
{
    public ToDoContext()
        : base("ToDoContext")
    {

    }

    public virtual DbSet<Project> Projects { get; set; }
    public virtual DbSet <Collaborator> Collaborators { get; set; }
    public virtual DbSet<ActionTask> Tasks { get; set; }
}

我的ProjectRepository看起来像:

public class ProjectRepository : IProjectRepository, IDisposable
{
    ToDoContext Context;
    public ProjectRepository(ToDoContext context)
    {
        this.Context = context;
    }

    public virtual List<Project> AllProjects()
    {
        IQueryable<Project> projects = Context.Projects;
        return projects.ToList<Project>();
    }

    public Project Find(int? id)
    {
        // some code
    }

    public void InsertOrUpdate(Project project)
    {
        // some code
    }

    public void Delete(int? id)
    {
       // some code
    }

    public void Save()
    {

        // some code
    }

    public void Dispose()
    {
        Context.Dispose();
    }
}

我的ProjectService类看起来像:

public class ProjectService : IProjectService
{
    IProjectRepository ProjectRepo;
    ICollaboratorRepository CollaboratorRepo;

    public ProjectService(IProjectRepository projectRepo, ICollaboratorRepository collaboratorRepo)
    {
        this.ProjectRepo = projectRepo;
        this.CollaboratorRepo = collaboratorRepo;
    }

    public List<Project> GetAllProjects()
    {
        return ProjectRepo.AllProjects();
    }

    public void CreateProject(FormCollection formData)
    {
        // code to parse form data as per my business needs

        // code to code to fetch related collaborator list

        // save the project data

    }

    public List<Collaborator> GetCollaborators(string[] collaboratorId)
    {
        // Fetch collaborator list using collaborator repository
        return CollaboratorRepository.GetAllCollaborators();
    }
}

同样,我已经为我的协作者实现了服务和存储库层。

总结代码我在ProjectService类中的 CreateProject()方法使用协作者存储库获取协作者列表,并创建一个新项目,将协作者列表与此新创建的项目相关联并保存。所以我猜我这整个过程是一个工作单元

当我使用CollaboratorRepository获取协作者列表并尝试使用ProjectRepository保存新创建的项目时,它会抛出错误“实体对象不能被多个IEntityChangeTracker实例引用。”。我想这是因为尚未处理CollaboratorRepository dbcontext。所以我在使用新上下文之前手动处理每个上下文。我知道我无法负担手动处理上下文的开销。有人可以帮帮我吗?

我知道我应该为一个工作单元使用相同的dbcontext对象。但是当dbcontext对象暴露给存储库而不是服务层时,我不知道如何实现这一点。

1 个答案:

答案 0 :(得分:1)

IoC如何配置?您应该按照Request \ Thread注册DbContext的LifeTime,以便为每个业务事务获取相同的实例。

提示:为了在Web环境之外拥有可重用的服务,请不要将FormCollection传递给CreateProject方法。解析FormCollection应该由controller \ model binder完成。

对于 Ninject ,请尝试InRequestScope

kernel.Bind<ToDoContext>().To<ToDoContext>().InRequestScope();