为对象工厂提供数据库上下文

Chr*_*Hvd 4 c# design-patterns entity-framework factory-pattern dbcontext

当我在代码中使用工厂模式时,我总是问自己一个问题(C#,但它适用于我认为的任何语言)。

我有一个“服务”,负责与我的数据库交互,对对象进行操作并与我的对象模型交互。

该服务有时使用工厂来委托对象的实例化。但是这个工厂显然需要自己与数据库交互才能正确实例化我的对象。例如,将数据库上下文传递给 Create 方法是好还是坏做法?

像这样 :

var myNewObject = MyFactory.Create(myDatabaseContext);
Run Code Online (Sandbox Code Playgroud)

另一种方法是让服务始终是唯一与数据库对话的服务。

var myNewObject = MyFactory.Create();
var extraProperty = myDatabaseContext.Get(something);
myNewObject.extraProp = extraProperty;
Run Code Online (Sandbox Code Playgroud)

有什么建议吗?

Car*_*son 5

将数据库上下文传递到工厂创建方法的想法称为方法注入。这是依赖注入的一种形式,所以你走在正确的轨道上。

您可以使用依赖注入通过构造函数来管理工厂内部的数据库上下文。工厂可能看起来像这样:

public class MyFactory 
{
    private readonly IMyDbContext dbContext;

    public MyFactory(IMyDbContext dbContext)
    {
        this.dbContext = dbContext;
    }

    public object Create()
    {
        // Use the dbContext, etc
    }
}
Run Code Online (Sandbox Code Playgroud)

构造函数注入通常受到青睐,因为它使方法签名不那么混乱。我们也很可能拥有一种类型的数据库上下文,因此无需利用基于其他运行时信息的多态性。

您可以选择使用依赖注入容器(例如Ninject或我最喜欢的SimpleInjector)来为您管理依赖项。

让 DbContext 仅由工厂使用是可以的。您可能需要注意的一件事是工厂的用户可能没有意识到工厂正在调用数据库。这可能是一件坏事,并且会对性能产生负面影响。通常,构造信息被传递到工厂方法中,而不是从数据库初始化到工厂方法中。如果您认为有必要但您还没有,您甚至可以更进一步,使用存储库模式抽象出更多的数据访问逻辑。

要了解有关依赖注入的更多信息,如果您不熟悉,可以从这里开始

我理想的结构可能是这样的:

public class MyFactory : IFactory
{  
    public object Create(object someProperty)
    {
        // build object
    }
}

public class MyService
{
    private readonly IMyDbContext dbContext;
    private readonly IFactory factory;

    public MyService(IMyDbContext dbContext, IFactory factory)
    {
        this.dbContext = dbContext;
        this.factory = factory;
    }

    public void DoWork()
    {
        var property = dbContext.Get(something);
        var newObj = factory.Create(property);
        // Use stuff
    }
}
Run Code Online (Sandbox Code Playgroud)