3

一些背景:我的应用程序中有多个层,其中两个是域层和用作我的 DAL 的基础设施层。在领域层,我已经实现了一个通用的存储库模式,如下所示:

    public interface IRepository<T, in TId> where T : IEntity<TId>
    {
        void Insert(T entity);
        void Delete(T entity);
        IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate);
        IQueryable<T> GetAll();
        T GetById(TId id);
    }

在我的 DAL 中,我实现了一个通用的 DAO 模式:

    public interface IDao<TEntity> where TEntity : class
    {
        IQueryable<TEntity> Select();
        IQueryable<TEntity> GetAll();
        IQueryable<TEntity> Where(Expression<Func<TEntity, bool>> predicate);
        TEntity GetSingle(Expression<Func<TEntity, bool>> predicate);
        TEntity GetFirst(Expression<Func<TEntity, bool>> predicate);
        void Add(TEntity entity);
        void Delete(TEntity entity);
        void Attach(TEntity entity);
    }

我有一个领域类,在商业术语中代表一个人。我的 DAL 层中有一个类似的单个对象,用于表示我的数据库中的对象。我有一个名为 EntityFrameworkDao 的类,它实现了我的 IDAO 接口,并负责在该 DAO 接口中找到的所有操作(CRUD 和上述一些其他操作)。

我正在尝试(尝试了几天)找到一种将存储库中使用的表达式映射到 DAL 中使用的表达式的方法。具体的例子是这样的:我有一个通用的 DomainRepository 实现了我的 IRepository 接口(见上文)。SearchFor 方法如下所示:

        public IQueryable<TDomainEntity> SearchFor(Expression<Func<TDomainEntity, bool>> predicate)
    {
        var convertedExpression = **SomeMagicFunctionToConvertExpressions**();
        var dataEntities = _dao.Where(convertedExpression);
        return AutoMapper.Mapper.Map<IEnumerable<TEfEntity>, IEnumerable<TDomainEntity>>(dataEntities).AsQueryable();
    }

我需要弄清楚 SomeMagicFunctionToConvertExpressions 是什么,以便我可以将域层中的谓词转换为 Where 方法可以在实现 IDao 的 DAL 类中理解的东西:

        public IQueryable<TEfEntity> Where(Expression<Func<TEfEntity, bool>> predicate)
        {
            return _context.Set<TEfEntity>().Where(predicate).AsQueryable();
        }

我尝试使用本文中找到的 Automapper 的 CreateMapExpression:AutoMapper for Func's between selector types

但这仅告诉我如何在Func<DomainType,bool>谓词与Func<DTOType,bool>(谓词)之间进行转换,而不是在表达式与表达式之间进行转换。我正在寻找一种方法来转换这样的东西:

Expression<Func<TDomainEntity, bool>> predicate

对此:

Expression<Func<TDAOEntity, bool>> predicate

在我找到这篇关于变异表达式树的文章后,我以为我正在做一些事情,但它不允许我传入包含 && 或 || 的 compex linq 表达式 或者比简单的 i => i.id.Equals(12345) 类型查询更复杂的任何内容。

我正在使用 Automapper,所以任何使用它的解决方案都会很棒,但我现在对任何想法持开放态度。我真的被困住了,现在已经研究了好几天了。这似乎是一项相当常见的任务:将基于类型的查询从架构中的一层转换为 DAL 中使用的类型。

在此先感谢您的帮助。

4

1 回答 1

2

你可能不应该这样做,看起来你把事情复杂化了。

第一:如果您使用通用存储库模式,您基本上违反了TDA原则;您正在创建对存储实现的直接依赖关系。在您的通用存储库上有一个“全部”、“按 ID”和“全文搜索”是很好的,但任何其他的都应该被您的界面隐藏。一个简单的例子:

repo.search(x=>x.IsActive==true)

假设这是一个简单的标志,后来不知何故您的域在某个地方发生了变化,并且您决定也可以软删除一个项目。这意味着您需要将域中任何地方的代码从前者更改为:

repo.search(x=>x.IsActive==true && x.IsDeleted == false)

正确的方法是在您的存储库上使用像这样的正确方法

repo.ActiveItems()

这可以确保您不会到处传播您的行为。

接下来,如果您要公开通用搜索,为什么不在您的领域模型中直接使用 Linq;毕竟,你仍然在你的 sql 对象的另一层上实现一层。你能解释一下添加这些额外层的附加价值吗?毕竟,它们仍然与相同的实现相关联(尽管它们可能在那里进行了一些额外的名称/值转换)。

于 2013-05-11T07:19:10.323 回答