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?
Lamloumi Afif
  • 8,941
  • 26
  • 98
  • 191
  • 1
    Why can't you just inject your context into the constructor for your CRUD class? – DavidG Feb 25 '15 at 09: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. – Lamloumi Afif Feb 25 '15 at 10:04
  • 2
    You should inject the `ICrud` in the constructor of your view model. – Steven Feb 25 '15 at 10:59
  • @Steven I need to inject the EF entities not the `ICrud`s – Lamloumi Afif Feb 25 '15 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. – Steven Feb 25 '15 at 11:54
  • @Steven can u explain plz, as an answer, what are the differences between Entities,services, messages and DTOs and what type I have to inject and what type I shouldn't.Thanks, – Lamloumi Afif Feb 25 '15 at 12:21

1 Answers1

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.

Steven
  • 166,672
  • 24
  • 332
  • 435