首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

NET CORE 2.0,ANGULAR 4和MYSQL的第4部分

什么是Repository模式,为什么要使用它?

使用Repository模式,我们在应用程序的数据访问和业务逻辑层之间创建一个抽象层。通过使用它,我们正在推广一种更松散耦合的方法来访问数据库中的数据。此外,代码更清洁,更易于维护和重用。数据访问逻辑位于一个单独的类中,或者称为存储库的类集,负责持久化应用程序的业务模型。

实施 存储库模式是本文的主题。

那么我们开始吧。

创建模型

首先创建一个名为Entities的新类库(.NET Core)项目,并在其中创建一个名为Models的文件夹,该文件夹将包含所有模型类。模型类将表示数据库中的表格,并将为您提供将数据库中的数据映射到.NET Core的功能。之后,将该项目引用到主项目中。

在Models文件夹中创建两个类并添加代码,如下所示:

using System.ComponentModel.DataAnnotations;

using System.ComponentModel.DataAnnotations.Schema;

namespace Entities.Models

{

[Table("owner")]

public class Owner

{

[Key]

public Guid OwnerId { get; set; }

[Required(ErrorMessage = "Name is required")]

[StringLength(60, ErrorMessage = "Name can't be longer than 60 characters")]

public string Name { get; set; }

[Required(ErrorMessage = "Date of birth is required")]

public DateTime DateOfBirth { get; set; }

[Required(ErrorMessage = "Address is required")]

[StringLength(100, ErrorMessage = "Address cannot be loner then 100 characters")]

public string Address { get; set; }

}

}

using System.ComponentModel.DataAnnotations;

using System.ComponentModel.DataAnnotations.Schema;

namespace Entities.Models

{

[Table("account")]

public class Account

{

[Key]

public Guid AccountId { get; set; }

[Required(ErrorMessage = "Date created is required")]

public DateTime DateCreated { get; set; }

[Required(ErrorMessage = "Account type is required")]

public string AccountType { get; set; }

[Required(ErrorMessage = "Owner Id is required")]

public Guid OwnerId { get; set; }

}

}

如您所见,有两个使用属性Table(“tableName”)装饰的模型。该属性将在数据库中配置相应的表名。此外,每个主键都具有用于配置表的主键的装饰属性Key。所有必填字段都具有[必需的] 属性,并且如果要约束字符串,则可以使用属性[StringLength]。

请注意,这些模型是干净的,它们只有那些与表格中的列匹配的属性。我喜欢尽可能保持模型的清洁 ,这是做到这一点的方法。稍后,我们将创建带有属性的DTO类,以将一个所有者与其所有帐户连接起来,或将一个帐户与其所有者连接起来。

上下文类和数据库连接

现在,让我们创建上下文类,它将成为与数据库通信的中间件组件。它具有包含来自数据库的表数据的DbSet属性。

在实体项目的根目录下,创建RepositoryContext类并按如下所示进行编码:

using Entities.Models;

using Microsoft.EntityFrameworkCore;

namespace Entities

{

public class RepositoryContext: DbContext

{

public RepositoryContext(DbContextOptions options)

:base(options)

{

}

public DbSet Owners { get; set; }

public DbSet Accounts { get; set; }

}

}

要启用.NET核心部分和MySQL数据库之间的通信,您需要安装名为Pomelo.EntityFrameworkCore.MySql的第三方库。在主项目中,您可以使用NuGet包管理器或包管理器控制台进行安装。

安装后,打开 appsettings.json文件并在其中添加数据库连接设置。

{

"Logging": {

"IncludeScopes": false,

"Debug": {

"LogLevel": {

"Default": "Warning"

}

},

"Console": {

"LogLevel": {

"Default": "Warning"

}

}

},

"mysqlconnection": {

"connectionString": "server=localhost;userid=root;password=yourpass;database=accountowner;"

}

}

在 ServiceExtensions类中,您将编写用于配置MySQL上下文的代码。

首先,添加 using指令,然后添加 方法ConfigureMySqlContext:

using Microsoft.Extensions.Configuration;

using Microsoft.EntityFrameworkCore;

public static void ConfigureMySqlContext(this IServiceCollection services, IConfiguration config)

{

var connectionString = config["mysqlconnection:connectionString"];

services.AddDbContext(o => o.UseMySql(connectionString));

}

借助 IConfiguration配置参数,您可以访问 appsettings.json文件并从中获取所需的全部数据。之后,在 ConfigureServices方法的Startup类中,将上下文服务添加到services.AddMvc()上面的IOC 。

services.ConfigureMySqlContext(Configuration);

存储库模式逻辑

建立与数据库的连接后,是时候创建通用存储库来为我们提供所有的 CRUD方法。因此,可以在项目中的任何存储库类上调用所有方法。

此外,创建使用该通用存储库的通用存储库和存储库类不会是最后一步。你会更进一步,创建一个围绕着存储库类的包装并将其作为服务注入。因此,您可以实例化这个包装器,然后在您的任何控制器内调用您需要的任何存储库类。 当我们在项目中使用它时,你会理解这个包装的优点。

首先,让我们为Contracts项目中的存储库创建一个接口。

namespace Contracts

{

public interface IRepositoryBase

{

IEnumerable FindAll();

IEnumerable FindByCondition(Expression> expression);

void Create(T entity);

void Update(T entity);

void Delete(T entity);

void Save();

}

}

在创建接口之后,您将创建一个 名为Repository的新类库(.NET Core)项目(将Contracts 的引用添加到此项目中),并在Repository项目中创建抽象类RepositoryBase,它将实现接口 IRepositoryBase 。

也参考这个项目到主项目。

提示:如果您在组件中引用EntityFrameworkCore时遇到问题,那么对于这个新的Repository项目,您需要右键单击Repository项目,然后单击Unload项目。当项目卸载时,右键点击它并选择Edit Repository.csproj。将此代码添加到打开的文件中:

最后,保存文件并右键单击Repository项目并单击Reload Project。

RepositoryBase类应如下所示:

using Contracts;

using Entities;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Linq.Expressions;

namespace Repository

{

public abstract class RepositoryBase : IRepositoryBase where T : class

{

protected RepositoryContext RepositoryContext { get; set; }

public RepositoryBase(RepositoryContext repositoryContext)

{

this.RepositoryContext = repositoryContext;

}

public IEnumerable FindAll()

{

return this.RepositoryContext.Set();

}

public IEnumerable FindByCondition(Expression> expression)

{

return this.RepositoryContext.Set().Where(expression);

}

public void Create(T entity)

{

this.RepositoryContext.Set().Add(entity);

}

public void Update(T entity)

{

this.RepositoryContext.Set().Update(entity);

}

public void Delete(T entity)

{

this.RepositoryContext.Set().Remove(entity);

}

public void Save()

{

this.RepositoryContext.SaveChanges();

}

}

}

这个抽象类以及IRepositoryBase接口使用泛型类型T来处理。这个类型T给RepositoryBase类提供了更多的可重用性。这意味着您现在不必为RepositoryBase指定确切的模型(类),稍后您将执行此操作。

存储库用户类

现在您已拥有RepositoryBase类,请创建 将继承此抽象类的用户类。每个用户类都有自己的接口,用于其他模型特定的方法。此外,通过继承RepositoryBase类,它们将可以访问RepositoryBase中的所有方法。通过这种方式,我们将逻辑分离出来,这对于我们所有的存储库用户类都很常见,并且也针对每个用户类本身。

让我们为您的Owner和Account类在Contracts项目中创建接口。

不要忘记从实体项目添加引用。

using Entities.Models;

namespace Contracts

{

public interface IAccountRepository: IRepositoryBase

{

}

using Entities.Models;

namespace Contracts

{

public interface IAccountRepository: IRepositoryBase

{

}

}

现在在Repository项目中创建一个存储库用户类:

using Contracts;

using Entities;

using Entities.Models;

namespace Repository

{

public class OwnerRepository: RepositoryBase, IOwnerRepository

{

public OwnerRepository(RepositoryContext repositoryContext)

:base(repositoryContext)

{

}

}

}

using Contracts;

using Entities;

using Entities.Models;

namespace Repository

{

public class AccountRepository: RepositoryBase, IAccountRepository

{

public AccountRepository(RepositoryContext repositoryContext)

:base(repositoryContext)

{

}

}

}

完成这些步骤后,您已完成创建存储库和存储库用户类的工作。但还有更多的 事情要做。

创建存储库包装

想象一下,如果在 控制器内部,您需要收集所有所有者并仅收集特定账户(例如国内账户)。您需要实例化OwnerRepository和AccountRepository类,然后调用FindAll和FindByCondition方法。

当你只有两个类时,也许这不是问题,但是如果你需要5个不同类或甚至更多的逻辑。记住这一点,让我们围绕您的存储库用户类创建一个包装。然后将其放入IOC中,最后将其注入控制器的构造函数中。现在,使用该包装器实例,您可以调用您需要的任何存储库类。

在合同项目中创建一个新界面:

namespace Contracts

{

public interface IRepositoryWrapper

{

IOwnerRepository Owner { get; set; }

IAccountRepository Account { get; set; }

}

}

向Repository项目添加一个新类:

using Contracts;

using Entities;

namespace Repository

{

public class RepositoryWrapper: IRepositoryWrapper

{

public IOwnerRepository Owner { get; set; }

public IAccountRepository Account { get; set; }

public RepositoryWrapper(RepositoryContext repositoryContext)

{

this.Owner = new OwnerRepository(repositoryContext);

this.Account = new AccountRepository(repositoryContext);

}

}

}

在ServiceExtensions类中添加以下代码:

public static void ConfigureRepositoryWrapper(this IServiceCollection services)

{

services.AddScoped();

}

在ConfigureServices方法中的Startup类中 ,在 services.AddMvc()行的上方添加以下代码:

services.ConfigureRepositoryWrapper();

所有你需要做的就是测试这个代码,就像你在本系列的第3部分中使用自定义记录器 一样。

在 Values控制器内注入RepositoryWrapper服务,并调用 RepositoryBase类中的任何方法。像这样的东西:

[Route("api/[controller]")]

public class ValuesController : Controller

{

private IRepositoryWrapper _repoWrapper;

public ValuesController(IRepositoryWrapper repoWrapper)

{

_repoWrapper = repoWrapper;

}

// GET api/values

[HttpGet]

public IEnumerable Get()

{

var domesticAccounts = _repoWrapper.Account.FindByCondition(x => x.AccountType.Equals("Domestic"));

var owners = _repoWrapper.Owner.FindAll();

return new string[] { "value1", "value2" };

}

}

将断点放在 Get()方法中,您将看到从数据库返回的数据。

结论

存储库模式增加了代码中的抽象级别。对于不熟悉模式的开发人员来说,这可能会使代码更难理解。但是,一旦你熟悉它,它将减少冗余代码的数量, 并使得逻辑更容易维护。

在这篇文章中,你已经了解到:

什么是存储库模式

如何创建模型和模型属性

如何创建上下文类和数据库连接

创建存储库逻辑的正确方法

以及围绕您的存储库类创建包装的方式

谢谢大家阅读这篇文章,我希望你阅读一些有用的信息。

在下一篇文章中很快会看到,我们将使用存储库逻辑创建HTTP请求。

对于任何建议 或问题,请不要犹豫,在下面的部分留下评论。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180225A0B4E500?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券