開發筆記:用不用UnitOfWork以及Repository返回什么集合類型


這2天實際開發中明確的東西,在這篇博文中記錄一下。

之前對是否需要自己封裝UnitOfWork有些猶豫,因為Entity Framework就是一個UnitOfWork實現, 自己再封裝一下顯得有些多余。

但是在這次開發中,把涉及數據庫操作的實現代碼放在最后寫,先完成其他層的代碼。這種情況下,根本用不了EF,只能先Fake出一個UnitOfWork,這時必須要進行UnitOfWork的封裝。

所以,定義了IUnitOfWork接口並實現了一個FakeUnitOfWork,簡化的示例代碼如下:

IUnitOfWork

public interface IUnitOfWork : IDisposable
{
    TEntity Add<TEntity>(TEntity entity) where TEntity : class; 
    Task CommitAsync();
}

FakeUnitOfWork

public class FakeUnitOfWork : IUnitOfWoerk
{
    private IList _entities = new List<object>();

    public TEntity Add<TEntity>(TEntity entity) where TEntity : class
    {
        var property = typeof(TEntity).GetProperty("ID");
        if(property != null)
        {
            property.SetValue(entity, new Random().Next());
        }
        _entities.Add(entity);            
        return entity;
    } 

    public async Task CommitAsync()
    {
        var bits = Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(_entities, 
            Newtonsoft.Json.Formatting.Indented));
        using (var fs = new FileStream(
            path: @"C:\temp\FakeUnitOfWork.json", 
            mode: FileMode.Create, 
            access: FileAccess.Write, 
            share: FileShare.None, 
            bufferSize: 4096, 
            useAsync: true))
        {
            await fs.WriteAsync(bits, 0, bits.Length);
        }
    }
}

到寫數據庫操作代碼時,基於EF實現一下IUnitOfWork接口即可。

接下來是Repository返回集合類型的問題。

之前Repository接口多數返回的是IList<T>,這樣使用的一個考慮就是讓涉及數據庫查詢的操作盡量在Repository層完成,避免在Application層進行數據庫查詢操作。

但是今天在Application層的Service中用到了AutoMapper的Project功能,Project的好處是讓EF生成的SQL只查詢DTO中的字段,但Project擴展方法是針對(且只能針對)IQureryable<T>接口的,所以不得不將Repository接口的返回類型改為IQureryable<T>。

考慮到Project的巨大吸引力以及為了保持Repository返回類型的一致,以后Repository就都統一返回IQureryable<T>吧。

示例代碼如下:

IBlogCategoryRepository

public interface IBlogCategoryRepository
{
    Task<IQueryable<BlogCategory>> GetCategoriesByBlogId(int blogId, bool activeOnly);
}

BlogCategoryService

public class BlogCategoryService : IBlogCategoryService
{
    private IBlogCategoryRepository _blogCategoryRepository;

    public BlogCategoryServiceImp(IBlogCategoryRepository blogCategoryRepository)
    {
        _blogCategoryRepository = blogCategoryRepository;
    }

    async Task<IList<BlogCategoryDto>> IBlogCategoryService.GetCategoriesByBlogId(int blogId, bool activeOnly)
    {
        return (await _blogCategoryRepository
            .GetCategoriesByBlogId(blogId, activeOnly))
            .Project()
            .To<BlogCategoryDto>()
            .ToList();
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM