2

I'm doing a wpf application using MVVM light with its Ioc SimpleIoc.

I implemented the repository pattern like this :

 public interface ICrud<T> where  T : class 
    {
        IEnumerable<T> GetAll();
        Task<IEnumerable<T>> AsyncGetAll(); 
        void AddNew(params T[] items);
        void Delete(params T[] items);
        void Update(params T[] items);
        void SaveOrUpdate(params T[] items);
    }

 public class Crud<T> : ICrud<T> where T : class 
    {

        public void AddNew(params T[] items)
        {
            using (var context = new DataEntities())
            {
                foreach (T item in items)
                {
                    context.Entry(item).State = System.Data.Entity.EntityState.Added;
                }
                context.SaveChanges();
            }
        }

        public void Delete(params T[] items)
        {
            using (var context = new DataEntities())
            {
                foreach (T item in items)
                {
                    context.Entry(item).State = System.Data.Entity.EntityState.Deleted;
                }
                context.SaveChanges();
            }
        }

        public void Update(params T[] items)
        {
            using (var context = new DataEntities())
            {
                foreach (T item in items)
                {
                    context.Entry(item).State = System.Data.Entity.EntityState.Modified;
                }
                context.SaveChanges ();
            }
        }


        public  void SaveOrUpdate(params T[] items)
        {
            using (var context = new DataEntities())
            {
                foreach (T item in items)
                {
                    try
                    {
                        context.Entry(item).State = System.Data.Entity.EntityState.Modified;
                         context.SaveChanges();
                    }
                    catch (Exception)
                    {
                        context.Entry(item).State = System.Data.Entity.EntityState.Added;
                         context.SaveChanges();
                    }

                }

            }
        }

        public IEnumerable<T> GetAll()
        {
            using (var context = new DataEntities())
            {
                DbSet<T> dbSet = context.Set<T>(); 
                return dbSet.AsEnumerable().ToList();
            }
        }


        public Task<IEnumerable<T>> AsyncGetAll()
        {
            return Task.Factory.StartNew(() =>
            {

                    var context = new DataEntities();
                    DbSet<T> dbSet = context.Set<T>();
                    return dbSet.AsEnumerable();

            });
        }
    }

in the viewmodel locator , I inject the dependencies like this :

 static ViewModelLocator()
        {
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
            SimpleIoc.Default.Register<IDataService, DataService>();
             SimpleIoc.Default.Register<ICrud<student>, Crud<student>>();
            SimpleIoc.Default.Register<ICrud<prof>, Crud<prof>>();
//Add the other EF entities dependencies
        }

My problem is when I'd to perform a crud operation I have to instanciate an EF entity before calling for example :

SimpleIoc.Default.GetInstance<ICrud<student>>().AddNew();

I need to know :

  1. the instanciation of an EF like above, is it a violation of the concept of Dependency Injection
  2. If it is the case, How can I fix this problem?
6
  • 1
    Why can't you just inject your context into the constructor for your CRUD class? Commented Feb 25, 2015 at 9:59
  • @DavidG I have to prepare the entity before calling the crud operation, for example I change the age of student so I instanciate a new student entity in the viewmodel class, change the value of age and finally calling the update operation. I need to know How can I avoid instanciating entities. Commented Feb 25, 2015 at 10:04
  • 2
    You should inject the ICrud<student> in the constructor of your view model. Commented Feb 25, 2015 at 10:59
  • @Steven I need to inject the EF entities not the ICruds Commented Feb 25, 2015 at 11:45
  • 1
    @LamloumiAfif: You shouldn't inject entities. Entities are not services. You should only inject services, not entities, nor messages or DTOs. Commented Feb 25, 2015 at 11:54

1 Answer 1

5

You shouldn't inject entities. Entities are not services. The object graphs that you build using dependency injection, should solely consist of services. Anything that contains runtime data (entities, messages, DTOs) should be passed through the built object graph using method calls.

Take a look for instance at this and this answer and this blog post.

Mixing data and behavior in a single class makes it much harder to test you DI configuration and makes it hard to apply cross-cutting concerns. But besides that, injecting runtime data (such as entities) into a service's constructor results in ambiguity, because it is unclear which exact entity to inject into the constructor. Take for instance some ICustomerService that depends on a Customer entity in its constructor. Which entity should we inject here, since we might have thousands. Although this can be solved by implementing the selection criteria in the location where we create the ICustomerService implementation (our Composition Root), this makes the DI configuration very complex, makes it really hard to verify the configuration and results in business logic in a part of the application that should not contain any business logic.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.