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

C# ef6中带有接口的存储库模式,c#,entity-framework-6,repository-pattern,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...

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
{
ICollection GetAll(),其中TModel:class;
//更多功能。。。
}
公共类RepositoryEF6Impl:IRepository
{
受保护的只读DbContext上下文;
public RepositoryEF6Impl(数据库上下文)
{
this.context=上下文;
}
public ICollection GetAll(),其中TModel:class
{
返回context.Set().ToList();
}
//更多功能。。。
}
现在,我可以直接使用存储库,如下所示:

IRepository repo = new RepositoryEF6Impl(context);
repo.GetAll<MemberEF6Impl>();
i假定回购=新回购EF6impl(上下文);
repo.GetAll();
到目前为止还不错。但我想这样使用它:

IRepository repo = new RepositoryEF6Impl(context);
repo.GetAll<IMember>(); //note the difference
i假定回购=新回购EF6impl(上下文);
repo.GetAll()//注意区别
问题是数据库中没有IMember,而是MemberEF6Impl

我为什么要这样使用它:

IRepository repo = new RepositoryEF6Impl(context);
repo.GetAll<IMember>(); //note the difference
因为数据库和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>();
    }
}
公共类RepositoryVMImpl:IRepository
{
受保护的只读存储库;
公共存储VMImpl(IRepository存储库)
{
this.repository=存储库;
}
public ICollection GetAll(),其中TModel:class
{
返回repository.GetAll();
}
}

有没有办法做到这一点?

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

方法重载:

public ICollection<TProjection> GetAll<TModel, TProjection>(Expression<Func<TModel, TProjection>> projection)
{
      return context.Set<TModel>().Select(projection).ToList();
}
public ICollection GetAll(表达式投影)
{
返回context.Set().Select(projection.ToList();
}
然后您可以使用这样的方法,它将提供对返回类型的控制

repository.GetAll<MemberEF6Impl, IMember>(memberEF => new MemberVMImp { ... })
repository.GetAll(memberEF=>newmembervmimp{…})
如果仍然需要EF实体模型作为结果类型,则可以使用当前方法:

repository.GetAll<MemberEF6Impl>();
repository.GetAll();
关于环境足迹预测的更多信息:


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

视图模型或dto最好与域逻辑解耦