0
votes

I am new to both Ninject and the Vita ORM (vita docs) and am just having issues coming up with a binding strategy for dependency injection and would really appreciate any help.

Firstly, my application in split into 3 layers, namely the data layer ( using Vita ORM so in essence it is a single EntityApp class similar to dbContext for EF), then I have a service layer with well defined interfaces ( and existing implementations using my current repository pattern using dapper.net ) and finally a simple MVC web application with controllers calling off to the service layer.

Currently I am using ninject constructor intection to inject the repo into the service and the service into the controller and scoping them accordingly. this works great because everything is interface driven and there is no shared context between services / repositories.

But now with the introduction of an "entity context" I need to create the context once in the app ( so singleton scope ) and then would in essence like to open a new session per request and pass that to any service layer objects that require it. Over and above this, the ORM needs to be initialized at application startup ( or I suppose it can be done lazily, but at app start would be better )

Here is some code generated by vita as to how to initialize the ORM

class Program {

public static MyEntityApp App;

static void Main(string[] args) {
  Console.WriteLine(" Sample application for VITA-generated model. ");
  Init();

  //Open session and run query
  var session = App.OpenSession();
  var query = from ent in session.EntitySet<IConnections>()  // just random entity
              // where ?condition?
              select ent;
  var entities = query.Take(5).ToList();

  Console.WriteLine("Loaded " + entities.Count + " entities.");
  foreach(var ent in entities)
    Console.WriteLine("  Entity: " + ent.ToString()); // change to smth more meaningful 

  Console.WriteLine("Press any key ...");
  Console.ReadKey();
}

private static void Init() {

  App = new MyEntityApp();
  App.CacheSettings.AddCachedTypes(CacheType.FullSet /* , <fully cached entity types> */ );
  App.CacheSettings.AddCachedTypes(CacheType.Sparse /* , <sparsely cached entity types> */ );
  var connString = @".......";
  var driver = new Vita.Data.MsSql.MsSqlDbDriver();
  App.LogPath = "_appLog.log";
  var dbSettings = new DbSettings(driver, DbOptions.Default, connString, upgradeMode: DbUpgradeMode.Always);
  App.ConnectTo(dbSettings);
}

}

As you can see they initialize and set a static variable which has reference to the context container. As can also be seen by the above is that you need to call var session = App.OpenSession(); to work with the context, so I was hoping to create one session per request and then inject that session into the service object contructors.

So here is what I have done so far

/*Map the Vita ORM session into the request scope*/
kernel.Bind<MyEntities>().ToSelf().InSingletonScope();

I am assuming that will call the contructor, and inside there I have initialized the context correctly ( and this should also only be called once )

then in the service objects i want to do something like this

here is the service impl

private IEntitySession _Session { get; set; }

public VitaSettingsServiceImpl(IEntitySession Session)
{
    _Session = Session;
}

And here is my attempt at injecting that session object...

kernel.Bind<ISettingsService>().To<VitaSettingsServiceImpl>().InRequestScope().WithConstructorArgument("Session", [WANT TO CALL MYENTITIES.OpenSession() HERE]);

As you can see it is that last binding that is stumping me? how do I bind a contructor object param to a method call on an existing singleton bound object?

Like I said in the begining, I am VERY green at this and maybe I am going about it all wrong, but i have scoured the web and cant find any info regarding these to technologies being used together, so any help would be greatly appreciated

1

1 Answers

0
votes

So for all the lonely souls trolling the web with similar issues, here is what I eventually cam up with :

        /*Map the Vita ORM session into the request scope*/
        kernel.Bind<SorbetEntities>().ToSelf().InSingletonScope();

        /*Map all the services to their respective implementations*/
        kernel.Bind<ISettingsService>().To<sorbet.Vita.VitaSettingsServiceImpl>().InRequestScope().WithConstructorArgument("Session", CreateVitaSession);

and then a static extension method to execute the method that will return my connection context

    private static object CreateVitaSession(IContext context)
    {
        return context.Kernel.Get<SorbetEntities>().OpenSession();
    }

And thats it. now i get a new connection context per request and I am a happy camper