【问题标题】:Dependency injection and Entity Framework依赖注入和实体框架
【发布时间】:2025-12-28 14:00:17
【问题描述】:

我正在使用 MVVM 灯及其 Ioc SimpleIoc 做一个 wpf 应用程序。

我实现了这样的存储库模式:

 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();

            });
        }
    }

在视图模型定位器中,我像这样注入依赖项:

 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
        }

我的问题是,当我要执行一个 crud 操作时,我必须在调用之前实例化一个 EF 实体:

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

我需要知道:

  1. 像上面这样的 EF 实例化,是否违反了依赖注入的概念
  2. 如果是这样,我该如何解决这个问题?

【问题讨论】:

  • 为什么不能将上下文注入到 CRUD 类的构造函数中?
  • @DavidG 我必须在调用 crud 操作之前准备实体,例如我更改了学生的年龄,所以我在 viewmodel 类中实例化了一个新的学生实体,更改了年龄的值,最后调用更新操作。我需要知道如何避免实例化实体。
  • 您应该在视图模型的构造函数中注入ICrud&lt;student&gt;
  • @Steven 我需要注入 EF 实体而不是 ICruds
  • @LamloumiAfif:你不应该注入实体。实体不是服务。您应该只注入服务,而不是实体、消息或 DTO。

标签: c# wpf entity-framework mvvm dependency-injection


【解决方案1】:

您不应该注入实体。实体不是服务。您使用依赖注入构建的对象图应仅包含服务。任何包含运行时数据(实体、消息、DTO)的东西都应该使用方法调用通过构建的对象图传递。

例如查看thisthis 答案和this 博客文章。

在单个类中混合数据和行为会使测试 DI 配置变得更加困难,并且难以应用横切关注点。但除此之外,将运行时数据(例如实体)注入服务的构造函数会导致歧义,因为不清楚将哪个确切的实体注入构造函数。以一些 ICustomerService 为例,它依赖于其构造函数中的 Customer 实体。我们应该在这里注入哪个实体,因为我们可能有数千个。虽然这可以通过在我们创建ICustomerService 实现(我们的组合根)的位置实现选择标准来解决,但这使得 DI 配置非常复杂,很难验证配置并导致业务逻辑在应用程序的一部分,不应包含任何业务逻辑。

【讨论】: