因为一直使用的Npoco,希望中以把Npoco作为abp的数据访问层,具体要如何实现呢?
中间要用到注入,配置,模块等各种abp的知识,因为对abp的源码并不是特别熟悉,反复的看了很多文章,终于可以把逻辑搞明白了,在这里记录一下。
参考dapper,首先是模块的定义,
总体看一下
![image.png](https://upload-images.jianshu.io/upload_images/1727627-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
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
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
}
}
}
```
>到这里,基本配置就完成了,下面是仓储的代码部分
>首先定义接口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
{
///
/// Dapper repository abstraction interface.
///
///
///
///
public interface INpocoRepository
{
void SetDatabase(Database db);
///
/// Gets the specified identifier.
///
/// The identifier.
///
[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
int Update(TEntity entity);
// public abstract int UpdateBatch(IEnumerable
int Delete(TEntity entity);
void Save(TEntity entity);
List
List
List
Page
Page
IEnumerable
IEnumerable
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
{
}
}
```
>定义抽象类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
{
///
/// Base class to implement
/// It implements some methods in most simple way.
///
///
///
///
public abstract class AbpNpocoRepositoryBase
{
static AbpNpocoRepositoryBase()
{
var attr = typeof(TEntity).GetSingleAttributeOfTypeOrBaseTypesOrNull
}
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
public abstract int Update(TEntity entity);
// public abstract int UpdateBatch(IEnumerable
public abstract int Delete(TEntity entity);
public abstract void Save(TEntity entity);
public abstract List
public abstract List
public abstract List
public abstract Page
public abstract Page
public abstract IEnumerable
public abstract IEnumerable
public abstract int Execute(string sql, params object[] args);
public abstract int Execute(string sql);
public virtual Task
{
return Task.FromResult(Single(id));
}
public virtual Task
{
return Task.FromResult(First(sql, args));
}
public virtual Task
{
return Task.FromResult(First(sql));
}
public virtual Task
{
return Task.FromResult(FirstOrDefault(sql, args));
}
public virtual Task
{
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
where TEntity : class, IEntity
{
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;
}
///
/// Gets the active transaction. If Dapper is active then
/// and there must be an active transaction.
///
///
/// The active transaction.
///
public override bool Exists(TPrimaryKey id )
{
return Db.Exists
}
public override TEntity First(string sql, params object[] args)
{
return Db.First
}
public override TEntity First(string sql)
{
return Db.First
}
public override TEntity Single(TPrimaryKey id)
{
return Db.SingleById
}
public override TEntity SingleById(TPrimaryKey id)
{
return Db.SingleById
}
public override TEntity FirstOrDefault(string sql, params object[] args)
{
return Db.FirstOrDefault
}
public override TEntity FirstOrDefault(string sql)
{
return Db.FirstOrDefault
}
public override object Insert(TEntity entity)
{
return Db.Insert
}
public override int InsertBatch(IEnumerable
{
return Db.InsertBatch
}
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
{
return Db.Fetch
}
public override List
return Db.Fetch
}
public override List
{
return Db.Fetch
}
public override Page
{
return Db.Page
}
public override Page
{
return Db.Page
}
public override IEnumerable
{
return Db.Query
}
public override IEnumerable
{
return Db.Query
}
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
where TEntity : class, IEntity
{ }
}
```
>到这里,代码就完成了,后面是具体的引用了
一般情况下,引用时,这个可以放在一个单独的仓储层,也可以直接在应用层直接声明使用根据具体情况来看要怎么处理。
感觉比较简单的方式,是直接在应用层来用比较好,如果是要操作多个表或者库的,就在应用层处理,或者如果有必需,做一个领域层也可以。
>第一步,在模块中添加依赖,并配置数据库
![image.png](https://upload-images.jianshu.io/upload_images/1727627-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
PersonRepository per;
// private readonly INpocoRepository
public StaffAppService(INpocoRepository
{
// _personDapperRepository = personDapperRepository;
personRepository = _personRepository;
// personRepository.SetDatabase(DataManager.GetDb());
per = _per;
}
```
也可以单独的写仓储层,如下所示
![image.png](https://upload-images.jianshu.io/upload_images/1727627-aaa3f0df77e2a1b8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
```
namespace Demo.Repositorys
{
public class PersonRepository: NpocoRepositoryBase
{
public PersonRepository()
{
Db = DataManager.GetDb();
}
```