因为一直使用的Npoco,希望中以把Npoco作为abp的数据访问层,具体要如何实现呢?
中间要用到注入,配置,模块等各种abp的知识,因为对abp的源码并不是特别熟悉,反复的看了很多文章,终于可以把逻辑搞明白了,在这里记录一下。
参考dapper,首先是模块的定义,
总体看一下
![image.png](https://img.haomeiwen.com/i1727627/ad4d44da0e4d936d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
>这里是模块的代码
在模块中注册了模块的配置项,并且完成了模块和仓储的注册
```
using Abp.Dependency;
using Abp.Modules;
using Abp.Npoco.Repository;
using Abp.Orm;
using Abp.Reflection.Extensions;
namespace Abp.Npoco
{
[DependsOn(typeof(AbpKernelModule))]
public class AbpNpocoModule : AbpModule
{
public override void PreInitialize()
{
IocManager.Register<AbpNpocoModuleConfig>();
Configuration.UnitOfWork.IsTransactionScopeAvailable = false;
}
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(typeof(AbpNpocoModule).GetAssembly());
IocManager.Register(typeof(INpocoRepository<>), typeof(NpocoRepositoryBase<>), DependencyLifeStyle.Transient);
IocManager.Register(typeof(INpocoRepository<,>), typeof(NpocoRepositoryBase<,>), DependencyLifeStyle.Transient);
}
}
}
```
>然后是配置项的代码,
这里配置项的代码是写了一个字典,用于存储数据库,本来是想,如果有多个数据库,可以在配置时写入,在仓储配置时,写一下自己用的是哪个数据库,但是又发现,可能在后面需要使用这个数据库,比如事务的处理,所以这里仅用于传入默认的数据库。
```
using System;
using System.Collections.Generic;
using System.Text;
using NPoco;
namespace Abp.Npoco
{
public class AbpNpocoModuleConfig
{
public static Dictionary<string, Database> DatabaseDic = new Dictionary<string, Database>();
public void AddDb (string str,Database db)
{
DatabaseDic.Add(str, db);
}
}
}
```
>为方便完成配置,需要再写一个扩展类
```
using Abp.Configuration.Startup;
using System;
using System.Collections.Generic;
using System.Text;
namespace Abp.Npoco
{
public static class AbpNpocoModuleConfigurationiExtensions
{
public static AbpNpocoModuleConfig AbpNpocoModule(this IModuleConfigurations configuration)
{
return configuration.AbpConfiguration.Get<AbpNpocoModuleConfig>();
}
}
}
```
>到这里,基本配置就完成了,下面是仓储的代码部分
>首先定义接口INpocoRepository
```
using Abp.Domain.Repositories;
using System;
using System.Collections.Generic;
using System.Text;
using JetBrains.Annotations;
using Abp.Domain.Entities;
using NPoco;
namespace Abp.Npoco.Repository
{
/// <summary>
/// Dapper repository abstraction interface.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <typeparam name="TPrimaryKey">The type of the primary key.</typeparam>
/// <seealso cref="INpocoRepository{TEntity,TPrimaryKey}" />
public interface INpocoRepository<TEntity, TPrimaryKey> : IRepository where TEntity : class, IEntity<TPrimaryKey>
{
void SetDatabase(Database db);
/// <summary>
/// Gets the specified identifier.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns></returns>
[NotNull]
TEntity Single([NotNull] TPrimaryKey id);
bool Exists(TPrimaryKey id);
TEntity First(string sql, params object[] args);
TEntity First(string sql);
TEntity FirstOrDefault(string sql, params object[] args);
TEntity FirstOrDefault(string sql);
TEntity SingleById(TPrimaryKey id);
object Insert(TEntity entity);
int InsertBatch(IEnumerable<TEntity> entitys);
int Update(TEntity entity);
// public abstract int UpdateBatch(IEnumerable<TEntity> entitys);
int Delete(TEntity entity);
void Save(TEntity entity);
List<TEntity> Fetch();
List<TEntity> Fetch(string sql);
List<TEntity> Fetch(string sql, params object[] args);
Page<TEntity> Page(long page, int itemsPerPage, string sql);
Page<TEntity> Page(long page, int itemsPerPage, string sql, params object[] args);
IEnumerable<TEntity> Query(string sql, params object[] args);
IEnumerable<TEntity> Query(string sql);
int Execute(string sql, params object[] args);
int Execute(string sql);
}
}
```
>定义默认的主键是整型
```
using Abp.Domain.Entities;
using Abp.Domain.Repositories;
namespace Abp.Npoco.Repository
{
public interface INpocoRepository<TEntity> : INpocoRepository<TEntity, int> where TEntity : class, IEntity<int>
{
}
}
```
>定义抽象类AbpNpocoRepositoryBase
```
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Abp.Dependency;
using Abp.Domain.Entities;
using Abp.Domain.Uow;
using Abp.MultiTenancy;
using Abp.Reflection.Extensions;
using NPoco;
namespace Abp.Npoco.Repository
{
/// <summary>
/// Base class to implement <see cref="IDapperRepository{TEntity,TPrimaryKey}" />.
/// It implements some methods in most simple way.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <typeparam name="TPrimaryKey">The type of the primary key.</typeparam>
/// <seealso cref="IDapperRepository{TEntity,TPrimaryKey}" />
public abstract class AbpNpocoRepositoryBase<TEntity, TPrimaryKey> : INpocoRepository<TEntity, TPrimaryKey> where TEntity : class, IEntity<TPrimaryKey>
{
static AbpNpocoRepositoryBase()
{
var attr = typeof(TEntity).GetSingleAttributeOfTypeOrBaseTypesOrNull<MultiTenancySideAttribute>();
}
public abstract void SetDatabase(Database db);
public abstract bool Exists(TPrimaryKey id);
public abstract TEntity First(string sql, params object[] args);
public abstract TEntity First(string sql);
public abstract TEntity FirstOrDefault(string sql, params object[] args);
public abstract TEntity FirstOrDefault(string sql);
public abstract TEntity Single(TPrimaryKey id);
public abstract TEntity SingleById(TPrimaryKey id);
public abstract object Insert(TEntity entity);
public abstract int InsertBatch(IEnumerable<TEntity> entitys);
public abstract int Update(TEntity entity);
// public abstract int UpdateBatch(IEnumerable<TEntity> entitys);
public abstract int Delete(TEntity entity);
public abstract void Save(TEntity entity);
public abstract List<TEntity> Fetch();
public abstract List<TEntity> Fetch(string sql);
public abstract List<TEntity> Fetch(string sql, params object[] args);
public abstract Page<TEntity> Page(long page, int itemsPerPage, string sql);
public abstract Page<TEntity> Page(long page, int itemsPerPage, string sql, params object[] args);
public abstract IEnumerable<TEntity> Query(string sql, params object[] args);
public abstract IEnumerable<TEntity> Query(string sql);
public abstract int Execute(string sql, params object[] args);
public abstract int Execute(string sql);
public virtual Task<TEntity> SingleAsync(TPrimaryKey id)
{
return Task.FromResult(Single(id));
}
public virtual Task<TEntity> FirstAsync(string sql, params object[] args)
{
return Task.FromResult(First(sql, args));
}
public virtual Task<TEntity> FirstAsync(string sql)
{
return Task.FromResult(First(sql));
}
public virtual Task<TEntity> FirstOrDefaultAsync(string sql, params object[] args)
{
return Task.FromResult(FirstOrDefault(sql, args));
}
public virtual Task<TEntity> FirstOrDefaultAsync(string sql)
{
return Task.FromResult(FirstOrDefault(sql));
}
}
}
```
> 实现功能NpocoRepositoryBase
```
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using System.Data.SqlClient;
using NPoco.FluentMappings;
using Abp.Data;
using Abp.Domain.Entities;
using Abp.Domain.Uow;
using Abp.Events.Bus.Entities;
using NPoco;
using Abp.Configuration;
namespace Abp.Npoco.Repository
{
public class NpocoRepositoryBase<TEntity, TPrimaryKey> : AbpNpocoRepositoryBase<TEntity, TPrimaryKey>
where TEntity : class, IEntity<TPrimaryKey>
{
public NpocoRepositoryBase()
{
Database db = null;
AbpNpocoModuleConfig.DatabaseDic.TryGetValue("Default",out db);
Db = db;
}
public Database Db { get; set; }
public override void SetDatabase(Database db)
{
Db = db;
}
/// <summary>
/// Gets the active transaction. If Dapper is active then <see cref="IUnitOfWork" /> should be started before
/// and there must be an active transaction.
/// </summary>
/// <value>
/// The active transaction.
/// </value>
public override bool Exists(TPrimaryKey id )
{
return Db.Exists<TEntity>(id);
}
public override TEntity First(string sql, params object[] args)
{
return Db.First<TEntity>(sql, args);
}
public override TEntity First(string sql)
{
return Db.First<TEntity>(sql);
}
public override TEntity Single(TPrimaryKey id)
{
return Db.SingleById<TEntity>(id);
}
public override TEntity SingleById(TPrimaryKey id)
{
return Db.SingleById<TEntity>(id);
}
public override TEntity FirstOrDefault(string sql, params object[] args)
{
return Db.FirstOrDefault<TEntity>(sql, args);
}
public override TEntity FirstOrDefault(string sql)
{
return Db.FirstOrDefault<TEntity>(sql);
}
public override object Insert(TEntity entity)
{
return Db.Insert<TEntity>(entity);
}
public override int InsertBatch(IEnumerable<TEntity> entitys)
{
return Db.InsertBatch<TEntity>(entitys);
}
public override int Update(TEntity entity)
{
return Db.Update(entity);
}
public override int Delete(TEntity entity)
{
return Db.Delete(entity);
}
public override void Save(TEntity entity)
{
Db.Save(entity);
}
public override List<TEntity> Fetch()
{
return Db.Fetch<TEntity>();
}
public override List<TEntity> Fetch(string sql){
return Db.Fetch<TEntity>(sql);
}
public override List<TEntity> Fetch( string sql, params object[] args)
{
return Db.Fetch<TEntity>(sql,args);
}
public override Page<TEntity> Page(long page,int itemsPerPage,string sql)
{
return Db.Page<TEntity>(page, itemsPerPage, sql);
}
public override Page<TEntity> Page(long page, int itemsPerPage, string sql,params object[] args)
{
return Db.Page<TEntity>(page, itemsPerPage, sql, args);
}
public override IEnumerable<TEntity> Query(string sql, params object[] args)
{
return Db.Query<TEntity>(sql,args);
}
public override IEnumerable<TEntity> Query(string sql)
{
return Db.Query<TEntity>(sql);
}
public override int Execute(string sql, params object[] args)
{
return Db.Execute(sql, args);
}
public override int Execute(string sql)
{
return Db.Execute(sql);
}
}
}
```
>实现功能默认为整型的主键
```
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using System.Data.SqlClient;
using NPoco.FluentMappings;
using Abp.Data;
using Abp.Domain.Entities;
using Abp.Domain.Uow;
using Abp.Events.Bus.Entities;
using NPoco;
using Abp.Configuration;
namespace Abp.Npoco.Repository
{
public class NpocoRepositoryBase<TEntity> : NpocoRepositoryBase<TEntity, int>, INpocoRepository<TEntity>
where TEntity : class, IEntity<int>
{ }
}
```
>到这里,代码就完成了,后面是具体的引用了
一般情况下,引用时,这个可以放在一个单独的仓储层,也可以直接在应用层直接声明使用根据具体情况来看要怎么处理。
感觉比较简单的方式,是直接在应用层来用比较好,如果是要操作多个表或者库的,就在应用层处理,或者如果有必需,做一个领域层也可以。
>第一步,在模块中添加依赖,并配置数据库
![image.png](https://img.haomeiwen.com/i1727627/a606836cfb461424.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
添加数据库配置
```
var configuration = AppConfigurations.Get(WebContentDirectoryFinder.CalculateContentRootFolder());
string constr = configuration.GetConnectionString(DemoConsts.ConnectionStringName);
Database db = new Database(constr, DatabaseType.MySQL, MySqlClientFactory.Instance);
Configuration.Modules.AbpNpocoModule().AddDb("Default",db);
```
>在应用层声明和使用仓储
```
private readonly INpocoRepository<Person> personRepository;
PersonRepository per;
// private readonly INpocoRepository<Person> ptory;
public StaffAppService(INpocoRepository<Person> _personRepository, PersonRepository _per)
{
// _personDapperRepository = personDapperRepository;
personRepository = _personRepository;
// personRepository.SetDatabase(DataManager.GetDb());
per = _per;
}
```
也可以单独的写仓储层,如下所示
![image.png](https://img.haomeiwen.com/i1727627/aaa3f0df77e2a1b8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
```
namespace Demo.Repositorys
{
public class PersonRepository: NpocoRepositoryBase<Person>,IPersonRepository
{
public PersonRepository()
{
Db = DataManager.GetDb();
}
```
网友评论