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

这是一篇关于在 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日

相关文章

  • C#难点逐个击破(2):out返回参数

    当我们在编写C#函数的返回值时,有时候需要返回多个参数,但是C#并不支持多返回值,这时候可以使用out参数来实现。 解释out参数的使用方法 out参数是C#中的一个关键字,它可以将一个函数所使用的某些值作为引用传递,以便在函数返回后继续使用。 举个例子,我们通过下面的代码来解释以下out参数的使用方法: void SetRGB(out int red, o…

    C# 2023年6月7日
    00
  • ASP.NET MVC前台动态添加文本框并在后台使用FormCollection接收值

    下面是“ASP.NET MVC前台动态添加文本框并在后台使用FormCollection接收值”的完整使用攻略,包括创建视图、创建控制器和两个示例。 步骤1:创建 ASP MVC 项目 在 Visual Studio 中创建名为“DynamicTextBoxDemo”的 ASP.NET MVC 项目。 步骤2:创建视图 在 Views 文件夹中创建为“Ind…

    C# 2023年5月12日
    00
  • C# 创建控制台应用程序

    C#创建控制台应用程序的完整攻略 在C#中,控制台应用程序是一种常见的应用程序类型,可以在命令行中运行。本文将提供一个完整的C#创建控制台应用程序的攻略,包括创建、编译、运行、调试等操作。 步骤1:创建控制台应用程序 要创建控制台应用程序,可以按照以下步骤操作: 打开Visual Studio。 选择“文件”->“新建”->“项目”。 在“新建项…

    C# 2023年5月15日
    00
  • WPF+ASP.NET SignalR实现动态折线图的绘制

    下面是详细的攻略: 简介 本文介绍如何使用 WPF 和 ASP.NET SignalR 实现动态折线图的绘制。WPF 是一个用于创建 Windows 应用程序的 UI 框架,而 ASP.NET SignalR 是一个用于实现实时应用程序的框架,两者结合可以实现实时折线图的绘制。 准备工作 在开始实现动态折线图之前,我们需要准备以下工具: Visual Stu…

    C# 2023年6月3日
    00
  • C#使用Jquery zTree实现树状结构显示 异步数据加载

    下面是详细的C#使用Jquery zTree实现树状结构显示 异步数据加载的攻略。 1、准备工作 首先需要引入相关的库文件,包括jquery、ztree和css文件。然后需要设定树状结构的容器,例如在HTML中加入一个div: <div id="tree"></div> 2、配置树状结构 通过以下代码配置树状结构:…

    C# 2023年5月31日
    00
  • C#使用回溯法解决背包问题实例分析

    C#使用回溯法解决背包问题实例分析 背包问题 给定一个固定大小、能够携重量的背包和一组物品,其中每个物品都有自己的重量和价值,在保证不超过背包重量的前提下,如何选择物品使得背包中物品的总价值最大。 问题分析 实际上,背包问题的本质是在不断做出选择中寻找最优解。每次可以选择将物品放入背包或不放入。可以使用回溯法解决该问题。 回溯法常用于解决在一组可能的解中找到…

    C# 2023年6月7日
    00
  • .NET Core 2.0 Preview2 发布汇总

    .NET Core 2.0 Preview2 发布汇总 简介 .NET Core 2.0 Preview2 是微软推出的基于 .NET Core 的第 二个预览版,其中包括了很多新特性、增强功能,同时也修复了一些已知问题和 bug 。 主要更新内容 .NET 标准库的版本升级到 2.0。 重新设计和重构了开发工具链,包括 .NET Core SDK 和 .N…

    C# 2023年6月3日
    00
  • C# Add(T):将元素添加到 ICollection

    C#中的Add(T)方法主要是用来向List集合中添加元素的,T代表数据类型,可以是整型、浮点型、字符串、对象等等。本文将详细讲解C# Add(T)方法的使用方法和注意点。 语法 以下是Add(T)方法的基本语法: public void Add(T item); 参数 Add(T)方法的参数是要添加到List集合中的元素。 返回值 Add(T)方法没有返回…

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