Ninject, DapperWrapper injecting SqlExecutor - ninject

I am trying to create some "repository" style classes to wrap calls to Dapper via DapperWrapper. Trying to inject SqlExecutor into the repository checking for an attribute to determine which database to connect to.
Here is the repository implementation so you can see what I am trying to do:
public class ProviderRepository : IProviderRepository<SearchType>
{
private readonly IDbExecutor executor;
public ProviderRepository([BHN]IDbExecutor executor)
{
this.executor = executor;
}
public IList<SearchType> GetAllSearchTypes()
{
return executor
.Query<SearchType>("BHN.pSEL_LU_SEARCHTYPE_Load", commandType: CommandType.StoredProcedure)
.ToList();
}
}
And here is my ninject binding which I know is bad but just to illustrate what I am trying to do:
kernel.Bind<IDbExecutor>().To<SqlExecutor>()
.WhenTargetHas<BHNAttribute>()
.WithConstructorArgument("sqlConnection",
new SqlConnection(connections["ProviderSearch"].ConnectionString));
Note: BHNAttribute is just an empty class inheriting from Attribute.
Now obviously problem with this is that the sql connection is created on app start, which I understand, but how can I make that load when it is used instead of at application load? Ive been toying around the Ninject Factory extension, but I am having trouble with what that implementation might look like. So I created this:
public class ExecutorFactory
{
private ISqlExecutorFactory executor;
public ExecutorFactory(ISqlExecutorFactory executor)
{
this.executor = executor;
}
public void Do()
{
var e = this.executor.CreateSqlExecutor("string");
}
}
public interface ISqlExecutorFactory
{
SqlExecutor CreateSqlExecutor(string conn);
}
And my binding would look like this:
kernel.Bind<ISqlExecutorFactory>.ToFactory();
The "string" in the factory class would would be "ProviderSearch" and need to be passed to the ToFactory() method I assuming, but I dont understand how I would do that and incorporate the use of the BHNAttribute, like I was doing before. Or if that's even possible at this point.
Am I looking at this the wrong way?

So I figured this one out on my own... interesting solution here so I thought I would share it for the world. I ended up using a provider (ToProvider)
My provider implementation:
public class ExecutorProvider : Provider<IDbExecutor>
{
private readonly string _connectoinString;
public ExecutorProvider(Func<string> connectionString)
{
_connectionString = connectionString();
}
protected override IDbExecutor CreateInstance(IContext context)
{
return new SqlExecutor(() => {
var sqlconnection = new SqlConnection(_connectionString);
sqlconnection.Open();
return sqlconnection;
});
}
}
Then I created a new implementation of the SqlExecutor using Lazy(T) to only instantiate and open SqlConnection when it is used:
public class SqlExecutor : IDbExecutor
{
readonly Lazy<SqlConnection> _sqlConnection;
public SqlExecutor(Func<SqlConnection> sqlConnection)
{
_sqlConnection = new Lazy<SqlConnection>(() => sqlConnection());
}
public int Execute(
string sql,
object param = null,
IDbTransaction transaction = null,
int? commandTimeout = default(int?),
CommandType? commandType = default(CommandType?))
{
return _sqlConnection.Value.Execute(
sql,
param,
transaction,
commandTimeout,
commandType);
}
public IEnumerable<dynamic> Query(
string sql,
object param = null,
IDbTransaction transaction = null,
bool buffered = true,
int? commandTimeout = default(int?),
CommandType? commandType = default(CommandType?))
{
return _sqlConnection.Value.Query(
sql,
param,
transaction,
buffered,
commandTimeout,
commandType);
}
public IEnumerable<T> Query<T>(
string sql,
object param = null,
IDbTransaction transaction = null,
bool buffered = true,
int? commandTimeout = default(int?),
CommandType? commandType = default(CommandType?))
{
return _sqlConnection.Value.Query<T>(
sql,
param,
transaction,
buffered,
commandTimeout,
commandType);
}
public void Dispose()
{
_sqlConnection.Value.Dispose();
}
}
And then my binding:
kernel.Bind<IDbExecutor>().ToProvider(new ExecutorProvider(()
=> connections["ProviderSearch"].ConnectionString))
.WhenTargetHas<BHNAttribute>()
.InRequestScope();
This allows me to do this during injection on my implementing classes to associate injected sql executors with a database connection based on the attribute:
public class ProviderRepository : IProviderRepository
{
private readonly IDbExecutor executor;
public ProviderRepository([BHN]IDbExecutor executor)
{
this.executor = executor;
}
public IList<SearchType> GetAllSearchTypes()
{
return executor
.Query<SearchType>("pSEL_LU_SEARCHTYPE_Load", commandType: CommandType.StoredProcedure)
.ToList();
}
}
BHNAttribute([BHN]) is just an empty class inheriting from Attribute.
NOTE: Yes I know using stored procs for this is lame, but my hands are tied on that one unfortunately.
I dont like having to re-create the SqlExecutor class, but this works really well.

Related

Hangfire per-job correlationId/state

I run Hangfire on ASP.NET Core.
For our other projects we have CorrelationIds that we pass when making API calls to be able to link the caller and callee.
We use the IHttpContextAccessor's TraceIdentifier for this in ASP.NET Core.
Unfortunately it looks like the trick used by ASP.NET Core to get a scoped CorrelationId in the Transient IHttpContextAccessor doesn't work for Hangfire job execution.
Using a Scoped state correlation object doesn't work because it must be Transient to be able to work with the rest of the system (logging etc.)
I used to be able to get away using the ServiceLocator anti-pattern and resolve a scoped state object in a transient service.
In the latest ASP.NET Core that is no longer supported and an exception is thrown making the system too slow because of the huge number of exceptions thrown.
Is there something that Hangfire provides already that would give me a unique ID per job execution?
Cheers.
Thanks to jbl's comment I looked at what I was doing again and managed to get it working through a kludge.
I've got the transient state holder
(basically it's the HttpContextAccessor class renamed):
public class StateHolder
{
private static AsyncLocal<ContextHolder> _contextCurrent = new AsyncLocal<ContextHolder>();
public string State {
get {
return _contextCurrent.Value?.Context;
}
set {
var holder = _contextCurrent.Value;
if (holder != null)
{
holder.Context = null;
}
if (value != null)
{
_contextCurrent.Value = new ContextHolder { Context = value };
}
}
}
private class ContextHolder
{
public string Context;
}
}
and then in Hangfire I hook it up to the activation with
public class LoggingActivator : JobActivator
{
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly ContextAccessor _contextAccessor;
public LoggingActivator([NotNull] IServiceScopeFactory serviceScopeFactory, ContextAccessor contextAccessor)
{
_serviceScopeFactory = serviceScopeFactory ?? throw new ArgumentNullException(nameof(serviceScopeFactory));
_contextAccessor = contextAccessor;
}
public override JobActivatorScope BeginScope(JobActivatorContext context)
{
return new LoggingActivatorScope(_serviceScopeFactory.CreateScope(), _contextAccessor);
}
}
and
public class LoggingActivatorScope : JobActivatorScope
{
private readonly IServiceScope _serviceScope;
private readonly ContextAccessor _contextAccessor;
public LoggingActivatorScope(
[NotNull] IServiceScope serviceScope,
ContextAccessor contextAccessor)
{
_serviceScope = serviceScope ?? throw new ArgumentNullException(nameof(serviceScope));
_contextAccessor = contextAccessor;
}
public override object Resolve(Type type)
{
_contextAccessor.Context = Guid.NewGuid().ToString();
return ActivatorUtilities.GetServiceOrCreateInstance(_serviceScope.ServiceProvider, type);
}
public override void DisposeScope()
{
_serviceScope.Dispose();
}
}
That seems to work fine.

How to write Xunit test case of factory design pattern code block which is tightly coupled?

I would like to write xunit test case of below method. Could you please suggest alternate design so i can write xunit test case with minimum change in my current project.
public ActionResult Index(int id = 0, AssetFilterType filter = AssetFilterType.All)
{
using (var tracer = new Tracer("AssetController", "Index"))
{
RemoveReturnUrl();
ViewBag.JobId = id;
var response = ContextFactory.Current.GetDomain<EmployeeDomain>().GetEmployeeFilterAsync(id,
CurrentUser.CompanyId, filter); // Not able write unit test case , please suggest alternate design.
return View("View", response);
}
}
current design is as follow
public interface IDomain
{
}
public interface IContext
{
D GetDomain<D>() where D : IDomain;
string ConnectionString { get; }
}
public class ApplicationContext : IContext
{
public D GetDomain<D>() where D : IDomain
{
return (D)Activator.CreateInstance(typeof(D));
}
public string ConnectionString
{
get
{
return "DatabaseConnection";
}
}
}
public class ContextFactory
{
private static IContext _context;
public static IContext Current
{
get
{
return _context;
}
}
public static void Register(IContext context)
{
_context = context;
}
}
//var response = ContextFactory.Current.GetDomain**< EmployeeDomain>**().GetEmployeeFilterAsync(id,
CompanyId, filter);
This line serve purpose to call specific class method i.e GetEmployeeFilterAsync from EmployeeDomain. Although it is very handy and widely used in our application but due to design issue i am not able to write unit
test case.
Could you please suggest design so with the minimum change we can write unit test case.
Don't use the Service Locator anti-pattern, use Constructor Injection instead. I can't tell what AssetDomain is from the OP, but it seems as though it's the dependency that matters. Inject it into the class:
public class ProbablySomeController
{
public ProbablySomeController(AssetDomain assetDomain)
{
AssetDomain = assetDomain;
}
public AssetDomain AssetDomain { get; }
public ActionResult Index(int id = 0, AssetFilterType filter = AssetFilterType.All)
{
using (var tracer = new Tracer("AssetController", "Index"))
{
RemoveReturnUrl();
ViewBag.JobId = id;
var response = AssetDomain.GetAssetFilterAsync(id, CurrentUser.CompanyId, filter);
return View("View", response);
}
}
}
Assuming that AssetDomain is a polymorphic type, you can now write a test and inject a Test Double:
[Fact]
public void MyTest()
{
var testDouble = new AssetDomainTestDouble();
var sut = new ProbablySomeController(testDouble);
var actual = sut.Index(42, AssetFilterType.All);
// Put assertions here
}
step1 : Required library
step 2 : When the application starts , register required domain like
protected void Application_Start()
UnityConfig.RegisterComponents();
Step 3: create one static class and register all your domain
example
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
Initialize domain which will injected in controller
container.RegisterType<IPricingDomain, PricingDomain>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
step 4 :
so you can inject respective interface in constructor
in controller file.
goal : get rid of below any pattern in your project.
and start writing unit test cases.

.NET Core 3.1 Complex Session Wrapper Not Working

I am trying to create a complex session wrapper in .NET Core 3.1. I ran into an issue where my variables are not being set. This is the way I set up the session wrapper class.
public class SessionWrapper : ISessionWrapper
{
private static IHttpContextAccessor context;
public SessionWrapper(IHttpContextAccessor _context)
{
context = _context;
}
public static Course Course
{
get
{
var key = context.HttpContext.Session.GetString("course");
if (key == null)
{
return default;
}
else
{
return JsonConvert.DeserializeObject<Course>(key);
}
}
set
{
if(value != null)
{
context.HttpContext.Session.SetString("course", JsonConvert.SerializeObject(value));
}
}
}
}
I configured my services to use session and the sessionwrapper.
services.AddDistributedMemoryCache();
services.AddSession();
services.AddHttpContextAccessor();
services.AddScoped<ISessionWrapper, SessionWrapper>();
I configured the pipeline to use session
app.UseSession();
In my controller, I am initializing course and set the session wrapper. Then, I am setting the course id to 4. It's not complaining, but the course id is not being set. It's always null. I've been looking at it for so and is getting frustrated. What am I missing here?
Course myCourse = new Course();
SessionWrapper.Course = myCourse;
SessionWrapper.Course.Id = "4"
I feel like your wrapper in itself isn't really the best approach to do this. A self-aware subclass of Course that has the 'know how' to store itself in Session, seems more logical to me. That way you are freeing your controller(s) from the responsibility for managing the persistence.
public abstract class Course
{
public abstract int Id { get; set; }
}
public class SessionCourse : Course
{
private int _id;
public override int Id
{
get => _id;
set { _id = value; UpdateSession(); }
}
// The GetCourse method is a factory for creating the SessionCourse objects
// and providing it with a ISession object so they can store themselves.
public static Course GetCourse(IServiceProvider services)
{
ISession session = services.GetRequiredService<IHttpContextAccessor>()?.HttpContext.Session;
SessionCourse course = session?.GetJson<SessionCourse>("Course") ?? new SessionCourse();
course.Session = session;
return course;
}
[JsonIgnore]
private ISession Session { get; set; }
private void UpdateSession() {
Session.SetJson("Course", this);
}
}
Now the trick is to satisfy requests for the Course object with the SessionCourse object that will store itself in session. You can do that by adding a scoped service with a lambda expression for the course object. The result is that requests for the Course service will return the SessionCourse object.
services.AddScoped<Course>(sp => SessionCourse.GetCourse(sp));
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
So the benefit of creating this kind of service is that it allows you to simplify the controllers where Course objects are used.
public class CourseController : Controller
{
private Course course;
public CartController(Course courseService)
{
course = courseService;
}
public void SetCourseId()
{
course.Id = "4";
}
SessionExtension.cs defines extension methods for adding objects to the session.
public static class SessionExtensions {
public static void SetJson(this ISession session, string key, object value) {
session.SetString(key, JsonConvert.SerializeObject(value));
}
public static T GetJson<T>(this ISession session, string key) {
var sessionData = session.GetString(key);
return sessionData == null ? default(T) : JsonConvert.DeserializeObject<T>(sessionData);
}
}

Closing connection when using Dapper

Is it necessary to close connection once query is executed explicitly calling Close method or putting the connection within Using statement? Would leaving connection open lead to connection reuse and improve SQL performance for future queries?
I am assuming that you are using latest version of Dapper.
With Dapper, there are two ways to manage connection:
Fully manage yourself:
Here, you are fully responsible for opening and closing connection. This is just like how you treat connection while working with ADO.NET.
Allow Dapper to manage it:
Dapper automatically opens the connection (if it was not opened) and closes it (if it was opened by Dapper) for you. This is similar to DataAdapter.Fill() method. I personally do not recommend this way. This may not be applicable every time. Following is what Marc Gravell says in one of the comment for this answer: https://stackoverflow.com/a/12629170/5779732
well, technically open/closed is different to disposed. If you are only going to be opening/closing around the individual calls, you might as well let dapper do it. If you are opening/closing at a wider granularity (per request, for example), it would be better for your code to do it and pass an open connection to dapper.
Below is the quote from here:
Dapper will close the connection if it needed to open it. So if you're just doing 1 quick query - let Dapper handle it. If you're doing many, you should open (once) and close at the end, with all the queries in the middle...just from an efficiency standpoint.
Ofcourse, you can call multiple queries on single connection. But, connection should be closed (by calling Close(), Dispose() method or by enclosing it in using block) to avoid resource leak. Closing connection returns it to connection pool. Involvement of connection pool improves the performance over new connection cost.
In addition to just handling connection, I suggest you implement UnitOfWork to manage transactions as well. Refer this excellent sample on GitHub.
Following source code may help you. Note that this is written for my needs; so it may not work for you as is.
public sealed class DalSession : IDisposable
{
public DalSession()
{
_connection = new OleDbConnection(DalCommon.ConnectionString);
_connection.Open();
_unitOfWork = new UnitOfWork(_connection);
}
IDbConnection _connection = null;
UnitOfWork _unitOfWork = null;
public UnitOfWork UnitOfWork
{
get { return _unitOfWork; }
}
public void Dispose()
{
_unitOfWork.Dispose();
_connection.Dispose();
}
}
public sealed class UnitOfWork : IUnitOfWork
{
internal UnitOfWork(IDbConnection connection)
{
_id = Guid.NewGuid();
_connection = connection;
}
IDbConnection _connection = null;
IDbTransaction _transaction = null;
Guid _id = Guid.Empty;
IDbConnection IUnitOfWork.Connection
{
get { return _connection; }
}
IDbTransaction IUnitOfWork.Transaction
{
get { return _transaction; }
}
Guid IUnitOfWork.Id
{
get { return _id; }
}
public void Begin()
{
_transaction = _connection.BeginTransaction();
}
public void Commit()
{
_transaction.Commit();
Dispose();
}
public void Rollback()
{
_transaction.Rollback();
Dispose();
}
public void Dispose()
{
if(_transaction != null)
_transaction.Dispose();
_transaction = null;
}
}
interface IUnitOfWork : IDisposable
{
Guid Id { get; }
IDbConnection Connection { get; }
IDbTransaction Transaction { get; }
void Begin();
void Commit();
void Rollback();
}
Now, your repositories should accept this UnitOfWork in some way. I choose Dependency Injection with Constructor.
public sealed class MyRepository
{
public MyRepository(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
IUnitOfWork unitOfWork = null;
//You also need to handle other parameters like 'sql', 'param' ect. This is out of scope of this answer.
public MyPoco Get()
{
return unitOfWork.Connection.Query(sql, param, unitOfWork.Transaction, .......);
}
public void Insert(MyPoco poco)
{
return unitOfWork.Connection.Execute(sql, param, unitOfWork.Transaction, .........);
}
}
And then you call it like this:
With transaction:
using(DalSession dalSession = new DalSession())
{
UnitOfWork unitOfWork = dalSession.UnitOfWork;
unitOfWork.Begin();
try
{
//Your database code here
MyRepository myRepository = new MyRepository(unitOfWork);
myRepository.Insert(myPoco);
//You may create other repositories in similar way in same scope of UoW.
unitOfWork.Commit();
}
catch
{
unitOfWork.Rollback();
throw;
}
}
Without Transaction:
using(DalSession dalSession = new DalSession())
{
//Your database code here
MyRepository myRepository = new MyRepository(dalSession.UnitOfWork);//UoW have no effect here as Begin() is not called.
myRepository.Insert(myPoco);
}
This way, instead of directly exposing connection in your calling code, you control it at one location.
More details about Repository in above code could be found here.
Please note that UnitOfWork is more than just a transaction. This code handles only transaction though. You may extend this code to cover additional roles.

Ninject does not inject dependency

having problem with my Ninject construct. May be somebody can show me where I am doing it wrong..
ok.. here is Module I have:
public class WebPageModule:NinjectModule
{
public override void Load()
{
Bind<TranscriptPageMediaWidgetViewModelForWebPage>().ToSelf().InSingletonScope();
Bind<TranscriptPageTranscriptWidgetViewModelForWebPage>().ToSelf().InSingletonScope();
Bind<WebPageTranscriptProvider>().ToSelf().InSingletonScope();
Bind<ITranscriptProvider>().To<WebPageTranscriptProvider>().WhenInjectedInto<TranscriptPageTranscriptWidgetViewModelForWebPage>();
//Bind<ITranscriptProvider>().To<WebPageTranscriptProvider>();
Bind<ITranscriptRendererWidget>().To<TranscriptPageTranscriptWidgetViewModelForWebPage>();
Bind<IMediaRendererWidget>().To<TranscriptPageMediaWidgetViewModelForWebPage>();
}
}
Then in NinjectWebCommons.cs I have:
private static IKernel CreateKernel()
{
var kernel = new StandardKernel(new WebPageModule(),new TweeterModule(), new BookmarkModule());
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
kernel.Settings.AllowNullInjection = true;//http://stackoverflow.com/questions/10517962/using-default-parameter-values-with-ninject-3-0
RegisterServices(kernel);
return kernel;
}
then I use the property injection:
https://github.com/ninject/ninject/wiki/Injection-Patterns
in my "public class TranscriptPageTranscriptWidgetViewModelForWebPage : ITranscriptRendererWidget"
here it is:
[Inject]
public ITranscriptProvider TranscriptProvider
{
get { return _transcriptProvider; }
set { _transcriptProvider = value; }
}
but, when I am going into the constructor and trying to use _transcriptProvider it is NULL:
public TranscriptPageTranscriptWidgetViewModelForWebPage(string dataEndpoint, string focusCue)
{
InitParentInterfaceProperties();
Transcript = _transcriptProvider.GetTranscript(new Uri(dataEndpoint));
FocusCue = focusCue.Replace("*", "").ToLower();
}
Any ideas what I am doing wrong? thanks!
Al
Looks like you're trying to access the property within the constructor.
.NET's object creation semantics are such that this simply cannot be made to work (which is one of lots of good reasons to try very hard to achieve things with constructor injection unless you really are dealing with an optional dependency)