简体   繁体   English

c#存储库模式以及lambdas在哪里,如何转换类型

[英]c# Repository pattern and where lambdas, how to convert type

I'm trying to build an Entity framework abstract repository with data transfer objects and separate data providers. 我正在尝试使用数据传输对象和单独的数据提供程序来构建实体框架抽象存储库。 We need to be able to switch between oracle, sql server and azure sql depending on the install. 我们需要能够根据安装在oracle,sql server和azure sql之间进行切换。

The end repository returns DTO's to the consuming code. 最终存储库将DTO返回到使用代码。 Get, Update and delete are working fine. 获取,更新和删除工作正常。 The issue I'm having is with the lambdas for where clauses etc. The generic repository is unaware of the actual Entity object from the data provider so I can't create a where lambda. 我遇到的问题是where子句等的lambda。通用存储库无法识别数据提供者提供的实际Entity对象,因此无法创建where lambda。

PS Using AutoMapper to convert between Entity and DTO PS使用AutoMapper在实体和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);
    }
}

Is it possible to build a Func<> to pass to the base Repository. 是否可以构建Func <>传递给基础存储库。

If not any ideas how I change the design to achieve what I need? 如果没有任何想法,我如何更改设计以实现所需?

Perhaps I could dig into your current implementation of repository pattern and try to fix it, but I believe that, after all, there're many design flaws that will force you to completely refactor your solution. 也许我可以深入研究您当前的存储库模式实现并尝试对其进行修复,但是我相信毕竟存在许多设计缺陷,这些缺陷会迫使您完全重构您的解决方案。

So I'll give you some hints: 所以我给你一些提示:

1) A repository is still domain , thus it always work with domain objects 1)存储库仍然是domain ,因此它总是与domain对象一起工作

Domain shouldn't work with DTOs. 域不能与DTO一起使用。 You use DTO pattern when you want to transfer data between logical or physical boundaries. 当您想在逻辑或物理边界之间传输数据时,可以使用DTO模式。 For example, when a domain service need to provide a list of some domain objects to an application service. 例如,当域服务需要向应用程序服务提供一些域对象的列表时。 That list will be exposed as DTOs of the domain object list. 该列表将作为域对象列表的DTO公开。

2) Database technology switch is a responsibility of data mapping layer (ie Entity Framework). 2)数据库技术转换是数据映射层(即实体框架)的职责。

Your repositories should remain agnostic to the database technology and coupled with the OR/M framework. 您的存储库应与数据库技术无关,并应与OR / M框架结合使用。

3) If an user repository IS a repository , you should use inheritance instead of composition 3)如果用户存储库 存储库 ,则应使用继承而不是组合

Thus, UserRepository should both implement IUserRepository and derive from Repository<User> . 因此, UserRepository应该既实现IUserRepository并从Repository<User>派生。

4) A concrete repository shouldn't accept a generic type parameter to provide the domain object to handle 4)具体的存储库不应接受泛型类型参数来提供要处理的域对象

At the end of the day, a concrete repository like IUserRepository handles instances of User , thus, why you want a TEntity generic parameter? 最终,像IUserRepository这样的具体存储库IUserRepository处理User实例,因此,为什么要TEntity泛型参数? Since you've this design flaw, TEntity isn't T ... and this is the reason behind the problem you want to solve... 由于存在设计缺陷,因此TEntity不是T ...,这就是您要解决的问题的原因...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM