Cordinate between my repository classes and controller classes to be using the same Context object

asp.net asp.net-mvc c# entity-framework-6 unit-of-work

Question

I am working on an asp.net mvc web application. now i have created multiple repositories classes, for example i have the following abstract repository classes:-

public interface ISkillRepository : IDisposable
{//code goes here..

&

public interface IStaffRepository : IDisposable
{//code goes here

and the model Repositories:-

public class SkillRepository :  ISkillRepository , IDisposable
                {
 private SkillManagementEntities context = new SkillManagementEntities();
    //code goes here

&

public class StaffRepository :  IStaffRepository , IDisposable
                {
                    private SkillManagementEntities context = new SkillManagementEntities();

now inside y controller i am intializing and creating the repo as follow:-

 public class SkillController : Controller
    {

        private ISkillRepository skillRepository;


      public SkillController() : this(new SkillRepository()) {}

      public SkillController(ISkillRepository repository)
      {
          skillRepository = repository;
      }

but currently i got the following error inside my application:

The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects.

and the problem is that i need to be passing the same context accross the repos and controllers. so can anyone adivce on this:-

  1. how i can inside one model repo to reference another repo using the same context class. for example inside the Staff repositoryto referecne the skill repository?

  2. how i can inside a controller class to refer multiple repos , but at the same time pass the same context object among them , so if i issue a save() it will wrap all the statements inside one transaction. for example insie my skillController to reference both the skill & staff repos using the same context object ?

Thanks

Edit I have created the following Unit of work class:-

 public class UnitOfWork : IDisposable
    {
        private SkillManagementEntities context = new SkillManagementEntities();
        private SkillRepository skillRepository;
        private StaffRepository staffRepository;
        private SecurityRoleRepository securityroleRepository;
        public SkillRepository SkillRepository
        {
            get
            {

                if (this.skillRepository == null)
                {
                    this.skillRepository = new SkillRepository(context);
                }
                return skillRepository;
            }
        }

        public StaffRepository StaffRepository
        {
            get
            {

                if (this.staffRepository == null)
                {
                    this.staffRepository = new StaffRepository(context);
                }
                return staffRepository;
            }
        }
        public SecurityRoleRepository SecurityRoleRepository
        {
            get
            {

                if (this.staffRepository == null)
                {
                    this.staffRepository = new SecurityRoleRepository(context);
                }
                return securityroleRepository;
            }
        }
        public async Task Save()
        {
            await context.SaveChangesAsync();
        }

        private bool disposed = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    context.Dispose();
                }
            }
            this.disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }
}

and then inside my repo i did the following:-

 public class SecurityRoleRepository :  ISecurityRoleRepository , IDisposable
        {
            private SkillManagementEntities context;// = new SkillManagementEntities();

            public SecurityRoleRepository(SkillManagementEntities context)
            {
              this.context = context;

and on the controller class i will be referencing the UnitOfWork as follow:-

   public class SecurityRoleController : Controller
    {

        private UnitOfWork unitOfWork = new UnitOfWork();

        public async Task<ActionResult> Index(string filter = null, int page = 1, int pageSize = 20, string sort = "Name", string sortdir = "ASC")
        {

            try
            {
                var records = new PagedList<SecurityRole>();
                ViewBag.filter = filter;
                records.Content = await unitOfWork.SecurityRoleRepository.GetSecurityRoleForGrid(filter, page, pageSize, sort, sortdir).ToListAsync();

now i am facing a problem is that how i can referecne a repo from another Repo ? for example how i can reference the Skill repo inside the SecurityRole repo ?

EDIT Final i did the following steps:- 1. i install

Install-Package Ninject.MVC5 

2. then i created the following dependency class:-

    public class YourDependencyResolverClass : IDependencyResolver
{
    private IKernel kernel;

    public YourDependencyResolverClass()
    {
        kernel = new StandardKernel();
        AddBindings();
    }

    public object GetService(Type serviceType)
    {
        return kernel.TryGet(serviceType);
    }
    public IEnumerable<object> GetServices(Type serviceType)
    {
        return kernel.GetAll(serviceType);
    }


    private void AddBindings()
    {
        kernel.Bind<ISkillRepository>().To<SkillRepository>();
        kernel.Bind<IStaffRepository>().To<StaffRepository>();
        kernel.Bind<ISecurityRoleRepository>().To<SecurityRoleRepository>();
        kernel.Bind<ICustomerRepository>().To<CustomerRepository>();
        kernel.Bind<ISkillVersionHistoryRepository>().To<SkillVersionHistoryRepository>();
     }
}
}

3.now inside my SkillRepository class i will be referencing the StaffRepository as follow:-

   public class SkillRepository :  ISkillRepository , IDisposable
            {
                private SkillManagementEntities context ;

                private IStaffRepository staffrepo = (IStaffRepository)DependencyResolver.Current.GetService(typeof(IStaffRepository));
                public SkillRepository(SkillManagementEntities context)
                {
                  this.context = context;
                }

Finally inside my action method i will be calling the Uiteofwork class as follow:-

 public class StaffController : Controller
    {
        //private SkillManagementEntities db = new SkillManagementEntities();

        UnitOfWork unitofwork = new UnitOfWork();




    public async Task<ActionResult> AutoComplete(string term)
      {

          var staff = await unitofwork.StaffRepository.GetAllActiveStaff(term).Select(a => new { label = a.SamAccUserName }).ToListAsync();

          return Json(staff, JsonRequestBehavior.AllowGet);

and the unite of work class is :-

   public class UnitOfWork : IDisposable
        {
            private SkillManagementEntities context = new SkillManagementEntities();
            private SkillRepository skillRepository;
            private StaffRepository staffRepository;
            private SecurityRoleRepository securityroleRepository;
            private CustomerRepository customerRepository;
            private SkillVersionHistoryRepository SVH;
            public SkillRepository SkillRepository
            {
                get
                {

                    if (this.skillRepository == null)
                    {
                        this.skillRepository = new SkillRepository(context);
                    }
                    return skillRepository;
                }
            }

            public StaffRepository StaffRepository
            {
                get
                {

                    if (this.staffRepository == null)
                    {
                        this.staffRepository = new StaffRepository(context);
                    }
                    return staffRepository;
                }
            }
            public CustomerRepository CustomerRepository
            {
                get
                {

                    if (this.customerRepository == null)
                    {
                        this.customerRepository = new CustomerRepository(context);
                    }
                    return customerRepository;
                }
            }
            public SecurityRoleRepository SecurityRoleRepository
            {
                get
                {

                    if (this.securityroleRepository == null)
                    {
                        this.securityroleRepository = new SecurityRoleRepository(context);
                    }
                    return securityroleRepository;
                }
            }
            public SkillVersionHistoryRepository SkillVersionHistoryRepository 
            {
                get
                {

                    if (this.SVH == null)
                    {
                        this.SVH = new SkillVersionHistoryRepository(context);
                    }
                    return SVH;
                }
            }
            public async Task Save()
            {
                await context.SaveChangesAsync();
            }

            private bool disposed = false;

            protected virtual void Dispose(bool disposing)
            {
                if (!this.disposed)
                {
                    if (disposing)
                    {
                        context.Dispose();
                    }
                }
                this.disposed = true;
            }

            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
        }

So can you adivce if my approach of using unitefwork and DI will guarantee that all my statements will be warped inside a single DB transaction ? thnaks?

1
0
2/6/2015 4:23:32 PM

Popular Answer

We handle this by sharing a context using a singleton that is scoped to the request using HttpContext:

    public MyContext GetContext()
    {
        if (System.Web.HttpContext.Current.Items["MyScopedContext"] == null)
        {
            System.Web.HttpContext.Current.Items["MyScopedContext"] = new MyContext();
        }

        return (MyContext)System.Web.HttpContext.Current.Items["MyScopedContext"];
    }

The context object (repository) itself essentially houses a Unit of Work. The code I added above just gives you a way to share a single repository across all code running within a request. If your repository classes are defined in the scope of a web application, you can just replace your direct instantiation of SkillManagementEntities() with a call to a GetContext() method.

On the other hand if your repositories are defined in a layer shared by heterogeneous applications, you may need to get your context from a factory object that you can inject as needed. Either way, creating a new context object per repository is what's causing your issue.

2
2/5/2015 3:39:07 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow