【问题标题】:c# Repository pattern and where lambdas, how to convert typec#存储库模式和lambdas,如何转换类型
【发布时间】:2016-06-22 10:05:21
【问题描述】:

我正在尝试使用数据传输对象和单独的数据提供者构建一个实体框架抽象存储库。我们需要能够根据安装在 oracle、sql server 和 azure sql 之间切换。

最终存储库将 DTO 返回给消费代码。获取、更新和删除工作正常。我遇到的问题是用于 where 子句等的 lambda。通用存储库不知道来自数据提供者的实际 Entity 对象,因此我无法创建 where lambda。

附:使用 AutoMapper 在 Entity 和 DTO 之间进行转换

//Repository base
public class Repository<TEntity> : IDisposable, IRepository<TEntity> where TEntity : class, IEntity
{
    public virtual IList<TEntity> GetList(Func<TEntity, bool> where, params Expression<Func<TEntity, object>>[] navigationProperties)
    {
        List<TEntity> list;

        IQueryable<TEntity> dbQuery = Context.Set<TEntity>();

        //Apply eager loading
        foreach (Expression<Func<TEntity, object>> navigationProperty in navigationProperties)
            dbQuery = dbQuery.Include<TEntity, object>(navigationProperty);

        list = dbQuery
            .AsNoTracking()
            .Where(where)
            .ToList<TEntity>();

        return list;
    }
}

//Implementing repository where T is the entity from the EF model
public class UserRepository<T> : IUserRepository, IUnitOfWork
    where T : class, IEntity
{
    public Repository<T> Base { get; private set; }

    public UserRepository(DbContext context)
    {
        Base = new Repository<T>(context);
    }

    public List<UserAccountDTO> GetList(Expression<Func<UserAccountDTO, bool>> where)
        {
            T obj = SupportedRepos.DTOMapper.Map<T>(where.Parameters[0]);
                /* HOW CAN I CONVERT THE FUNC<>? */
                //Base.GetList();
                return null;
        }
    }

public void TestMethod1()
{
    var dbtypeFromConfig = RepoEF.Setup.StorageType.SQLServer;

    using (var repo = RepoEF.Setup.SupportedRepos.Create(dbtypeFromConfig))
    {
        //WORKS FINE, CHANGES AND UPDATES
        var source = repo.Get(3);
        source.LookupId = 111111;
        repo.Add(source);

        //CAN'T CREATE WHERE BECAUSE UserRepository<T> ONLY SEES IEntity
        repo.GetList(x => x.UserAccountId == 3);
    }
}

是否可以构建一个 Func 以传递给基础存储库。

如果没有任何想法,我该如何更改设计以实现我的需要?

【问题讨论】:

    标签: c# entity-framework repository dto


    【解决方案1】:

    也许我可以深入研究您当前的存储库模式实现并尝试修复它,但我相信,毕竟有许多设计缺陷会迫使您完全重构您的解决方案。

    所以我会给你一些提示:

    1) 存储库仍然是,因此它始终与域对象一起使用

    域不应与 DTO 一起使用。当您想要在逻辑或物理边界之间传输数据时,您可以使用 DTO 模式。例如,当域服务需要向应用服务提供一些域对象的列表时。该列表将作为域对象列表的 DTO 公开。

    2)数据库技术switch是数据映射层(即Entity Framework)的职责。

    您的存储库应与数据库技术保持无关,并与 OR/M 框架相结合。

    3) 如果一个用户存储库IS是一个存储库,你应该使用继承而不是组合

    因此,UserRepository 应该同时实现 IUserRepository 并派生自 Repository&lt;User&gt;

    4) 具体存储库不应接受泛型类型参数来提供要处理的域对象

    归根结底,像IUserRepository 这样的具体存储库会处理User 的实例,因此,为什么需要TEntity 通用参数?既然你有这个设计缺陷,TEntity 就不是T...这就是您要解决的问题背后的原因...

    【讨论】:

    • 感谢 Matias,我不得不根据您的建议重新设计,但现在可以正常工作了。现在遇到了多个 DbConfigurations 的问题,只有第一个使用的有效,第二个错误。 :|
    • @fruitbatinshades 不客气!顺便说一句,您是在使用控制容器的反转还是什么?
    • 是的,使用 AutoFac。解决了 EF 的多重配置问题。您只能有一个配置类,并且必须在其中加载所有必需的提供程序。
    猜你喜欢
    • 2015-10-06
    • 2018-10-30
    • 1970-01-01
    • 2018-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多