依赖注入和Entity Framework [英] Dependency injection and Entity Framework

查看:164
本文介绍了依赖注入和Entity Framework的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在做MVVM使用灯带及其IOC SimpleIoc WPF应用程序。



我实现了资源库这样的格局:

 公共接口ICrud< T>其中T:类
{
IEnumerable的< T>得到所有();
任务<&IEnumerable的LT; T>> AsyncGetAll();
无效的AddNew(PARAMS T []项目);
无效删除(PARAMS T []项目);
无效更新(PARAMS T []项目);
无效SaveOrUpdate(PARAMS T []项目);
}

公共类和界面污物LT; T> :ICrud< T>其中T:类
{

公共无效的AddNew(PARAMS T []项目)
{
使用(VAR上下文=新DataEntities())
{
的foreach(在项目牛逼的项目)
{
context.Entry(项目)= .STATE System.Data.Entity.EntityState.Added;
}
context.SaveChanges();
}
}

公共无效删除(PARAMS T []项目)
{
使用(VAR上下文=新DataEntities())
{
的foreach(在项目牛逼的项目)
{
context.Entry(项目)= .STATE System.Data.Entity.EntityState.Deleted;
}
context.SaveChanges();
}
}

公共无效更新(PARAMS T []项目)
{
使用(VAR上下文=新DataEntities())
{
的foreach(在项目牛逼的项目)
{
context.Entry(项目)= .STATE System.Data.Entity.EntityState.Modified;
}
context.SaveChanges();
}
}


公共无效SaveOrUpdate(PARAMS T []项目)使用(VAR上下文=新DataEntities
{
() )
{
的foreach(在项目牛逼的项目)
{

{
context.Entry(项目)= .STATE System.Data.Entity的.EntityState.Modified;
context.SaveChanges();
}
赶上(例外)
{
context.Entry(项目)= .STATE System.Data.Entity.EntityState.Added;
context.SaveChanges();
}

}

}
}

公开的IEnumerable< T> GETALL()
{
使用(VAR上下文=新DataEntities())
{
DbSet< T> dbSet = context.Set< T>();
返回dbSet.AsEnumerable()了ToList();
}
}


公共任务<&IEnumerable的LT; T>> AsyncGetAll()
{
返回Task.Factory.StartNew(()=>
{

VAR背景=新DataEntities();
DbSet< ; T> dbSet = context.Set< T>();
返回dbSet.AsEnumerable();

});
}
}

在视图模型定位,我注入这样的依赖

 静态ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(()=> SimpleIoc.Default );
SimpleIoc.Default.Register< IDataService,DataService的>();
SimpleIoc.Default.Register< ICrud<学生>中和界面污物LT;学员GT;>();
SimpleIoc.Default.Register< ICrud<教授>中和界面污物LT;教授>>();
//添加其他EF实体依赖性
}



我的问题是,当我倒是呼吁例如之前执行CRUD操作我有一个实例化EF实体:

  SimpleIoc.Default.GetInstance< ICrud<学员GT;>()的AddNew()。 



我需要知道:




  1. 像上面的EF的instanciation,是它违反了依赖关系注入

  2. 如果是的话,如何能概念我解决这个问题?


解决方案

您不应该注入实体。实体不是服务。你建立使用依赖注入的对象图,应该只包括服务。任何含有(实体,消息的DTO)应通过使用方法调用内置对象图通过运行时数据。



采取在的this 回答和的这个的博客帖子



在一个类中混合数据和行为使得它更难考你DI配置,使得它难以应用横切关注点。但除此之外,运行时数据(如实体)注入歧义服务的构造函数的结果,因为它是不清楚注入构造它的确切实体。就拿一些 ICustomerService 这取决于客户实体在其构造。哪个实体,我们应该在这里注入,因为我们可能有成千上万。虽然这可以通过在我们创建 ICustomerService 实现(我们的作文根)的位置实施的选择标准来解决,这使得DI配置非常复杂,使得它真的很难验证在不应该包含任何业务逻辑的应用程序的一部分中的业务逻辑的配置和效果。


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?

解决方案

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.

这篇关于依赖注入和Entity Framework的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆