【asp.net core】7 实战之 数据访问层定义(aspnet是什么语言)

网友投稿 333 2022-06-21


0. 前言

在上一篇,我们搭建了一个项目框架,基本上是一个完整的项目。目前而言,大部分的应用基本都是这个结构。好的,不废话了,进入今天的议题:完成并实现数据层的基础实现。

1. 数据实体

通常情况下,一个项目的数据实体中字段并不是完全没有规律可寻。通常情况下,必须有一个主键。有些时候,会要求在数据表中增加上次修改时间和创建时间,以及创建人和修改人的主键。

所以,我们可以创建一个泛型父类,来帮我们定义这些公共字段:

using System;

namespace Data.Infrastructure

{

public class BaseEntity

{

public T Id { get; set; }

public string ModifyUserId { get; set; }

public DateTime? ModifyTime { get; set; }

public string CreatorId { get; set; }

public DateTime? CreateTime { get; set; }

}

}

看上述代码里,命名空间并不在Data里,而是在Data.Infrastructure里。这个命名空间 Infrastructure 用来存放一些项目的架构类或者接口,里面还会其他的类。

那么,给这个类补充一些可能有用的方法:

public void Create(object userId)

{

CreatorId = userId.ToString();

CreateTime = DateTime.Now;

}

public void Create(object userId, DateTime createTime)

{

CreatorId = userId.ToString();

CreateTime = createTime;

}

public void Modify(object userId)

{

ModifyUserId = userId.ToString();

ModifyTime = DateTime.Now;

}

public void Modify(object userId, DateTime modifyTime)

{

ModifyUserId = userId.ToString();

ModifyTime = modifyTime;

}

这里用来保存用户ID的字段,我都用了字符串做保存,是借用字符串类型保存数据时能容纳更多的数据类型。

2. 常见数据操作接口

在正常开发中,一个完整的数据操作接口会有很多分类,但是很多时候我们需要分开增删改和查询这两种操作。对于数据库而言,视图和有些数据表都是不被允许改变的,这时候就需要我们只对调用方开放查询接口,而不开放修改接口。

所以,在Domain下应该有以下两个接口:

using System;

using System.Collections.Generic;

using System.Linq.Expressions;

namespace Domain.Infrastructure

{

///

/// 修改接口

///

///

public interface IModifyRepository

{

///

/// 插入数据

///

///

///

T Insert(T entity);

///

/// 插入数据

///

///

void Insert(params T[] entities);

///

/// 插入数据

///

///

void Insert(IEnumerable entities);

///

/// 保存已提交的修改

///

///

void Update(T entity);

///

/// 保存已提交的修改

///

///

void Update(params T[] entities);

///

/// 更新数据

///

///

///

void Update(Expression> predicate, Expression> updator);

///

/// 删除

///

///

void Delete(T entity);

///

/// 删除数据

///

///

void Delete(params T[] entities);

///

/// 根据条件删除数据

///

///

void Delete(Expression> predicate);

///

/// 删除主键对应的数据

///

///

void DeleteByKey(object key);

///

/// 删除主键对应的数据

///

///

void DeleteByKeys(params object[] keys);

}

}

上述是更新接口,那么我们回过头来写查询接口,查询接口的方法有很多。我们先创建一个接口文件:

using System;

using System.Linq.Expressions;

namespace Domain.Infrastructure

{

///

/// 查询接口

///

///

public interface ISearchRepository

{

}

}

一个查询接口应该包括以下方法:

获取单个数据

///

/// 根据主键获取数据

///

///

///

T Get(object key);

///

/// 查询

///

///

///

T Get(Expression> predicate);

统计数量:

///

/// 返回数据库中的数据条目

///

///

int Count();

///

/// 返回数据库中的数据条目,类型为Long

///

///

long LongCount();

///

/// 返回符合条件的数据数目

///

///

///

int Count(Expression> predicate);

///

/// 返回长整形的符合条件的数目

///

///

///

long LongCount(Expression> predicate);

存在性判断

///

/// 是否存在满足条件的数据

///

///

///

bool IsExists(Expression> predicate);

查询

//

/// 返回数据库中所有记录

///

///

List Search();

///

/// 返回所有符合条件的数据

///

///

///

List Search(Expression> predicate);

///

/// 返回一个延迟查询的对象

///

///

IEnumerable Query();

///

/// 返回一个延迟查询的对象,并预设了一个查询条件

///

///

///

IEnumerable Query(Expression> predicate);

排序

///

/// 排序查询,默认升序

///

///

///

///

///

List Search

(Expression> predicate, Expression> order);

///

/// 排序查找,指定是否降序排列

///

///

///

///

///

///

List Search

(Expression> predicate, Expression> order, bool isDesc);

分页

实际上分页的接口定义模型需要两个类的辅助,如果没有这两个类,接口的定义会变得十分复杂,不利于代码的可读性:

using System;

using System.Collections.Generic;

using System.Linq.Expressions;

namespace Data.Infrastructure

{

///

/// 分页条件模型

///

///

public class PageCondition

{

///

/// 查询条件

///

///

public Expression> Predicate { get; set; }

///

/// 排序字段

///

///

public string OrderProperty { get; set; }

///

/// 升序排序或者降序排序,升序为 asc或者空,降序为desc

///

///

public string Sort{get;set;}

///

/// 每页最大数据容量

///

///

public int PerpageSize { get; set; }

///

/// 当前页

///

///

public int CurrentPage { get; set; }

}

///

/// 分页结果

///

///

public class PageModel

{

///

/// 数据

///

///

public List Items { get; set; }

///

/// 当前页码

///

///

public int CurrentPage { get; set; }

///

/// 每页最大数据容量

///

///

public int PerpageSize { get; set; }

///

/// 查询数据总数

///

///

public long TotalCount { get; set; }

///

/// 总页码

///

///

public int TotalPages { get; set; }

}

}

这是两个辅助类,可以简单看一下如果这些参数不进行封装直接传给方法,可以预见方法的参数列表会特别长,这对于可读性和可维护性来说简直就是灾难。我曾经接手过一个项目的维护,上一位开发者在一个方法写了近15个参数,而且还有大量的可选参数,嗯,十分头疼。所以,我不建议大家这样写,一个方法参数超过4个我建议还是封装一下。

那么,看一看方法的声明:

///

/// 根据分页参数设置,进行分页查询

///

///

///

PageModel Search(PageCondition condition);

这是使用参数封装了请求的写法,小伙伴们可以试试不用封装,方法是如何声明的。

3. 总结

在这一篇带领大家梳理了一下数据访问的接口定义,对一个系统来说,这些方法都是有必要的(但不是每个方法使用频率都一样高)。也是简单的跟大家分享一下我在实际工作中写代码的总结。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:LeetCode刷题 -- 20200607 前缀和篇(leetcode刷题班)
下一篇:深入C#内核 IL汇编语言 (1) by Eddy(深入查摆)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~