简体   繁体   English

依赖注入和实体框架

[英]Dependency injection and Entity Framework

I'm doing a wpf application using MVVM light with its Ioc SimpleIoc . 我正在使用MVVM light及其Ioc SimpleIoc做一个wpf应用程序。

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 : 在viewmodel定位器中,我像这样注入依赖项:

 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 : 我的问题是,当我要执行粗操作时,必须在调用例如之前先实例化EF实体:

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 上面的EF的实例化,是否违反了依赖注入的概念
  2. If it is the case, How can I fix this problem? 如果是这种情况,如何解决此问题?

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. 包含运行时数据(实体,消息,DTO)的所有内容都应使用方法调用通过构建的对象图传递。

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. 将数据和行为混合在一个类中,这将使测试DI配置变得更加困难,并且难以应用跨领域关注点。 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. 例如,某些ICustomerService依赖于其构造函数中的Customer实体。 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. 尽管可以通过在创建ICustomerService实现的位置(我们的组成根)实现选择标准来解决此问题,但这使DI配置非常复杂,使得很难验证配置并导致业务逻辑的一部分。不应包含任何业务逻辑的应用程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM