如何使用 DI 在实体框架中使用通用 CRUD



我想尝试通用,但我遇到了一些问题。

这是我的一步

第 1 步。我创建一个数据库模型也继承类

    public class DBRepo { }
    public partial class UserAccount : DBRepo
    {
        public int Id { get; set; }
        public string Account { get; set; }
        public string Pwd { get; set; }
    }

第 2 步。我希望所有 CRUD 操作都可以使用此接口。所以我这样做

public class DBServices
    {     
        public interface IDBAction<TEntity> where TEntity : DBRepo
        {
            void InsertData(TEntity entity);
        }
        public class dbCRUD<TEntity> : IDBAction<TEntity> where TEntity : DBRepo
        {
            private readonly CoreContext _db;
            private DbSet<TEntity> dbSet;
            public dbCRUD(CoreContext _db)
            {
                this._db = _db;
                this.dbSet = _db.Set<TEntity>();
            }
            public void InsertData(TEntity _entity)
            {
                this.dbSet.Add(_entity);
                this._db.SaveChanges();
            }
        }
    }

然后我像ServiceProvider

ServiceProvider provider = new ServiceCollection()
                               .AddSingleton<IDBAction<DBRepo>>()
                               .BuildServiceProvider();
        provider.GetService<IDBAction<DBRepo>>().InsertData(_ua);

我会得到这个错误

无法实例化实现类型....

所以我改变尝试其他方式。

在构造函数中

private readonly IDBAction<DBRepo> dBAction;
public HomeController( IDBAction<DBRepo> _dBAction)
{
   this.dBAction = _dBAction;
}
....
this.dBAction.InsertData(_ua);

确定。我再次收到错误

无效操作异常: 无法解析类型...

有些人可以教我如何解决问题吗?

->更新

我试图改变,但它失败了

ServiceProvider provider = new ServiceCollection()
                            .AddScoped<IDBAction<DBRepo>, dbCRUD<DBRepo>>()
                            .AddScoped<CoreContext>()
                                .BuildServiceProvider();

错误与此相同

无法解析类型...

这是我的数据库

文本
public virtual DbSet<UserAccount> UserAccount { get; set; }

        public CoreContext(DbContextOptions<CoreContext> options) 
            : base(options)
        {
        }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
               optionsBuilder.UseSqlServer(@"Connection String");
            }
        }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<UserAccount>(entity =>
            {
                entity.Property(e => e.Account).IsRequired();
                entity.Property(e => e.Pwd)
                    .IsRequired()
                    .HasMaxLength(20);
            });
        }

您以错误的方式注册了它。您必须提供(泛型(的实现,并且还必须注册 DbContext。

ServiceProvider provider = new ServiceCollection()
                               .AddSingleton<IDBAction<DBRepo>, dbCRUD<DBRepo>>()
                               .BuildServiceProvider();
 provider.GetService<IDBAction<DBRepo>>().InsertData(_ua);

此外,将其注册为单例会导致实体框架的更改跟踪出现问题。所以你应该像这样注册它:

ServiceProvider provider = new ServiceCollection()
                               .AddScoped<IDBAction<DBRepo>, dbCRUD<DBRepo>>()
.AddScoped<CoreContext>()
                                   .BuildServiceProvider();
 provider.GetService<IDBAction<DBRepo>>().InsertData(_ua);

你也可以实现一个真正的泛型,比如

public interface IEntity
{
   Guid Id { get; set; }
}
public class DbAction<TEntity> : IDbAction<TEntity> where TEntity: class, IEntity, new()
{
    public void InsertData(TEntity entity)
    {
        ...
    }
}

现在将其注册为泛型

ServiceProvider provider = new ServiceCollection()
                               .AddScoped(typeof(IDbAction<>), typeof(DbAction<>))
.AddScoped<CoreContext>()
                                   .BuildServiceProvider();
 provider.GetService<IDBAction<DBRepo>>().InsertData(_ua);

小例子,但会起作用。

编辑:

当然,必须将 DbContextOptions 传递给 DbContext,IoC 才能正常工作。

.AddDbContext<CoreContext>(options => options.UseSqlServer("my-conntection-string")); // change provider if necessary, this will only work with MS SQL Server

最新更新