热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用多个dbcontext实例和依赖项注入

如何解决《使用多个dbcontext实例和依赖项注入》经验,为你挑选了1个好方法。

这是几周前我在这里提出的一个类似的问题,其中一个重要的变化需求.

我有一个新的和独特的(我在stackoverflow搜索中找不到这样的东西)业务要求:

我创建了两个独立的实体框架6 DbContexts,指向两个结构不同的数据库,让我们称它们为PcMaster和PcSubs.虽然PcMaster是一个直接的数据库,而PcMasterContext将有一个静态连接字符串,但PcSubs数据库用作模板来创建新的数据库.显然,由于这些复制的数据库将具有相同的确切结构,因此想法只是在实例化dbcontext时将连接字符串中的数据库(目录)名称更改为指向不同的数据库.我还使用了存储库模式和依赖注入(目前是Ninject,但考虑转向Autofac).

我没有看到DbContext的IDbContext接口,除非你想自己创建一个.但后来,我看到很多人说这不是一个好主意或不是最好的做法.

基本上,我想要做的是,在某些条件下,不仅应用程序需要在PCMasterContext和PCSubsContext之间切换,而且如果PCSubsContext是当前上下文,还要将连接字符串修改为PCSubsContext.我在存储库中使用的dbContext需要指向不同的数据库.我不知道如何使用像Ninject或Autofac这样的IoC容器来做到这一点.这是我到目前为止创建的一些代码片段.非常感谢帮助一些真正的工作解决方案.

这是我的基础存储库的界面

public interface IPCRepositoryBase where T : class
{
  void Add(T entity);
  void Delete(T entity);
  T FindOne(Expression> predicate);
  IQueryable FindBy(Expression> predicate);
  IQueryable GetAll();
  void SetConnection(string connString);
  //... 
  //...
}

这是我的抽象存储库库

public abstract class PCRepositoryBase : IPCRepositoryBase, IDisposable where T : class
{
  protected readonly IDbSet dbSet;
  protected DbContext dbCtx;

  public PCRepositoryBase(DbContext dbCtx)
  {
     this.dbCtx = dbCtx;
     dbSet = dbCtx.Set();
  }
  public void SetConnection(string connString)
  {
     dbCtx.Database.Connection.COnnectionString= connString;
  }
  public IQueryable FindBy(Expression> predicate)
  {
     return dbSet.Where(predicate); // DataContext.Set().Where( predicate  );
  }
  public virtual IQueryable GetAll()
  {
     return dbSet;
  }
  public T FindOne(Expression> predicate)
  {
     return dbSet.SingleOrDefault(predicate);
  }
  //... Not all implementations listed
  //...
}

现在,这是一个派生存储库的接口:

public interface ISubscriberRepository : IPCRepositoryBase
{
  IQueryable GetByStatusName( PCEnums.enumSubsStatusTypes status   );
  IQueryable GetByBusinessName( string businessName );
  //...
  //...
}

public class SubscriberRepository : PCRepositoryBase, ISubscriberRepository
{
  public SubscriberRepository( DbContext context ) : base( context ) { }
  public IQueryable GetByStatusName( PCEnums.enumSubsStatusTypes    status )
  {
     return FindBy(x => x.SubsStatusType.Name == status.ToString());
  }
  public IQueryable GetByBusinessName( string businessName )
  {
     return FindBy( s => s.BusinessName.ToUpper() == businessName.ToUpper()  );
  }
  //... other operations omitted for brevity!
}

现在,我的PCSubs dbContext由设计师生成:

public partial class PCSubsDBContext : DbContext
{
    public PCSubsDBContext() : base("name=PCSubsDBContext")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

    public virtual DbSet Currencies { get; set; }
    public virtual DbSet DurationNames { get; set; }
    public virtual DbSet Subscribers { get; set; }
}

有没有办法,我可以为两个数据库使用和/或注入一个通用dbcontext以及不同数据库的连接字符串.如何在没有相应接口的情况下在Ioc容器中注册"DbContext",并且仍然能够在运行时注入连接字符串?一些代码示例将真正有所帮助.



1> Steven..:

解决方案实际上非常简单.您需要确保您PCSubsDBContext的构造函数包含连接字符串,连接字符串名称,数据库名称或类似名称.这样您就可以PCSubsDBContext根据它所处的上下文创建适当的值.注入其ctor的值可能取决于登录用户或某个请求.这是你已经知道该怎么做的事情.

如何注册取决于您的容器,但您通常必须为此注册一个委托.这可能如下所示:

// Autofac
builder.Register(c =>
    new PCSubsDBContext(GetConnectionStringForCurrentRequest());

// Ninject
kernel.Bind().ToMethod(m =>
    new PCSubsDBContext(GetConnectionStringForCurrentRequest());

// Simple Injector
container.Register(() =>
    new PCSubsDBContext(GetConnectionStringForCurrentRequest());

由于创建上下文取决于请求的可用性,因此可能会稍微更改您的设计,以便PCSubsDBContext可以懒惰地加载,而您仍然可以在不存在Web请求的情况下构建对象图的其余部分.这非常有价值,因为这可以让您验证容器的配置.

解决方案(一如既往)是引入一种新的抽象,例如:

public interface IPcSubsContextProvider
{
    PCSubsDBContext Context { get; }
}

现在,PCSubsDBContext您可以在执行期间注入IPcSubsContextProvider并使用其Context属性(而不是在构建对象图时),而不是直接向消费​​者注入.这允许PCSubsDBContext仅在需要时才创建,并且仅在构建了对象图的其余部分之后才创建.实施将是微不足道的:

class LazyPcSubsContextProvider : IPcSubsContextProvider
{
    private readonly Lazy context;
    public LazyPcSubsContextProvider(Func factory) {
        this.cOntext= new Lazy(factory);
    }

    public PCSubsDBContext Context { get { return this.context.Value; } }
}

可以使用作用域/请求生活方式注册此实现:

// Autofac
builder.Register(c =>
    new LazyPcSubsContextProvider(() =>
        new PCSubsDBContext(GetConnectionStringForCurrentRequest())))
   .InstancePerHttpRequest();

// Ninject
kernel.Bind().ToMethod(m =>
    new LazyPcSubsContextProvider(() =>
        new PCSubsDBContext(GetConnectionStringForCurrentRequest())))
    .InRequestScope();

// Simple Injector
container.RegisterPerWebRequest(() =>
    new LazyPcSubsContextProvider(() =>
        new PCSubsDBContext(GetConnectionStringForCurrentRequest())));

在此之后,Simple Injector将使验证配置变得非常容易:

container.Verify();

它还允许您诊断配置.

使用其他容器,这将更难做到.


推荐阅读
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 标题: ... [详细]
  • 使用圣杯布局模式实现网站首页的内容布局
    本文介绍了使用圣杯布局模式实现网站首页的内容布局的方法,包括HTML部分代码和实例。同时还提供了公司新闻、最新产品、关于我们、联系我们等页面的布局示例。商品展示区包括了车里子和农家生态土鸡蛋等产品的价格信息。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • MySQL语句大全:创建、授权、查询、修改等【MySQL】的使用方法详解
    本文详细介绍了MySQL语句的使用方法,包括创建用户、授权、查询、修改等操作。通过连接MySQL数据库,可以使用命令创建用户,并指定该用户在哪个主机上可以登录。同时,还可以设置用户的登录密码。通过本文,您可以全面了解MySQL语句的使用方法。 ... [详细]
  • 本文整理了Java中java.lang.NoSuchMethodError.getMessage()方法的一些代码示例,展示了NoSuchMethodErr ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Postgresql备份和恢复的方法及命令行操作步骤
    本文介绍了使用Postgresql进行备份和恢复的方法及命令行操作步骤。通过使用pg_dump命令进行备份,pg_restore命令进行恢复,并设置-h localhost选项,可以完成数据的备份和恢复操作。此外,本文还提供了参考链接以获取更多详细信息。 ... [详细]
  • 本文介绍了在使用Laravel和sqlsrv连接到SQL Server 2016时,如何在插入查询中使用输出子句,并返回所需的值。同时讨论了使用CreatedOn字段返回最近创建的行的解决方法以及使用Eloquent模型创建后,值正确插入数据库但没有返回uniqueidentifier字段的问题。最后给出了一个示例代码。 ... [详细]
  • 本文整理了Java中com.evernote.android.job.JobRequest.getTransientExtras()方法的一些代码示例,展示了 ... [详细]
author-avatar
lily0407520
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有