1 應(yīng)用層(Application)
Application
|-- Dtos
|-- Services
1.1數(shù)據(jù)傳輸對象
序號 | 分類 | 名稱 | CRUD |
---|---|---|---|
1 | InputDto | CreateDictCategoryInput | C |
2 | InputDto | GetAllDictCategoryInput | R |
3 | InputDto | GetDictCategoryInfoInput | R |
4 | InputDto | UpdateDictCategoryInput | U |
5 | InputDto | DeleteDictCategoryInput | D |
6 | OutputDto | DictCategoryOutput | R |
7 | OutputDto | GetAllDictCategoryOutput | R |
1.1.1 CreateDictCategoryInput
using System;
namespace Boer.Cloud.Bas.Application.DictCategoryMgr.Dtos
{
public class CreateDictCategoryInput
{
public string CategoryName { get; set; }
public string ParentCategoryId { get; set; }
public string CategoryDesc { get; set; }
public DateTime? CreationTime { get; set; }
public string CreatorUserId { get; set; }
public DateTime? LastModificationTime { get; set; }
public string LastModifierUserId { get; set; }
public DateTime? DeletionTime { get; set; }
public string DeleterUserId { get; set; }
public int? IsDeleted { get; set; }
public int? Status { get; set; }
public int? DisOrder { get; set; }
}
}
1.1.2 GetAllDictCategoryInput
namespace Boer.Cloud.Bas.Application.DictCategoryMgr.Dtos
{
public class GetAllDictCategoryInput
{
public string Token { get; set; }
}
}
1.1.3 GetDictCategoryInfoInput
namespace Boer.Cloud.Bas.Application.DictCategoryMgr.Dtos
{
public class GetDictCategoryInfoInput
{
public string CategoryId { get; set; }
}
}
1.1.4 UpdateDictCategoryInput
namespace Boer.Cloud.Bas.Application.DictCategoryMgr.Dtos
{
public class UpdateDictCategoryInput : CreateDictCategoryInput
{
public string CategoryId { get; set; }
}
}
1.1.5 DeleteDictCategoryInput
namespace Boer.Cloud.Bas.Application.DictCategoryMgr.Dtos
{
public class DeleteDictCategoryInput
{
public string CategoryId { get; set; }
}
}
1.1.6 DictCategoryOutput
namespace Boer.Cloud.Bas.Application.DictCategoryMgr.Dtos
{
public class DictCategoryOutput : UpdateDictCategoryInput { }
}
1.1.7 GetAllDictCategoryOutput
using System.Collections.Generic;
namespace Boer.Cloud.Bas.Application.DictCategoryMgr.Dtos
{
public class GetAllDictCategoryOutput
{
public List<DictCategoryOutput> DictCategories { get; set; }
}
}
2 DTO和實(shí)體間的自動映射
2.1 CreateMap
CreateMap<CreateDictCategoryInput, DictCategory>();
CreateMap<UpdateDictCategoryInput, DictCategory>();
CreateMap<DeleteDictCategoryInput, DictCategory>();
CreateMap<DictCategory, DictCategoryOutput>();
2.2 Map
var entity = Mapper.Map<CreateDictCategoryInput, DictCategory>(model);
var entity = Mapper.Map<UpdateDictCategoryInput, DictCategory>(model);
var entity = Mapper.Map<DeleteDictCategoryInput, DictCategory>(model);
jsonMsg.Result = Mapper.Map<DictCategory, DictCategoryOutput>(entity);
jsonMsg.Result = Mapper.Map<List<DictCategoryOutput>>(entity);
3 依賴注入
維基百科說:“依賴注入是一種軟件設(shè)計(jì)模式,在這種模式下,一個(gè)或更多的依賴(或服務(wù))被注入(或者通過引用傳遞)到一個(gè)獨(dú)立的對象(或客戶端)中寞缝,然后成為了該客戶端狀態(tài)的一部分剩晴。該模式分離了客戶端依賴本身行為的創(chuàng)建,這使得程序設(shè)計(jì)變得松耦合鲤桥,并遵循了依賴反轉(zhuǎn)和單一職責(zé)原則箫锤。與服務(wù)定位器模式形成直接對比的是泞歉,它允許客戶端了解客戶端如何使用該系統(tǒng)找到依賴”。
3.1 依賴注入框架
微軟提供的Unity宇弛,引用Microsoft.Practices.Unity.dll
和Microsoft.Practices.Unity.Configuration.dll
3.2 構(gòu)造器注入
構(gòu)造器注入(Constructor Injection):IoC容器會智能地選擇選擇和調(diào)用適合的構(gòu)造函數(shù)以創(chuàng)建依賴的對象鸡典。如果被選擇的構(gòu)造函數(shù)具有相應(yīng)的參數(shù),IoC容器在調(diào)用構(gòu)造函數(shù)之前解析注冊的依賴關(guān)系并自行獲得相應(yīng)參數(shù)對象枪芒。
// AppService使用倉儲進(jìn)行數(shù)據(jù)庫操作轿钠,它通過構(gòu)造函數(shù)注入倉儲對象的引用
// 構(gòu)造函數(shù)自動注入我們所需要的類或接口
private readonly IUnitOfWork _uow = null;
private readonly IBasPolicy _policy = null;
public DictCategoryAppService(IUnitOfWork uow, IBasPolicy policy)
{
this._uow = uow;
this._policy = policy;
}
調(diào)用代碼
// 創(chuàng)建容器
var container = new UnityContainer();
// 注冊依賴對象
container.RegisterType<IDictCategoryAppService, DictCategoryAppService>(new HierarchicalLifetimeManager());
container.RegisterType<IUnitOfWork, Boer.Cloud.Bas.Domain.UnitOfWork.UnitOfWork>(new HierarchicalLifetimeManager());
container.RegisterType<IBasPolicy, BasPolicy>(new HierarchicalLifetimeManager());
2 領(lǐng)域?qū)?/h1>
2.1 倉儲
2.1.1 查詢
IRepository定義了通用的方法,從數(shù)據(jù)庫中檢索實(shí)體病苗。
2.1.1.1 獲得單個(gè)實(shí)體
TEntity Get(TPrimaryKey id);
Task<TEntity> GetAsync(TPrimaryKey id);
TEntity Single(Expression<Func<TEntity, bool>> predicate);
Task<TEntity> SingleAsync(Expression<Func<TEntity, bool>> predicate);
TEntity FirstOrDefault(TPrimaryKey id);
Task<TEntity> FirstOrDefaultAsync(TPrimaryKey id);
TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate);
Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate);
TEntity Load(TPrimaryKey id);
Get方法用于獲得一個(gè)給定主鍵(Id)的實(shí)體疗垛。如果在數(shù)據(jù)庫中沒有找到這個(gè)實(shí)體,就會拋出異常硫朦。Single方法和Get類似贷腕,但是它的參數(shù)是一個(gè)表達(dá)式而不是一個(gè)Id。因此咬展,你可以使用Lambda表達(dá)式獲得一個(gè)實(shí)體泽裳。樣例用法:
var person = _personRepository.Get(42);
var person = _personRepository.Single(p => p.Name == "Halil ?brahim Kalkan");
注意:如果根據(jù)給定的條件沒有查找出實(shí)體或者查出不止一個(gè)實(shí)體,那么Single方法會拋出異常破婆。
FirstOrDefault是相似的涮总,但是如果根據(jù)給的的Id或者表達(dá)式?jīng)]有找到實(shí)體,那么就會返回null祷舀。如果對于給定的條件存在不止一個(gè)實(shí)體瀑梗,那么會返回找到的第一個(gè)實(shí)體烹笔。
Load方法不會從數(shù)據(jù)庫中檢索實(shí)體,但是會創(chuàng)建一個(gè)用于懶加載的代理對象抛丽。如果你只用了Id屬性谤职,那么Entity實(shí)際上并沒有檢索到。只有你訪問實(shí)體的其他屬性亿鲜,才會從數(shù)據(jù)庫中檢索允蜈。考慮到性能因素蒿柳,這個(gè)就可以替換Get方法饶套。這在NHiberbate中也實(shí)現(xiàn)了。如果ORM提供者沒有實(shí)現(xiàn)它垒探,那么Load方法會和Get方法一樣地工作凤跑。
一些方法有用于async編程模型的異步(async)版本。
2.1.1.2 獲得實(shí)體的列表
List<TEntity> GetAllList();
Task<List<TEntity>> GetAllListAsync();
List<TEntity> GetAllList(Expression<Func<TEntity, bool>> predicate);
Task<List<TEntity>> GetAllListAsync(Expression<Func<TEntity, bool>> predicate);
IQueryable<TEntity> GetAll();
GetAllList從數(shù)據(jù)庫中檢索所有的實(shí)體叛复。該方法的重載可以用于過濾實(shí)體仔引。例子如下:
var allPeople = _personRepository.GetAllList();
var somePeople = _personRepository.GetAllList(person => person.IsActive && person.Age > 42);
GetAll返回的類型是IQueryable。因此褐奥,你可以在此方法之后添加Linq方法咖耘。例子如下:
//Example 1
var query = from person in _personRepository.GetAll()
where person.IsActive
orderby person.Name
select person;
var people = query.ToList();
//Example 2:
List<Person> personList2 = _personRepository.GetAll().Where(p => p.Name.Contains("H")).OrderBy(p => p.Name).Skip(40).Take(20).ToList();
有了GetAll方法,幾乎所有的查詢都可以使用Linq重寫撬码。甚至可以用在一個(gè)連接表達(dá)式中儿倒。
關(guān)于IQueryable
脫離了倉儲方法調(diào)用GetAll()方法時(shí),數(shù)據(jù)庫連接必須要打開呜笑。這是因?yàn)镮Queryable的延遲執(zhí)行夫否。直到調(diào)用ToList()方法或者在foreach循環(huán)中使用IQueryable(或者訪問查詢到的元素)時(shí),才會執(zhí)行數(shù)據(jù)庫查詢操作叫胁。因此凰慈,當(dāng)調(diào)用ToList()方法時(shí)。數(shù)據(jù)庫連接必須打開驼鹅。這可以通過ABP中的UnitOfWork特性標(biāo)記調(diào)用者方法來實(shí)現(xiàn)微谓。注意:應(yīng)用服務(wù)方法默認(rèn)已經(jīng)是UnitOfWork,因此输钩,即使沒有為應(yīng)用服務(wù)層方法添加UnitOfWork特性豺型,GetAll()方法也會正常工作。
這些方法也存在用于異步編程模型的asyn版本买乃。
2.1.1.3 自定義返回值
也存在提供了IQueryable的額外方法姻氨,在調(diào)用的方法中不需要使用UnitOfWork。
T Query<T>(Func<IQueryable<TEntity>, T> queryMethod);
Query方法接受一個(gè)接收IQueryable的lambda(或方法)剪验,并返回任何對象的類型肴焊。例子如下:
var people = _personRepository.Query(q => q.Where(p => p.Name.Contains("H")).OrderBy(p => p.Name).ToList());
在該倉儲方法中前联,因?yàn)閳?zhí)行了給定的lambda(或方法),它是在數(shù)據(jù)庫連接打開的時(shí)候執(zhí)行的抖韩。你可以返回實(shí)體列表蛀恩,單個(gè)實(shí)體疫铜,一個(gè)投影或者執(zhí)行了該查詢的其他東西茂浮。
2.1.2 插入
IRepository接口定義了將一個(gè)實(shí)體插入數(shù)據(jù)庫的簡單方法:
TEntity Insert(TEntity entity);
Task<TEntity> InsertAsync(TEntity entity);
TPrimaryKey InsertAndGetId(TEntity entity);
Task<TPrimaryKey> InsertAndGetIdAsync(TEntity entity);
TEntity InsertOrUpdate(TEntity entity);
Task<TEntity> InsertOrUpdateAsync(TEntity entity);
TPrimaryKey InsertOrUpdateAndGetId(TEntity entity);
Task<TPrimaryKey> InsertOrUpdateAndGetIdAsync(TEntity entity);
Insert方法簡化了將一個(gè)實(shí)體插入數(shù)據(jù)庫,并將剛剛插入的實(shí)體返回壳咕。
InsertAndGetId方法返回了新插入實(shí)體的Id席揽。如果實(shí)體的Id是自動增長的并且需要最新插入實(shí)體的Id那伐,那么該方法很有用品嚣。InsertOrUpdate方法通過檢查Id的值插入或更新給定的實(shí)體。最后癌淮,當(dāng)插入或者更新之后竟稳,InsertOrUpdateAndGetId返回該實(shí)體的值属桦。
所有的方法都存在用于異步編程模型的async版本。
2.1.3 更新
IRepository定義了一個(gè)方法來更新數(shù)據(jù)庫中已存在的實(shí)體他爸。它可以獲得要更新的實(shí)體并返回相同的實(shí)體對象聂宾。
TEntity Update(TEntity entity);
Task<TEntity> UpdateAsync(TEntity entity);
2.1.4 刪除
IRepository定義了從數(shù)據(jù)庫中刪除一個(gè)已存在的實(shí)體的方法。
void Delete(TEntity entity);
Task DeleteAsync(TEntity entity);
void Delete(TPrimaryKey id);
Task DeleteAsync(TPrimaryKey id);
void Delete(Expression<Func<TEntity, bool>> predicate);
Task DeleteAsync(Expression<Func<TEntity, bool>> predicate);
第一個(gè)方法接受一個(gè)已存在的實(shí)體诊笤,第二個(gè)方法接受一個(gè)要刪除的實(shí)體的Id系谐。
最后一個(gè)方法接受一個(gè)刪除符合給定條件的所有實(shí)體的方法。注意讨跟,匹配給定謂詞的所有實(shí)體都會從數(shù)據(jù)庫中檢索到然后被刪除纪他。因此,小心使用它晾匠,如果給定的條件存在太多的實(shí)體茶袒,那么可能會造成性能問題。
2.1.5 其他
IRepository也提供了獲得表中實(shí)體數(shù)量的方法凉馆。
int Count();
Task<int> CountAsync();
int Count(Expression<Func<TEntity, bool>> predicate);
Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate);
long LongCount();
Task<long> LongCountAsync();
long LongCount(Expression<Func<TEntity, bool>> predicate);
Task<long> LongCountAsync(Expression<Func<TEntity, bool>> predicate);
2.1.6 關(guān)于異步方法
支持異步編程模型(APM)弹谁。因此,倉儲方法有異步版本句喜。下面是一個(gè)使用了異步模型的應(yīng)用服務(wù)方法樣例:
public class PersonAppService : AbpWpfDemoAppServiceBase, IPersonAppService
{
private readonly IRepository<Person> _personRepository;
public PersonAppService(IRepository<Person> personRepository)
{
_personRepository = personRepository;
}
public async Task<GetPeopleOutput> GetAllPeople()
{
var people = await _personRepository.GetAllListAsync();
return new GetPeopleOutput
{
People = Mapper.Map<List<PersonDto>>(people)
};
}
}
GetAllPeople方法是異步的预愤,并使用了具有await關(guān)鍵字的GetAllListAsync方法。
也許不是所有的ORM框架都支持Async咳胃,但是EntityFramework支持植康。如果不支持,異步倉儲方法就會同步進(jìn)行展懈。比如销睁,在EF中供璧,InsertAsync和Insert是等效的,因?yàn)橹钡焦ぷ鲉卧瓿桑―bcontext.SaveChanges)冻记,EF才會將新的實(shí)體寫入數(shù)據(jù)庫睡毒。
工作單元
如何處理多個(gè)Repository庫?
下面想象下如下場景冗栗,我們數(shù)據(jù)庫中有多個(gè)表演顾,那樣我們需要為每個(gè)表創(chuàng)建一個(gè)Reporsitory類。(好多重復(fù)工作的說隅居,其實(shí)這不是問題)
問題是關(guān)于 數(shù)據(jù)上下文(DbContext) 對象的钠至。如果我們創(chuàng)建多個(gè)Repository類,是不是每一個(gè)都單獨(dú)的包含一個(gè) 數(shù)據(jù)上下文對象胎源?我們知道同時(shí)使用多個(gè) 數(shù)據(jù)上下文 會存在問題棉钧,那我們該怎么處理每個(gè)Repository都擁有自己的數(shù)據(jù)上下文 對象的問題?
來解決這個(gè)問題吧涕蚤。為什么每個(gè)Repository要擁有一個(gè)數(shù)據(jù)上下文的實(shí)例呢宪卿?為什么不在一些地方創(chuàng)建一個(gè)它的實(shí)例,然后在repository被實(shí)例化的時(shí)候作為參數(shù)傳遞進(jìn)去呢⊥蛘ぃ現(xiàn)在這個(gè)新的類被命名為 UnitOfWork 佑钾,此類將負(fù)責(zé)創(chuàng)建數(shù)據(jù)上下文實(shí)例并移交到控制器的所有repository實(shí)例。
IUnitOfWork.cs
using Boer.Cloud.Bas.Domain.Repositories;
using System;
namespace Boer.Cloud.Bas.Domain.UnitOfWork
{
public interface IUnitOfWork : IDisposable
{
IBasRepositoryBase<T> Repository<T>() where T : class;
void SaveChanges();
}
}
UnitOfWork.cs
using Boer.Cloud.Bas.Domain.Repositories;
using Boer.Cloud.Bas.EntityFramework;
using Boer.Cloud.Bas.EntityFramework.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Boer.Cloud.Bas.Domain.UnitOfWork
{
public class UnitOfWork : IUnitOfWork
{
private BasDbContext dbContext = null;
public UnitOfWork()
{
dbContext = new BasDbContext();
}
public Dictionary<Type, object> repositories = new Dictionary<Type, object>();
public IBasRepositoryBase<T> Repository<T>() where T : class
{
// 檢查倉儲類是否已經(jīng)創(chuàng)建申钩,如果存在將返回一個(gè)實(shí)例次绘,
// 否則將創(chuàng)建一個(gè)新的實(shí)例。
if (repositories.Keys.Contains(typeof(T)) == true)
{
return repositories[typeof(T)] as IBasRepositoryBase<T>;
}
IBasRepositoryBase<T> repo = new BasRepositoryBase<T>(dbContext);
repositories.Add(typeof(T), repo);
return repo;
}
public void SaveChanges()
{
dbContext.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
dbContext.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
倉儲
IBasRepositoryBase.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
namespace Boer.Cloud.Bas.Domain.Repositories
{
public interface IBasRepositoryBase<T> where T : class
{
void OnBeforeInsert(T entity);
void OnAfterInsert(T entity);
void OnBeforeUpdate(T entity);
void OnAfterUpdate(T entity);
void OnBeforeDelete(T entity);
void OnAfterDelete(T entity);
#region 獲得實(shí)體的列表
List<T> GetAllList();
Task<List<T>> GetAllListAsync();
Task<List<T>> GetAllListAsync(Expression<Func<T, bool>> predicate);
IQueryable<T> GetAll();
IEnumerable<T> GetAll(Expression<Func<T, bool>> predicate = null);
#endregion
#region 獲取實(shí)體的列表撒遣,支持分頁
IEnumerable<T> Get(string orderBy, int pageIndex, int pageSize);
IEnumerable<T> Get(Expression<Func<T, bool>> predicate, string orderBy, int pageIndex, int pageSize);
#endregion
#region 獲得單個(gè)實(shí)體
T Single(Expression<Func<T, bool>> predicate);
Task<T> SingleAsync(Expression<Func<T, bool>> predicate);
T FirstOrDefault(Expression<Func<T, bool>> predicate);
Task<T> FirstOrDefaultAsync(Expression<Func<T, bool>> predicate);
#endregion
#region 插入
T Insert(T entity);
Task<T> InsertAsync(T entity);
#endregion
#region 更新
T Update(T entity);
Task<T> UpdateAsync(T entity);
#endregion
#region 刪除
void Delete(T entity);
Task DeleteAsync(T entity);
void Delete(Expression<Func<T, bool>> predicate);
Task DeleteAsync(Expression<Func<T, bool>> predicate);
#endregion
#region 其他
int Count();
Task<int> CountAsync();
int Count(Expression<Func<T, bool>> predicate);
Task<int> CountAsync(Expression<Func<T, bool>> predicate);
long LongCount();
Task<long> LongCountAsync();
long LongCount(Expression<Func<T, bool>> predicate);
Task<long> LongCountAsync(Expression<Func<T, bool>> predicate);
#endregion
}
}
BasRepositoryBase.cs
using Boer.Cloud.Bas.Domain.Repositories;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Dynamic;
using System.Linq.Expressions;
using System.Threading.Tasks;
namespace Boer.Cloud.Bas.EntityFramework.Repositories
{
public class BasRepositoryBase<T> : IBasRepositoryBase<T> where T : class
{
private BasDbContext dbContext = null;
public virtual DbSet<T> Table { get { return dbContext.Set<T>(); } }
public BasRepositoryBase(BasDbContext _dbContext)
{
dbContext = _dbContext;
}
public virtual void OnBeforeInsert(T entity){ }
public virtual void OnAfterInsert(T entity) { }
public virtual void OnBeforeUpdate(T entity) { }
public virtual void OnAfterUpdate(T entity) { }
public virtual void OnBeforeDelete(T entity) { }
public virtual void OnAfterDelete(T entity) { }
#region 獲得實(shí)體的列表
public IQueryable<T> GetAll()
{
return Table;
}
public List<T> GetAllList()
{
return GetAll().ToList();
}
public async Task<List<T>> GetAllListAsync()
{
return await GetAll().ToListAsync();
}
public async Task<List<T>> GetAllListAsync(Expression<Func<T, bool>> predicate)
{
return await GetAll().Where(predicate).ToListAsync();
}
public IEnumerable<T> GetAll(Expression<Func<T, bool>> predicate = null)
{
if (predicate != null)
{
return Table.Where(predicate);
}
return Table.AsEnumerable();
}
#endregion
#region 獲取實(shí)體的列表邮偎,支持分頁
public IEnumerable<T> Get(string orderBy, int pageIndex, int pageSize)
{
return
GetAll()
.OrderBy(orderBy)
.Skip((pageIndex - 1) * pageSize)
.Take(pageSize)
.AsEnumerable();
}
public IEnumerable<T> Get(Expression<Func<T, bool>> predicate,
string orderBy, int pageIndex, int pageSize)
{
return
GetAll().Where(predicate)
.OrderBy(orderBy)
.Skip((pageIndex - 1) * pageSize)
.Take(pageSize)
.AsEnumerable();
}
#endregion
#region 獲得單個(gè)實(shí)體
public T Single(Expression<Func<T, bool>> predicate)
{
return GetAll().Single(predicate);
}
public async Task<T> SingleAsync(Expression<Func<T, bool>> predicate)
{
return await GetAll().SingleAsync(predicate);
}
public T FirstOrDefault(Expression<Func<T, bool>> predicate)
{
return GetAll().FirstOrDefault(predicate);
}
public async Task<T> FirstOrDefaultAsync(Expression<Func<T, bool>> predicate)
{
return await GetAll().FirstOrDefaultAsync(predicate);
}
#endregion
#region 插入
public T Insert(T entity)
{
return Table.Add(entity);
}
public Task<T> InsertAsync(T entity)
{
return Task.FromResult(Table.Add(entity));
}
#endregion
#region 更新
public T Update(T entity)
{
AttachIfNot(entity);
dbContext.Entry(entity).State = EntityState.Modified;
return entity;
}
public Task<T> UpdateAsync(T entity)
{
AttachIfNot(entity);
dbContext.Entry(entity).State = EntityState.Modified;
return Task.FromResult(entity);
}
#endregion
#region 刪除
public void Delete(T entity)
{
AttachIfNot(entity);
Table.Remove(entity);
}
public Task DeleteAsync(T entity)
{
Delete(entity);
return Task.FromResult(0);
}
public void Delete(Expression<Func<T, bool>> predicate)
{
foreach (var entity in GetAll().Where(predicate).ToList())
{
Delete(entity);
}
}
public async Task DeleteAsync(Expression<Func<T, bool>> predicate)
{
Delete(predicate);
}
#endregion
#region 其他
public int Count()
{
return GetAll().Count();
}
public async Task<int> CountAsync()
{
return await GetAll().CountAsync();
}
public int Count(Expression<Func<T, bool>> predicate)
{
return GetAll().Where(predicate).Count();
}
public async Task<int> CountAsync(Expression<Func<T, bool>> predicate)
{
return await GetAll().Where(predicate).CountAsync();
}
public long LongCount()
{
return GetAll().LongCount();
}
public async Task<long> LongCountAsync()
{
return await GetAll().LongCountAsync();
}
public long LongCount(Expression<Func<T, bool>> predicate)
{
return GetAll().Where(predicate).LongCount();
}
public async Task<long> LongCountAsync(Expression<Func<T, bool>> predicate)
{
return await GetAll().Where(predicate).LongCountAsync();
}
#endregion
protected virtual void AttachIfNot(T entity)
{
if (!Table.Local.Contains(entity))
{
Table.Attach(entity);
}
}
}
}
創(chuàng)建DbContext
提到DbContext,對于經(jīng)常使用DbFirst模式的開發(fā)者來說已經(jīng)再熟悉不過了,EntityFramework全靠這員大將义黎。它的作用是代表與數(shù)據(jù)庫連接的會話禾进,提供了查詢、狀態(tài)跟蹤廉涕、保存等功能泻云。
還有一個(gè)重要的對象是DbSet,對實(shí)體類型提供了集合操作狐蜕,比如Add宠纯、Attach、Remove层释。繼承了DbQuery婆瓜,所以可以提供查詢功能。
BasDbContext.cs
using Boer.Cloud.Bas.Domain.Entities;
using Boer.Cloud.Bas.EntityFramework.Mapping;
using Boer.Cloud.Core.Helper;
using System;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Diagnostics;
namespace Boer.Cloud.Bas.EntityFramework
{
public class BasDbContext : DbContext
{
public BasDbContext()
: base("name=DefaultDBConnection")
{
Database.SetInitializer<BasDbContext>(null);
this.Database.Log = new Action<string>(q => Debug.WriteLine(q));
}
#region Property
public virtual IDbSet<AreaCategory> AreaCategories { get; set; }
public virtual IDbSet<DictCategory> DictCategories { get; set; }
public virtual IDbSet<Dict> Dicts { get; set; }
#endregion
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// 設(shè)置禁用一對多級聯(lián)刪除
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
// 設(shè)置Schema
modelBuilder.HasDefaultSchema(Config.GetValue("DefaultSchema", "BOER"));
#region BasMapping
modelBuilder.Configurations.Add(new AreaCategoryMap());
modelBuilder.Configurations.Add(new DictCategoryMap());
modelBuilder.Configurations.Add(new DictMap());
#endregion
}
}
}
應(yīng)用服務(wù)
IAreaCategoryAppService.cs
using Boer.Cloud.Bas.Application.AreaCategoryMgr.Dtos;
using Boer.Cloud.Core.Dto;
using System.Threading.Tasks;
namespace Boer.Cloud.Bas.Application.AreaCategoryMgr
{
public interface IAreaCategoryAppService
{
Task<JsonMessage> Create(CreateAreaCategoryInput model);
Task<JsonMessage> Update(UpdateAreaCategoryInput model);
Task<JsonMessage> Delete(DeleteAreaCategoryInput model);
Task<JsonMessage> GetInfo(GetAreaCategoryInfoInput model);
JsonMessage GetAll(GetAllAreaCategoryInput model);
}
}
AreaCategoryAppService.cs
using AutoMapper;
using Boer.Cloud.Bas.Application.AreaCategoryMgr.Dtos;
using Boer.Cloud.Bas.Domain.Entities;
using Boer.Cloud.Bas.Domain.Policies;
using Boer.Cloud.Bas.Domain.UnitOfWork;
using Boer.Cloud.Core.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Boer.Cloud.Bas.Application.AreaCategoryMgr
{
public class AreaCategoryAppService : IAreaCategoryAppService
{
private readonly IUnitOfWork _uow = null;
private readonly IBasPolicy _policy = null;
public AreaCategoryAppService(IUnitOfWork uow, IBasPolicy policy)
{
this._uow = uow;
this._policy = policy;
}
public async Task<JsonMessage> Create(CreateAreaCategoryInput model)
{
var entity = Mapper.Map<CreateAreaCategoryInput, AreaCategory>(model);
entity.AreaId = Guid.NewGuid().ToString("N").ToUpper();
await _uow.Repository<AreaCategory>().InsertAsync(entity);
_uow.SaveChanges();
return _policy.GetErrorMsgByErrCode(0);
}
public async Task<JsonMessage> Update(UpdateAreaCategoryInput model)
{
if (string.IsNullOrEmpty(model.AreaId))
return _policy.GetErrorMsgByErrCode(20601003);
var entity = Mapper.Map<UpdateAreaCategoryInput, AreaCategory>(model);
await _uow.Repository<AreaCategory>().UpdateAsync(entity);
_uow.SaveChanges();
return _policy.GetErrorMsgByErrCode(0);
}
public async Task<JsonMessage> Delete(DeleteAreaCategoryInput model)
{
if (string.IsNullOrEmpty(model.AreaId))
return _policy.GetErrorMsgByErrCode(20601003);
if (_policy.IsExistsByParentAreaId(model.AreaId))
return _policy.GetErrorMsgByErrCode(20601004);
if (_policy.IsNullByAreaCategories(model.AreaId))
return _policy.GetErrorMsgByErrCode(20601002);
await _uow.Repository<AreaCategory>().DeleteAsync(b => b.AreaId == model.AreaId);
_uow.SaveChanges();
return _policy.GetErrorMsgByErrCode(0);
}
public async Task<JsonMessage> GetInfo(GetAreaCategoryInfoInput model)
{
if (string.IsNullOrEmpty(model.AreaId))
return _policy.GetErrorMsgByErrCode(20601003);
if (_policy.IsNullByAreaCategories(model.AreaId))
return _policy.GetErrorMsgByErrCode(20601002);
var entity = await _uow.Repository<AreaCategory>().SingleAsync(b => b.AreaId == model.AreaId);
JsonMessage jsonMsg = _policy.GetErrorMsgByErrCode(0);
jsonMsg.Result = Mapper.Map<AreaCategory, AreaCategoryOutput>(entity);
return jsonMsg;
}
public JsonMessage GetAll(GetAllAreaCategoryInput model)
{
var entity = _uow.Repository<AreaCategory>().GetAll().OrderBy(item => item.AreaCode).ToList();
JsonMessage jsonMsg = _policy.GetErrorMsgByErrCode(0);
jsonMsg.Result = Mapper.Map<List<AreaCategoryOutput>>(entity);
return jsonMsg;
}
}
}