ASP.Net Core基于EF6、Unitwork、Autofac实现Repository模式

yizhihongxing

这是一篇关于在 ASP.Net Core 中应用 Repository 模式的攻略。我们将使用 Entity Framework 6,以及 UnitOfWork 模式和 Autofac 依赖注入框架来实现它。下面将是具体的步骤:

准备工作

在继续之前,我们需要确保在系统中安装了以下软件:

  • Visual Studio 2017 及以上版本
  • .NET Core SDK 及以上版本
  • Entity Framework 6.2 及以上版本

创建项目

首先我们需要新建一个 ASP.Net Core Web 应用程序。我们可以选择在 Visual Studio 2017 中使用 “ASP.Net Core Web 应用程序” 模板来创建。选择 Web 应用程序模板后,我们需要选择 ASP.Net Core 的版本以及项目的类型(例如 Web API 或 MVC)。

安装 NuGet 包

在创建完项目后,我们需要安装一些 NuGet 包。打开 NuGet 包管理器控制台并运行以下命令:

Install-Package EntityFramework
Install-Package Autofac
Install-Package Autofac.Extensions.DependencyInjection
Install-Package Autofac.Extras.DynamicProxy
Install-Package Microsoft.EntityFrameworkCore.SqlServer

这些命令将安装 Entity Framework、Autofac 及其相关插件以及 SQL Server 数据库提供程序。

创建仓储接口

接下来我们需要创建一个仓储接口,该接口定义了一些标准的 CRUD 操作。在本教程中,我们将创建一个名为 IRepository 的接口。我们可以在项目中创建一个名为 “Repositories” 的文件夹,然后在该文件夹下创建一个接口文件:

public interface IRepository<TEntity> where TEntity : class
{
    TEntity GetById(int id);
    void Insert(TEntity entity);
    void Update(TEntity entity);
    void Delete(TEntity entity);
}

在这个例子中,我们定义了四个基本的操作,并使用泛型来确保我们能够处理任何实体类型。

实现仓储接口

接下来我们需要实现 IRepository 接口。在本教程中,我们将使用 Entity Framework 6 数据访问技术实现这个接口。我们可以在项目中创建一个名为 “Repositories” 的文件夹,然后在该文件夹下创建一个名为 EfRepository 的类,该类将实现 IRepository 接口:

public class EfRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
    private readonly DbContext _dbContext;

    public EfRepository(DbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public TEntity GetById(int id)
    {
        return _dbContext.Set<TEntity>().Find(id);
    }

    public void Insert(TEntity entity)
    {
        _dbContext.Set<TEntity>().Add(entity);
    }

    public void Update(TEntity entity)
    {
        _dbContext.Set<TEntity>().Attach(entity);
        _dbContext.Entry(entity).State = EntityState.Modified;
    }

    public void Delete(TEntity entity)
    {
        _dbContext.Set<TEntity>().Remove(entity);
    }
}

在这个例子中,我们创建了一个名为 EfRepository 的类来实现 IRepository 接口。我们使用 Entity Framework 中的 DbContext 类来管理数据库连接和操作实体。在构造函数中,我们将 DbContext 通过构造函数注入到仓储实现中。

实现 UnitOfWork

现在我们需要创建一个名为 IUnitOfWork 的接口,该接口定义了一个 SaveChanges 方法,并在其内部使用事务来确保数据的完整性。我们可以在项目中创建一个名为 “UnitOfWorks” 的文件夹,然后在该文件夹下创建一个接口文件:

public interface IUnitOfWork : IDisposable
{
    void SaveChanges();
}

在这个例子中,我们定义了 IUnitOfWork 接口,并指定了一个 SaveChanges 方法,该方法将确保在一个事务内提交所有待提交的更改。

接下来,我们需要一个具体的 UnitOfWork 类来实现 IUnitOfWork 接口。我们可以在项目中的名为 “UnitOfWorks” 的文件夹下创建一个名为 EfUnitOfWork 的类,代码如下:

public class EfUnitOfWork : IUnitOfWork
{
    private readonly DbContext _dbContext;
    private readonly ILifetimeScope _lifetimeScope;
    private readonly IDictionary<Type, object> _repositories;

    public EfUnitOfWork(DbContext dbContext, ILifetimeScope lifetimeScope)
    {
        _dbContext = dbContext;
        _lifetimeScope = lifetimeScope;
        _repositories = new Dictionary<Type, object>();
    }

    public void SaveChanges()
    {
        using (var transaction = _dbContext.Database.BeginTransaction())
        {
            try
            {
                _dbContext.SaveChanges();

                foreach (var repository in _repositories.Values)
                {
                    ((dynamic) repository).Commit();
                }

                transaction.Commit();
            }
            catch (Exception)
            {
                transaction.Rollback();
                throw;
            }
            finally
            {
                foreach (var repository in _repositories.Values)
                {
                    ((IDisposable) repository).Dispose();
                }

                _repositories.Clear();
                _dbContext.Dispose();
            }
        }
    }

    public IRepository<TEntity> GetRepository<TEntity>() where TEntity : class
    {
        if (!_repositories.ContainsKey(typeof(TEntity)))
        {
            var repository = _lifetimeScope.Resolve<IRepository<TEntity>>();
            _repositories.Add(typeof(TEntity), repository);
        }

        return (IRepository<TEntity>) _repositories[typeof(TEntity)];
    }

    private bool _disposed;

    public virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                _dbContext.Dispose();
            }

            _disposed = true;
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

在这个例子中,我们创建了一个基于 Entity Framework 的 EfUnitOfWork 类来实现我们定义的 IUnitOfWork 接口。在构造函数中,我们将 DbContext 和 Autofac 的 ILifetimeScope 通过构造函数注入到了 EfUnitOfWork 类中。此外,我们还为每个类型创建了一个仓储对象。在 SaveChanges 方法中,我们开始一个新的事务,并处理所有等待提交的更改。在成功提交更改后,我们将调用每个仓储的 Commit 方法来确保所有数据都已保存。

实现依赖注入

现在我们需要设置依赖注入来确保我们的 EfRepositoryEfUnitOfWork 类能够被正确地注入到其他类中。为此,我们需要在 ConfigureServices 方法中做以下两件事情:

  1. 注册依赖项
  2. 设置 MVC 控制器解析

请注意,我们需要为 DbContextIUnitOfWork 接口设置生命周期为“请求”,以确保在 HTTP 请求期间使用的所有组件都具有相同的依赖项。这将确保所有组件都使用相同的数据库上下文对象,并在 HTTP 请求结束时确保它被销毁。我们可以通过以下方式来配置依赖注入:

public void ConfigureServices(IServiceCollection services)
{
    // ...

    services.AddDbContext<MyDbContext>(options =>
    {
        options.UseSqlServer(Configuration.GetConnectionString("MyDbContext"));
    }, ServiceLifetime.Scoped);

    services.AddScoped(typeof(IRepository<>), typeof(EfRepository<>));

    services.AddScoped<IUnitOfWork, EfUnitOfWork>();

    services.AddControllers().AddControllersAsServices().AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.IgnoreNullValues = true;
    });

    // ...
}

在这个例子中,我们首先为 DbContext 注册一个 SQL Server 数据库提供程序。我们在这里使用了 AddDbContext 方法,该方法将被发送到 IServiceCollection,从而确保在请求期间只有一个 SQL Server 数据库实例存在。此外,我们还将 IRepositoryIUnitOfWork 接口注册为 Scoped 生存期,以确保它们在 HTTP 请求内部具有相同的生存期,只有在请求结束时才会被销毁。

注入仓储和工作单元

现在我们已经设置好了依赖注入,所以我们可以注入我们的仓储接口和工作单元接口到我们的代码中。例如,假设我们已经创建了一个名为 MyService 的类,在这个类中我们需要使用一个仓储:

public class MyService
{
    private readonly IRepository<MyEntity> _repository;
    private readonly IUnitOfWork _unitOfWork;

    public MyService(IRepository<MyEntity> repository, IUnitOfWork unitOfWork)
    {
        _repository = repository;
        _unitOfWork = unitOfWork;
    }

    public void DoSomething()
    {
        var entity = new MyEntity { Name = "John Doe" };

        _repository.Insert(entity);

        _unitOfWork.SaveChanges();
    }
}

在这个例子中,我们已经注入了一个 IRepository<MyEntity> 对象和一个 IUnitOfWork 对象到 MyService 类中。

示例说明

下面将给出两个示例说明,以便更好地理解本教程中所描述的概念。

示例 1:使用仓储

首先,我们将使用 MyService 类中注入的 IRepository<MyEntity> 对象实现一些数据访问示例:

public class MyController : Controller
{
    private readonly IRepository<MyEntity> _repository;

    public MyController(IRepository<MyEntity> repository)
    {
        _repository = repository;
    }

    public IActionResult GetById(int id)
    {
        var entity = _repository.GetById(id);

        if (entity != null)
        {
            return Ok(entity);
        }

        return NotFound();
    }

    public IActionResult Create()
    {
        var entity = new MyEntity { Name = "John Doe" };

        _repository.Insert(entity);

        return Ok();
    }
}

在这个示例中,我们创建了一个名为 MyController 的 ASP.Net Core 控制器来处理两个请求。 GetById 请求接受一个参数 id,并使用 IRepository<MyEntity> 中的 GetById 方法查找具有这个 ID 的实体。 如果找到了,就返回一个包含字符串表示的 MyEntity 对象。否则返回 404 未找到错误。

另一个动作是 Create,它创建一个新的 MyEntity 对象并插入数据库。在这个例子中,我们使用 IRepository<MyEntity>Insert 方法来操作数据。

示例 2:使用工作单元

现在我们将实现一个需要使用工作单元来确保数据完整性的功能。假设我们需要在数据库中创建一个需要提交多个更改才能保持完整性的实体。在这种情况下,我们将使用 IUnitOfWork 接口和 EfUnitOfWork 类中的 SaveChanges 方法。

下面是一个使用 IUnitOfWork 接口的示例:

public class MyController : Controller
{
    private readonly IRepository<MyEntity> _repository;
    private readonly IUnitOfWork _unitOfWork;

    public MyController(IRepository<MyEntity> repository, IUnitOfWork unitOfWork)
    {
        _repository = repository;
        _unitOfWork = unitOfWork;
    }

    public IActionResult CreateComplexEntity()
    {
        var entity1 = new MyEntity { Name = "John Doe" };
        var entity2 = new MyEntity { Name = "Jane Doe" };
        var entity3 = new MyComplexEntity
        {
            Entity1 = entity1,
            Entity2 = entity2
        };

        _repository.Insert(entity1);
        _repository.Insert(entity2);
        _repository.Insert(entity3);

        _unitOfWork.SaveChanges();

        return Ok();
    }
}

在这个示例中,我们创建了一个名为 CreateComplexEntity 的 ASP.Net Core 控制器动作,该动作将创建一个包含两个实体的复合实体并将它们全部插入数据库。在这个例子中,我们需要在 IUnitOfWork 接口上调用 SaveChanges 方法,这将确保在事务内提交所有更改。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:ASP.Net Core基于EF6、Unitwork、Autofac实现Repository模式 - Python技术站

(0)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • unity 如何使用文件流读取streamingassets下的资源

    首先,在 Unity3D 中, streaming assets 是一个目录,它在打包成应用程序之前,所有文件都都被放在该目录下,通过文件路径的方式进行访问。访问 streaming assets 中的文件,可以使用File类和 FileStream 类提供的OpenRead()和Read()方法进行读取。 以下是在 Unity3D 中使用文件流读取 str…

    C# 2023年5月15日
    00
  • .NetCore Web Api 利用ActionFilterAttribute统一接口返回值格式及问题解析

    在.NET Core Web API中,我们可以使用ActionFilterAttribute来统一接口返回值格式。在本攻略中,我们将详细讲解如何使用ActionFilterAttribute来统一接口返回值格式,并解析可能遇到的问题。 创建ActionFilterAttribute:首先,我们需要创建一个名为ResultFilterAttribute的Ac…

    C# 2023年5月16日
    00
  • ThreadLocal 在上下文传值场景实践源码

    ThreadLocal 是 Java 中常用的多线程编程技术之一,它可以在多个线程环境中保存并传递数据,将数据与线程绑定在一起,实现线程的局部变量。在一些上下文传值的场景中,ThreadLocal 可以较为方便的实现参数的传递。接下来,本文将详细讲解 ThreadLocal 在上下文传值场景实践源码的完整攻略。 什么是 ThreadLocal ThreadL…

    C# 2023年6月7日
    00
  • C#如何用ThoughtWorks生成二维码

    生成二维码可以使用ThoughtWorks开源的ZXing库。以下是使用C#利用ThoughtWorks生成二维码的完整攻略: 步骤一:引入依赖 使用ZXing生成二维码需要引入ThoughtWorks.QRCode的Nuget包。在Visual Studio中,可以通过在“解决方案资源管理器”中右键点击项目,选择“管理NuGet程序包”来搜索并安装Thou…

    C# 2023年6月6日
    00
  • 三步将Asp.Net页面输出到EXCEL里

    下面是“三步将Asp.Net页面输出到Excel里”的完整攻略,包含两个示例。 1. 引用Excel操作库 在输出Asp.Net页面到Excel前,需要先引用Excel操作库。常用的Excel操作库包括: NPOI(Nuget包名:NPOI) EPPlus(Nuget包名:EPPlus) 这里以NPOI为例。我们可以通过Nuget引入NPOI: Instal…

    C# 2023年6月3日
    00
  • ASP.NET Core自定义中间件的方式详解

    ASP.NET Core自定义中间件的方式详解 在ASP.NET Core中,中间件是一种非常强大的机制,可以在请求管道中执行自定义逻辑。本攻略将提供一些示例,演示如何在ASP.NET Core中创建自定义中间件。 步骤 步骤1:创建.NET Core Web API项目 首先,需要创建一个.NET Core Web API项目。可以使用以下命令在命令行中创…

    C# 2023年5月17日
    00
  • C#中Hash table的一些操作方法讲解

    哈希表(Hash table)是一种常见的数据结构,用于存储键值对(key-value pairs)。在C#中,可以使用System.Collections.Hashtable类来创建一个哈希表对象,它提供了各种方法来管理键值对。 以下是一些C#中哈希表的操作方法的详细讲解: 创建哈希表对象 可以通过以下代码来创建一个哈希表对象: Hashtable has…

    C# 2023年5月31日
    00
  • abp(net core)+easyui+efcore实现仓储管理系统——模块管理升级(六十)

    Abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+easyui+efcore实现仓储管理系统——解决方案介绍(二) abp(net core)+easyui+efcore实现仓储管理系统——领域层创建实体(三)…

    C# 2023年4月18日
    00
合作推广
合作推广
分享本页
返回顶部