Getting started with nhibernate, informix and fluentmapping - nhibernate

I need to configure NHibernate 3.1 to target an informix 11.50 database in an asp.net 4.0 application
using Fluent NHibernate for mappings.
I have this connection string: jdbc:informix-sqli://server:1530/database:informixserver=lufi_tcp
and I have the user an pass. I can connect to to the database using dbvisualizer.
I tray some examples of configuracion that I find on the Internet but it dosen't work.
Can someone get my a link or informacion about what I need to do for
configure nhibernate with fluent to target an informix database (for dummies, please.)
S.O: Windows 8 64 bits
Thanks you in advance.
More information:
I Build the session factory in this way:
class FluentNHibernateLocalSessionFactory : LocalSessionFactoryObject
{
public string[] FluentNhibernateMappingAssemblies { get; set; }
protected override ISessionFactory NewSessionFactory(Configuration config)
{
return Fluently.Configure()
.Database(
IfxSQLIConfiguration
.Informix1000
.Provider<NHibernate.Connection.DriverConnectionProvider>()
.Driver<NHibernate.Driver.IfxDriver>()
.Dialect<NHibernate.Dialect.InformixDialect>()
.ConnectionString("Database=myDatabase;Server=myServer:1530;Persist Security Info=True;Authentication=Server;uid=myUser;password=myPass;")
.ShowSql()
)
.Mappings(m =>
{
foreach (string assemblyName in FluentNhibernateMappingAssemblies)
m.FluentMappings.AddFromAssembly(Assembly.Load(assemblyName));
})
.BuildConfiguration()
.BuildSessionFactory();
}
}
The error I get:
{"Could not create the driver from NHibernate.Driver.IfxDriver, NHibernate, Version=3.1.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4."}

You have to add a reference to IBM.Data.Informix otherwise the driver will throw this exception. To do so you have to add a reference to IBM.Data.Informix.dll to the project which is running your code above.

Related

options.UseSqlServer returns Error in startup.cs

I'm developing a test Project using asp.net core.
For Connecting to database I'm using Entity framework.
I add appsetings.json file to the project and change the connection string as follows:
{
"ConnectionStrings": {
"DefaultConnection": "Server=.\\mihanrayan;Initial Catalog=SportsStore;User = sa; Password = 123456"
}
}
sql version is : mssql 2008 r2
in startup.cs class I add codes below:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration["Data:SportStoreProducts:ConnectionString"]));
services.AddTransient<IProductRepository, EFProductRepository>();
}
but
options.UseSqlServer(
Configuration["Data:SportStoreProducts:ConnectionString"]));
returns this error:
An exception of type 'System.ArgumentNullException' occurred in
Microsoft.EntityFrameworkCore.SqlServer.dll but was not handled in
user code
Additional information: Value cannot be null.
Configuration["Data:SportStoreProducts:ConnectionString"]) is returning null.
"Data:SportStoreProducts:ConnectionString"
should probably be
"ConnectionStrings:Defaultconnection"
It should be like as shown below:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
Install this nuGet package:
"Microsoft.EntityFrameworkCore.SqlServer"
Upon spending hours searching for the fix, this was what worked for me.
NB: select the same version as your .net version

Instantiate DBContext and get its metadata from a Type (another project)

I have Project 1 which is an ASP.NET Core application and Project 2 which is a .NET Standard library.
Is there a way to instantiate a DbContext found in Project 1 from my library using only the Type? I only want to get the metadata about it.
How does Scaffolding do it?
Example
var context = InstatiateFromType(typeof(MyContext));
// So that I get access to the metadata
var x = context.Model.FindEntityType(...);
I'm not sure I understood correctly.
But instead of instantiating it yourself, you could use get an instance via DI in your constructor.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDbContext<MyContext>(options => options.UseSqlServer("connectionString"));
}
And then in your Class you just get it via the constructor.

The DbContext of type cannot be pooled because it does not have a single public constructor accepting a single parameter of type DbContextOptions

I am trying to upgrade our current .Net Core application from 1.1 to 2.0 and am getting this runtime error: "The DbContext of type 'CoreContext' cannot be pooled because it does not have a single public constructor accepting a single parameter of type DbContextOptions".
It is caused by using the new IServiceCollection.AddDbContextPool<> function. When I use IServiceCollection.AddDbContext<> it still works.
This application is DB-First, so I generate all our contexts using 'Scaffold-DbContext'. Due to that, and the need to inject other services I have an extension on every context like this:
public partial class CoreContext
{
public CoreContext(
DbContextOptions<CoreContext> options,
IUserService userService,
IAuditRepository auditRepository
) : base(options) {...}
}
Whenever I run the Scaffold-DbContext I just remove the autogenerated Constructor from CoreContext, but even if I put it in there I still get this error.
public partial class CoreContext : DbContext
{
public CoreContext(DbContextOptions<CoreContext> options) : base(options) {}
}
I've already updated Program.cs to the new style:
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
}
And the Startup.cs is pretty straightforward:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
...
services.AddDbContextPool<CoreContext>(options => options.UseSqlServer(absConnectionString));
...
}
I am using Autofac for DI if that helps. For now I'll default back to the non-Pooling alternative, but it would be nice to take advantage of this feature.
When using DbContext Pooling, your own state (e.g. private fields) in your derived DbContext class will be preserved. Which means the lifetime of your services is now singleton. That's why you shouldn't have other injected services here.
But it's possible to query the required services this way:
First we should use the UseInternalServiceProvider method on DbContextOptionsBuilder to tell EF which service provider to use for its services. This service provider must have all the services configured for EF and any providers. So we should register EF Services manually:
services.AddEntityFrameworkSqlServer();
And then introduce the application's services provider which now includes the EF Services too:
services.AddDbContextPool<ApplicationDbContext>((serviceProvider, optionsBuilder) =>
{
optionsBuilder.UseSqlServer("...");
optionsBuilder.UseInternalServiceProvider(serviceProvider);
});
After that define these namespaces:
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
And now you can access the registered services in the application within the
ApplicationDbContext class using the following methods
var siteSettings = this.GetService<IOptionsSnapshot<SiteSettings>>();
Or
var siteSettings = this.GetInfrastructure().GetRequiredService<IOptionsSnapshot<SiteSettings>>();
this is the current instance of the DbContext.
Remove the default constructor in the DbContext class, this worked for me
"because it does not have a single public constructor accepting a
single parameter of type DbContextOptions"
If you have any public constructors apart from one that accepts DbContextOptions, you need to remove them or make them non-public in order to use context pooling.
Also, there are restrictions on what can be done by overriding the OnConfiguring method. This is referenced in the documentation here but it isn't explicit about what those restrictions are: https://learn.microsoft.com/en-us/ef/core/what-is-new/index#dbcontext-pooling
This issue is mostly encountered when you "Scaffold-Dbcontext" and two constructors are generated.
Simple Solutions:
AddDbContextPool:
If you want to use AddDbContextPool, remove your empty constructor and maintain the one with the DbContextOptionsBuilder. Note that in this case you might have to provide the options, as suggested in the previous posts.
AddDbContext:
With AddDbContext, you can have both constructors/Overloads
Note: AddDbContextPool is preferred for performance reasons!
Try to use AddDbContext instead of AddDbContextPool. This helped me in the same situation.
services.AddDbContext<CoreContext>(options => options.UseSqlServer(absConnectionString));
in some case need to
remove the constractor with zero parameter
//public MyContext()
//{
//}
or use
"AddDbContext"
instead of
"AddDbContextPool"
in startup.cs => ConfigureServices()
services.AddDbContext(options =>
options.UseSqlServer(absConnectionString));

Ninject, Linq to Sql, request scope for each controller without injecting

I recently came across this article titled:
Linq to Sql and ASP.NET MVC – DataContext Per Request
at this link:
http://www.jeremyskinner.co.uk/2010/01/31/linq-to-sql-and-asp-net-mvc-datacontext-per-request/
I would like to set this up using ninject rather than structuremap preferably using the new mvc 3 dependency resolver as I'm using mvc 3 rtm.
The relevant part of the article is this:
Firstly, you’ll need to configure StructureMap by calling ObjectFactory.Configure inside your Global.asax passing in a custom Registry instance:
protected void Application_Start() {
RegisterRoutes(RouteTable.Routes);
ObjectFactory.Configure(cfg => {
cfg.AddRegistry(new MyRegistry());
});
}
The code for MyRegistry looks like this:
public class MyRegistry : Registry {
public MyRegistry() {
For<BlogDataContext>()
.HttpContextScoped()
.Use(c => new BlogDataContext());
Scan(scan => {
scan.AddAllTypesOf<Controller>();
});
}
}
Here I’m telling StructureMap to create one instance of my BlogDataContext per HTTP Request as well as registering each Controller instance with the container.
Next, we need to tell MVC to use StructureMap to instantiate our controllers. This can be done by creating a custom ControllerFactory:
public class StructureMapControllerFactory : DefaultControllerFactory {
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) {
return (IController) ObjectFactory.GetInstance(controllerType);
}
}
We can then replace the DefaultControllerFactory with the StructureMapControllerFactory in our Application_Start:
protected void Application_Start() {
RegisterRoutes(RouteTable.Routes);
ObjectFactory.Configure(cfg => {
cfg.AddRegistry(new MyRegistry());
});
ControllerBuilder.Current.SetControllerFactory(
new StructureMapControllerFactory());
}
I would like to do the same thing with ninject 2.0 rather than structure map. I'm building an mvc 3 site with ninject mvc3. I downloaded the ninject mvc 3 package from nuget and I have this file in my solution which handles wiring up ninject.
AppStart_NinjectMVC3.cs
I do not want to use structurmap and I know the same setup can be done with ninject, but I'm unsure how to wire it up.
Thank you.
I'd rather use the official mvc3 extension from the ninject project found at https://github.com/ninject/ninject.web.mvc. It comes with a full example application showing how to wire up an mvc3 application.

Correct way of bootstrapping NHibernate in MVC

I need to setup session management in MVC. what is the correct way of doing so?
How to setup nhibernate session management in mvc using structuremap so I don't get:
Session is closed
or
Using a single Session in multiple threads is likely a bug.
My current configuration is:
in GlobalAssax:
protected void Application_Start()
{
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
Bootstrapper.ConfigureStructureMap();
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
in my BootStrapper I do:
var cfg = NHibernateManager.Configuration(assembly);
For<Configuration>().Singleton().Use(cfg);
For<ISessionFactory>().Singleton().Use(cfg.BuildSessionFactory());
For<ISession>().HttpContextScoped().Use(ctx => ctx.GetInstance<ISessionFactory>().OpenSession());
I Inject ISession into repositoryes that I use in application layer.
Edit: What happens if I do this?:
For().LifecycleIs(Lifecycles.GetLifecycle(InstanceScope.PerRequest)).Use(ctx => ctx.GetInstance().OpenSession());
Have you added a dispose for the session?
//In Global.asax.cs
protected void Application_EndRequest()
{
ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
}
Otherwise it looks correct.