MVC 5 NHibernate Autofac, not able to see database data - nhibernate

I'm building an MVC5 web app connecting to a MS SQL 2008 database, so that the users can search and make changes to data stored there. I've looked at a bunch of autofac tutorials and examples, but can't seem to make any of them work.
I'm assuming my autofac configuration is the problem, because when I run the app it says my model is null. Which I think means the autofac is not connecting to the datbase.
So, in my global.asax.cs file I have the following:
protected void Application_Start()
{
#region Autofac
// Register Controllers
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly); //all controllers in assembly at once ?
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterFilterProvider();
// Set the Dependency Resolver
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// Register Model Binders
builder.RegisterModelBinders(typeof(MvcApplication).Assembly); //all binders in assembly at once ?
builder.RegisterModelBinderProvider();
// Register Modules
builder.RegisterModule<PersistenceModule>();
#endregion
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
I have a hibernate.cfg.xml file as
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
</configSections>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="connection.connection_string">Data Source=DEVSRV\SQLSERVER;Initial Catalog=tipdemo;Persist Security Info=True;User ID=admin;Password=***********</property>
<property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
<property name="proxyfactory.factory_class">NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu</property>
<!--<mapping assembly="NHibernateTest"/> -->
</session-factory>
</hibernate-configuration>
</configuration>
And my PersistenceModule class is:
public class PersistenceModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
if (builder == null)
throw new ArgumentException("builder", "builder is null");
base.Load(builder);
}
private ISessionFactory ConfigureDB()
{
Configuration cfg = new Configuration().Configure(System.Web.HttpContext.Current.Server.MapPath("~/Config/hibernate.cfg.xml"));
cfg.AddAssembly(typeof(Domain.General.Project).Assembly);
return cfg.BuildSessionFactory();
}
}

You can't register things in the container after it's built.
On line 11 in the sample for Application_Start you're building the container, but then after you set the DependencyResolver you're registering more stuff with the ContainerBuilder. You can't do that - you have to register everything first, then build the container as the last thing you do.
That's why it's never entering your PersistenceModule - you've already built the container, so it's not actually getting registered.
If, for some reason, you need to add registrations to an already-built container, you need to create an all new ContainerBuilder and call builder.Update(container). However, I strongly recommend you just reorder things so the container is built last rather than go the Update route if possible.

Related

EJB #PersistenceContext EntityManager Throws NullPointerException

I'm having a problem with injecting EntityManager by using #PersistenceContext. I try to inject EntityManager in EJB class with #PersistenceContext and I always get NullPointerException.
Here is EJB class:
#Stateless
public class BookEJB {
public BookEJB(){
}
#PersistenceContext(unitName = "BookWebStorePU")
private EntityManager em;
public Book createBook(Book book) throws Exception {
System.out.println("EM: " + em);
em.persist(book);
return book;
}
public Book findBookByIsbn10(String isbn10){
Book book = new Book();
em.find(Book.class, isbn10);
return book;
}
//Other methods here
}
Here's Persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="BookWebStorePU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<validation-mode>NONE</validation-mode>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="create"/>
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/BookWebStoreDB"/>
<property name="javax.persistence.jdbc.user" value="bookwebstoreadmin"/>
<property name="javax.persistence.jdbc.password" value="password"/>
<!-- Let EclipseLink create database schemas automatically -->
<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
<property name="eclipselink.ddl-generation.output-mode" value="database"/>
</properties>
Here's my test file:
public class BookDaoTests {
private BookEJB bookDao;
private Book newBook;
#Before
public void init() {
newBook = new Book();
newBook.setName("Flying Cow");
newBook.setDescription("Super cool story about flying cow");
newBook.setAuthor("Me");
newBook.setIsbn10("0123456789");
newBook.setIllustrations(true);
newBook.setPublishYear(2013);
newBook.setNumberOfPages(1567);
newBook.setQuantity(58);
bookDao = new BookEJB();
}
#Test
public void createBook() throws Exception{
bookDao.createBook(newBook);
Assert.assertEquals("Book was created!", bookDao.findBookByIsbn10("0123456789"), newBook);
}
}
So when I run that test file I get following error:
Testcase: createBook(com.mysite.bookstore.tests.BookDaoTests): Caused an ERROR
null
java.lang.NullPointerException
at com.mysite.bookwebstore.beans.BookEJB.createBook(BookEJB.java:27)
at com.mysite.bookstore.tests.BookDaoTests.createBook(BookDaoTests.java:46)
EM: null
I use following technologies:
Glassfish 4
JavaEE 7
JSF
EclipseLink 2.1
Java DB
I hope we can find some solution for this problem. I have been tackling now 3 days of this problem and searched and tested solutions from Google and from Stackoverflow but none of the solutions helped/worked. To make sure that the EntityManager was really null, I debugged test file and saw that indeed it gives null. So how can I solve this problem?
The EntityManager instance, is injected when the EJB is deployed in the Container.
If you take a look at the lifecycle of enterprise bean, you will see clearly when dependency injection occurs.
When the Container sees the #Persistencecontext annotation it will inject a container-managed EntityManager.
The problem is that the code executed in this test is not managed by the Container, therefore, no one inject the necessary dependencies.
bookDao = new BookEJB();
When you run the test, the BookEJB class is just a simple POJO, the #Stateless and #PersistenceContext annotations are simply ignored.
You have several alternatives in order to test your EJB, take a look at this link.

NHibernateHelper - many tables

I am new in NHibernate, I have based on tutorial: http://nhibernate.info/doc/tutorials/first-nh-app/your-first-nhibernate-based-application.html . So I have NHibernateHelper:
public class NHibernateHelper {
private static ISessionFactory _sessionFactory;
private static ISessionFactory SessionFactory
{
get
{
if (_sessionFactory == null)
{
var configuration = new Configuration();
configuration.Configure();
configuration.AddAssembly(typeof (Product).Assembly);
_sessionFactory = configuration.BuildSessionFactory();
}
return _sessionFactory;
}
}
public static ISession OpenSession()
{
return SessionFactory.OpenSession();
} }
But I have also entity Category and User? Do I need each entity add to configuration using code AddAssembly?? Because when I have added code:
configuration.AddAssembly(typeof (Product).Assembly);
configuration.AddAssembly(typeof(Category).Assembly);
I have error:
Could not compile the mapping document: MvcApplication1.Mappings.Product.hbm.xml
First check whether you have set the "Build Action" of all the mapping files (*.hbm.xml) to "Embedded Resource". This is VERY important.
Then you only need to add a call to AddAssembly once as NHibernate is clever enough to scan through the assembly to sniff out all your entities that map to all your embedded hbm.xml files..
e.g. You only need to supply the assembly once that contains all your entities:-
_configuration.AddAssembly(typeof (Product).Assembly);
NHibernate will now find Category (and all others) automatically as long as they are in the same assembly as Product. HTH
you can alternatively add the mapping tag into the web.config, instead of adding it in code on the SessionFactory initialization. Then, your code will look like this:
if (_sessionFactory == null)
{
var configuration = new Configuration();
configuration.Configure();
_sessionFactory = configuration.BuildSessionFactory();
}
And in the web config you will have to indicate the assembly where all of your mappings are, like this:
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.provider">
NHibernate.Connection.DriverConnectionProvider
</property>
<property name="dialect">
NHibernate.Dialect.MsSql2005Dialect
</property>
<property name="connection.driver_class">
NHibernate.Driver.SqlClientDriver
</property>
<property name="connection.connection_string">
-- YOUR STRING CONNECTION --
</property>
<property name="proxyfactory.factory_class">
NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle
</property>
<mapping assembly="You.Assembly.Namespace" />
</session-factory>
Being the important configuration tag "mapping assembly="Your.Assembly.Namespace". As the other contributor mentioned before, it is very important that you mark each of the hbm.xml file as embedded resource, otherwise it will be as you never created it. By doing this, you just need to create all of the mappings inside of this assembly (project) and those will be automatically read when NH configures.

Logging SQL statements of Entity Framework 5 for database-first aproach

I'm trying to use Entity Framework Tracing Provider to log the SQL staments generated.
I changed my context class to something like this:
public partial class MyDBContext: DbContext
{
public MyDBContext(string nameOrConnectionString)
: base(EFTracingProviderUtils.CreateTracedEntityConnection(nameOrConnectionString), true)
{
// enable sql tracing
((IObjectContextAdapter) this).ObjectContext.EnableTracing();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
//DbSets definition....
}
But this doesn't log the SQL statements on the Output window...
Should I had something more in the class or in web.config file? (I'm working on a ASP.NET MVC 4 project)
I using the solution in the following post:Entity Framework 4.1 - EFTracingProvider
but I made some changes that I don't know if they are important:
The class is partial instead of abstract, and the constructor is public instead of protected...
What am I missing?
After modifying your code, you need to enable tracing in your web.config like this:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.diagnostics>
<sources>
<source name="EntityFramework.NorthwindEntities" switchValue="All" />
</sources>
</system.diagnostics>
</configuration>
The name of your TraceSource should be your context name prefixed with 'EntityFramework'.
Make sure that you disable tracing when you deploy your application to production by setting the switchValue to Off.

How to write custom nHibernate dialect?

I am using NHibernate with a legacy rdbms rule engine. I am using GenericDialect but some of the sql generated are not working. If I need to write custom Dialect for this rule engine how do start?
This is an example dialect:
using System;
using System.Collections.Generic;
using System.Web;
///
/// This class ensures that the tables created in our db are handling unicode properly.
///
public class NHibernateMySQL5InnoDBDialect : NHibernate.Dialect.MySQL5Dialect
{
public override String TableTypeString { get { return " ENGINE=InnoDB DEFAULT CHARSET=utf8"; } }
}
The assembly it's in has a reference to NHibernate.dll
hibernate.cfg.dll (note that I don't have 'connection.connection_string' property set here, this is my setup specific and usually you would have connection string here) :
<?xml version="1.0" encoding="utf-8"?>
<!-- This is the ByteFX.Data.dll provider for MySql -->
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" >
<session-factory name="NHibernate.Test">
<property name="connection.driver_class">NHibernate.Driver.MySqlDataDriver</property>
<property name="dialect">NHibernateMySQL5InnoDBDialect, Assembly1</property>
<property name="proxyfactory.factory_class">NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu</property>
</session-factory>
</hibernate-configuration>
In some setups the dialect line would be
<property name="dialect">Assembly1.NHibernateMySQL5InnoDBDialect, Assembly1</property>
And the code creating an ISessionFactory:
NHibernate.Cfg.Configuration cfg = new NHibernate.Cfg.Configuration();
cfg.Configure();
cfg.Properties["connection.connection_string"] = ConnectionStringForDatabase();
cfg.AddDirectory(PathToMappingsIfYouUseNonStandardDirectory);//not needed if using embedded resources
return cfg.BuildSessionFactory();
I would start by grabbing the nhibernate source, the 2.1.x branch is here. The existing Dialects are all under src/NHibernate/Dialect.
Copy one and start hacking. The base class Dialect has many extension points.

How to properly configure NHibernate event listeners

I'm trying to use an event listener for the first time. All samples I've seen show how easy it is to configure, but for some reason I'm having trouble - it doesn't seem to be called. I suspect I'm missing something obvious.
I've tried this:
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory name="TerraCognita.LoanExpress">
<!-- other stuff... -->
<listener type="delete" class="Test.TestDeleteListener, MyDllName" />
</session-factory>
</hibernate-configuration>
as well as:
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory name="TerraCognita.LoanExpress">
<!-- other stuff... -->
<event type="delete">
<listener class="Test.TestDeleteListener, MyDllName" />
</event>
</session-factory>
</hibernate-configuration>
When configuration is loaded and the session factory is built:
var cfg = new NHibernate.Cfg.Configuration();
cfg.AddAssembly("MyDllName");
sessionFactory = cfg.BuildSessionFactory();
After instantiation, cfg.EventListeners.DeleteEventListeners has a single entry, of type DefaultDeleteEventListener (as I'd expect). However, after cfg.AddAssembly is called, this is still the case - but given the configuration, I would expect that the DeleteEventListener should actually be of type TestDeleteListener.
In my unit test, the only way I can get my event listener working is by manually adding it to the session info:
var sess = GetSession();
sess.GetSessionImplementation().Listeners.DeleteEventListeners =
new NHibernate.Event.IDeleteEventListener[] { new TestDeleteListener() };
I know this shouldn't be required, and I should be able to configure it properly. Can anyone shine a light on what I'm doing wrong here?
Your configuration is ok, it's just that you overlooked to call cfg.Configure(). Change your initialization code to this and your fine:
var cfg = new NHibernate.Cfg.Configuration();
cfg.Configure();
cfg.AddAssembly("MyDllName");
sessionFactory = cfg.BuildSessionFactory();