带有接口的ef6中的存储库模式

时间:2017-09-19 13:59:54

标签: c# entity-framework-6 repository-pattern

aLets有一个简单的场景:

public interface IMember
{
    string Name { get; set; }
}

public class MemberEF6Impl : IMember
{
    //some annotations...
    public string Name { get; set; }
}

public class MemberVMImpl : IMember
{
    //some other annotations...
    public string Name { get; set; }

    //some functionality...
}

我的程序中有两个具体的接口实现。一种特别适用于数据库迁移的实现,一种用于我们的viewmodel。现在我想实现工厂模式并添加一个接口和两个更具体的实现:

public interface IRepository
{
    ICollection<TModel> GetAll<TModel>() where TModel : class;
    //some more functionality...
}


public class RepositoryEF6Impl : IRepository
{
    protected readonly DbContext context;

    public RepositoryEF6Impl(DbContext context)
    {
        this.context = context;
    }
    public ICollection<TModel> GetAll<TModel>() where TModel : class
    {
         return context.Set<TModel>().ToList();
    }
    //some more functionality...
}

现在我可以直接使用存储库,如下所示:

IRepository repo = new RepositoryEF6Impl(context);
repo.GetAll<MemberEF6Impl>();

到目前为止一切顺利。但我想用这种方式使用它:

IRepository repo = new RepositoryEF6Impl(context);
repo.GetAll<IMember>(); //note the difference

问题是数据库中没有IMember,而是一个MemberEF6Impl。

为什么我要这样使用它:

因为我们对数据库内容和viewmodel有不同的具体类,所以我必须为viewmodel创建第二个存储库,它只是具体的VMImpl类和EF6存储库之间的一个层。

public class RepositoryVMImpl : IRepository
{
    protected readonly IRepository repository;

    public RepositoryVMImpl(IRepository repository)
    {
        this.repository = repository;
    }

    public ICollection<TModel> GetAll<TModel>() where TModel : class
    {
        return repository.GetAll<TModel>();
    }
}

有没有办法实现这个目标?

1 个答案:

答案 0 :(得分:1)

我的建议是使用单个存储库,但使用一些方法重载来预测所请求的泛型类型。

方法重载:

public ICollection<TProjection> GetAll<TModel, TProjection>(Expression<Func<TModel, TProjection>> projection)
{
      return context.Set<TModel>().Select(projection).ToList();
}

然后你可以使用这样的方法,它将控制返回类型。

repository.GetAll<MemberEF6Impl, IMember>(memberEF => new MemberVMImp { ... })

如果您仍需要EF实体模型作为结果类型,则可以使用当前方法:

repository.GetAll<MemberEF6Impl>();

有关EF投影的更多信息:https://www.tektutorialshub.com/projection-queries-entity-framework/

同样Automapper提供了这样的功能 - 它可以为您节省一些时间。你应该看看它。