我将如何在运行时将构造函数参数传递给我的dbContext,并将其注册到Unity [英] How would I pass a constructor parameter at runtime to my dbContext and also register them with Unity as such

本文介绍了我将如何在运行时将构造函数参数传递给我的dbContext,并将其注册到Unity的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现各种好东西,如UnitOfWork,Repository,DI。我正在使用Unity for DI。这是我的困境。我有几个(目前3个)数据库具有相同的模式,但由于业务原因,我显然有不同的数据(我将其称为GroupDB1,GroupDB2和GroupDB3)。我还有一个主数据库(DifferentDB),它具有不同的模式。我的dbcontext需要在运行时为不同的场景使用不同的数据库。我不知道如何让他们一起工作。



这是我的dbContexts

  public partial class GroupDB2:DataContext 
{
public GroupDB2():base(name = GroupDB2)
{
}
public IDbSet< ; T>设置< T>()其中T:EntityBase {return base.Set< T>();

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// ......
}
}

public partial class MasterDB:DataContext
{
public MasterDB():base(name = MasterDB)
{
}
public IDbSet< T>设置< T>()其中T:EntityBase {return base.Set< T>();

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// ......
}
}

这里是我的其他接口和实现。

 public class DataContext:DbContext,IDataContextAsync 
{
private readonly Guid _instanceId;
bool _disposed;

public DataContext(string nameOrConnectionString):base(nameOrConnectionString)
{
_instanceId = Guid.NewGuid();
//Configuration.LazyLoadingEnabled = false;
//Configuration.ProxyCreationEnabled = false;
}
}

public interface IDataContext:IDisposable
{
int SaveChanges();
}


public interface IDataContextAsync:IDataContext
{
任务< int> SaveChangesAsync(CancellationToken cancellToken);
任务< int> SaveChangesAsync();
}

public interface IRepository< T>其中T:class
{
IDataContextAsync Context {get; }
IDbSet< T> DbSet {get; }
void Add(T entity);
void Delete(T entity);
void Delete(动态id);
T FindOne(表达式< Func< T,bool>>谓词);
IQueryable< T> FindBy(表达式< Func< T,bool>>谓词);
IQueryable< T>得到所有();
void Update(T entity);
}

public interface IRepositoryAsync< TEntity> :IRepository< TEntity>其中TEntity:class
{
任务< TEntity> FindAsync(params object [] keyValues);
任务< TEntity> FindAsync(CancellationToken cancelToken,params object [] keyValues);
任务< bool> DeleteAsync(params object [] keyValues);
任务< bool> DeleteAsync(CancellationToken cancelToken,params object [] keyValues);
}

public static IUnityContainer InitializeContainer(IUnityContainer _container)
{
container = _container;

....
....

container.RegisterType< IDataContextAsync,DataContext>(new InjectionConstructor(name = MasterDB));
container.RegisterType< IUnitOfWorkAsync,UnitOfWork>(); //(Async);

//这里是我没有线索我如何根据一些条件注册和解析正确的实体上下文
// Like ConnectionStringService.GetConnectionString(for some condition);

//container.RegisterType<IDataContextAsync,DataContext>(GroupDB,new InjectionConstructor(xxxxxx));
//container.RegisterType<IDataContextAsync,DataContext>(DifferentDB,new InjectionConstructor(yyyyyy));

....
....

返回容器;
}

由于我读了很多关于反模式,我不愿意做/

  var result = container.Resolve< MyObject>(
new ParameterOverride(x,ExpectedValue)
。 OnType< MyOtherObject>());

我被骗了任何帮助是非常感谢。谢谢。



Babu。

解决方案

我想出了一个例子这可能有点过度的设计,但我相信它给你最大的灵活性。您可以在这里查看整个示例。如果您只想支持设计时间或仅支持运行时,则可以清理一下。



对于设计时间分辨率,这将使用一个额外的泛型参数用于标识要连接到的数据存储的令牌。这允许您通过构造函数注入一个工作单元和/或特定于一个数据存储库的存储库。

  MyService(IUnitOfWork< Group2Token> unitOfWork){/ * ... * /} 

,这使用一个管理类来使用字符串令牌来检索所需工作单元的实例。

  MyService(IUnitOfWorkManager unitOfWorkManager) 
{
_unitOfWork = unitOfWorkManager.GetUnitOfWork(Group2);
}

经理使用Unity的内置支持来解决所有命名的注册成一个数组。更多信息可以在这个问题和答案中找到。



请注意,我建议您使用 HierarchicalLifetimeManager 注册任何一次性的东西。如果您结合使用儿童容器,您将拥有自动处理机制。此问题和答案中的更多信息。


I am trying to implement all sorts of good stuff like UnitOfWork, Repository, DI. I am using Unity for DI. Here is my dilemma. I have a few (currently 3) databases with identical schema but obviously with different data for business reasons (I will call them GroupDB1, GroupDB2 and GroupDB3). I also have a Master Database (DifferentDB) that has a different schema. My dbcontext need to use different databases for different scenarios at runtime. I have no clue how to put them all to work together.

Here is my dbContexts

    public partial class GroupDB2 : DataContext
{
    public GroupDB2() : base( "name=GroupDB2" )
    {
    }
    public IDbSet<T> Set<T>() where T : EntityBase { return base.Set<T>(); }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //......
    }
}

public partial class MasterDB : DataContext
{
    public MasterDB() : base( "name=MasterDB" )
    {
    }
    public IDbSet<T> Set<T>() where T : EntityBase { return base.Set<T>(); }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //......
    }
}

and here are my other interfaces and implementations.

    public class DataContext : DbContext, IDataContextAsync
{
    private readonly Guid _instanceId;
    bool _disposed;

    public DataContext(string nameOrConnectionString) : base(nameOrConnectionString)
    {
        _instanceId = Guid.NewGuid();
        //Configuration.LazyLoadingEnabled = false;
        //Configuration.ProxyCreationEnabled = false;
    }
}

public interface IDataContext : IDisposable
{
    int SaveChanges();
}


public interface IDataContextAsync : IDataContext
{
    Task<int> SaveChangesAsync(CancellationToken cancellationToken);
    Task<int> SaveChangesAsync();
}

public interface IRepository<T> where T : class
{
    IDataContextAsync Context { get; }
    IDbSet<T> DbSet { get; }
    void Add(T entity);
    void Delete(T entity);
    void Delete(dynamic id);
    T FindOne(Expression<Func<T, bool>> predicate);
    IQueryable<T> FindBy(Expression<Func<T, bool>> predicate);
    IQueryable<T> GetAll();
    void Update(T entity);
}

public interface IRepositoryAsync<TEntity> : IRepository<TEntity> where TEntity : class
{
    Task<TEntity> FindAsync( params object[] keyValues );
    Task<TEntity> FindAsync( CancellationToken cancellationToken, params object[] keyValues );
    Task<bool> DeleteAsync( params object[] keyValues );
    Task<bool> DeleteAsync( CancellationToken cancellationToken, params object[] keyValues );
}

public static IUnityContainer InitializeContainer( IUnityContainer _container )
{
    container = _container;

    ....
    ....

    container.RegisterType<IDataContextAsync, DataContext>( new InjectionConstructor( "name=MasterDB" ) );
    container.RegisterType<IUnitOfWorkAsync, UnitOfWork>();// ("Async");

    // Here is where I have no clue how do I register and resolve the correct entity context based on some conditions
    // Like ConnectionStringService.GetConnectionString( for some condition );

    //container.RegisterType<IDataContextAsync, DataContext>( "GroupDB", new InjectionConstructor( xxxxxx ) );
    //container.RegisterType<IDataContextAsync, DataContext>( "DifferentDB", new InjectionConstructor( yyyyyy ) );

    ....
    ....

    return container;
}

Since I read a lot about anti-patterns I am reluctant to do

var result = container.Resolve<MyObject>(
    new ParameterOverride("x", ExpectedValue)
        .OnType<MyOtherObject>());

I am stumped. Any help is highly appreciated. Thanks.

Babu.

解决方案

I came up with an example that might be a bit over engineered, but I believe it gives you the most flexibility. You can see the entire example here. If you only want support for design time or only support for runtime, you can probably clean it up a bit.

For design time resolution, this uses an additional generics parameter as a token to identify the data store you wish to connect to. That allows you to resolve (via constructor injection) a unit of work and/or a repository that is specific to one data store.

MyService(IUnitOfWork<Group2Token> unitOfWork) { /* ... */ }

For runtime resolution, this uses a manager class to retrieve an instance of the desired unit of work with a string token.

MyService(IUnitOfWorkManager unitOfWorkManager)
{ 
    _unitOfWork = unitOfWorkManager.GetUnitOfWork("Group2");
}

The managers use Unity's built-in support for resolving all named registrations into an array. More on that can be found in this question and answer.

Note that I suggest you use HierarchicalLifetimeManager for the registration of anything that's disposable. If you use that in combination with using child containers, you will have an automatic disposal mechanism. More info in this question and answer.

这篇关于我将如何在运行时将构造函数参数传递给我的dbContext,并将其注册到Unity的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆