C# 将EF6与其自定义Api解耦

C# 将EF6与其自定义Api解耦,c#,entity-framework,dependency-injection,decoupling,C#,Entity Framework,Dependency Injection,Decoupling,我想就依赖注入和架构方法寻求一些帮助 因此,我有一个由EF6实现的ORM层,其中描述了对象,Ef执行其业务,等等。我在上面创建了一个自定义库,称为DatabaseApi,在标题中称为“Api”,在这里我查询数据并将其映射到datacontract对象。我这样做纯粹是为了测试。我希望我的应用程序中的不同库是可测试的 我开始实现注入DbContext的代码,但我不知道如何处理这种情况下的使用 我浏览了一些关于mocking和EF的博客和文章,特别是关于测试EF本身,而不是关于如何将其与其他库分离。另

我想就依赖注入和架构方法寻求一些帮助

因此,我有一个由EF6实现的ORM层,其中描述了对象,Ef执行其业务,等等。我在上面创建了一个自定义库,称为DatabaseApi,在标题中称为“Api”,在这里我查询数据并将其映射到datacontract对象。我这样做纯粹是为了测试。我希望我的应用程序中的不同库是可测试的

我开始实现注入DbContext的代码,但我不知道如何处理这种情况下的使用

我浏览了一些关于mocking和EF的博客和文章,特别是关于测试EF本身,而不是关于如何将其与其他库分离。另一方面,我认为我的搜索关键字不正确

您知道关于如何将实体框架与其他库解耦的好的、可用的教程和文章吗

提前谢谢

示例:

我创建了一个空接口,以便DbContext可以被注入。它由databaseContext实现

public interface IDatabase
{
}

public class DatabaseModelContext : DbContext, IDatabase{

    public DbSet<TableOne> TableOne { get; set; } 
    public DbSet<TableTwo> TableTwo { get; set; }

}
公共接口IDatabase
{
}
公共类DatabaseModelContext:DbContext,IDatabase{
公共DbSet TableOne{get;set;}
公共DbSet TableTwo{get;set;}
}
在自定义Api库构造函数中,我编写了一段代码,通过Unity解析接口。我不知道它是否有效。我还没有执行死刑

public partial class DatabaseApi : IDatabaseApi {
    private readonly IDatabase iDatabase;

    private readonly UnityContainer unityContainer;

    public DatabaseApi()
    {
        this.unityContainer = new UnityContainer();
        this.unityContainer.RegisterType<IDatabase, DatabaseModelContext>();
        this.iDiLibDatabase = this.unityContainer.Resolve<IDiLibDatabase>();
    }
}
公共部分类数据库API:IDatabaseApi{
私有只读IDatabase IDatabase;
私有只读UnityContainer UnityContainer;
公共数据库API()
{
this.unityContainer=新的unityContainer();
this.unityContainer.RegisterType();
this.iDiLibDatabase=this.unityContainer.Resolve();
}
}
这就是问题所在。由于注入,我将使用和接口,但据我所知,使用对管理资源很重要。怎么做

public partial class DatabaseApi : IDatabaseApi
    {
        public List<SomeDataContract> GetMainStructure()
        {
            var result = new List<SomeDataContract>();

            //this is the old implementation
            using (var database = new DatabaseModelContext())
            {
                //some data manipulation magic... :)
            }
            return result;
        }
公共部分类数据库API:IDatabaseApi
{
公共列表GetMainStructure()
{
var result=新列表();
//这是旧的实现
使用(var database=newdatabasemodelcontext())
{
//一些数据操作魔术…:)
}
返回结果;
}

如果您可以使用linq to对象作为域访问层的核心元素,那么公开用于访问实体的IQueryable就可以了

public interface IRepository<TEntity>
{
  IQueryable<TEntity> AllEntities { get; }
}
公共接口IRepository
{
IQueryable allenties{get;}
}
这样,您就可以执行Where、Select等操作,而无需直接硬连接到EF。在幕后,IRepository实现将处理EF部分、数据库连接等。无法避免在数据访问层将其耦合到EF。但您可以使用类似于您已经开始的方式将其约束到该层。只需确保IRepository对象使用的数据库上下文是唯一使用EF的对象


换句话说:不要让你的IDatabase返回实体。只要让它处理连接,你就应该为域对象访问创建另一个层,它接收IDatabase。在我给出的示例中,IRepository实现会以某种方式接收IDatabase的实例。

因此,解决方案是使用Autofac DI框架。我发现了有趣的问题和答案以及两个非常有用的教程。以下链接:


您可以在
IDatabase
中声明
IDbSet
成员并显式实现它们。对于
使用…dispose
,您必须使用处理一次性对象的IOC容器。Unity并不是开箱即用的,但它还实现了一个用于Unity的
TransientDisposableLifetimeManager
We如果你搜索它。我不知道其他IOC容器。Keith,谢谢你的建议。根据你的建议,我找到了AutoFac和有关它的有趣文章、教程。谢谢!我找到了解决我问题的方法!:)Keith,我如何才能将你的答案标记为我寻找的解决方案?因为我只有一条有用的评论,而你如果您自己找到了问题的答案,您应该发布一个答案,解释您发现的内容,可能包括您自己的一些代码,并将其标记为答案。这样,其他可能正在搜索相同或类似问题答案的人可以找到您的答案。请尝试查看存储库模式。例如:很遗憾,这没有效果e当您尝试使用不同实体执行工作单元时。