I'm making a simple web project using NHibernate and i'm stuck at this error whenever i try to build the sessionfactory.
The line that causes the exception is this
ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
People with similar problem seems to solve them by referencing Mysql.data.dll which i've already done, and checked that the dll is in my bin folder.
i suspect the fault lies in my hibernate.cfg.xml which looks like this
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="dialect">NHibernate.Dialect.MySQLDialect</property>
<property name="connection.provider">NHibernate.Driver.MySqlDataDriver</property>
<property name="connection.driver_class">NHibernate.Driver.SqlServerCeDriver</property>
<property name="connection.connection_string">connectionstring</property>
<property name='proxyfactory.factory_class'>NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
<mapping assembly="Mcgvd" />
</session-factory>
</hibernate-configuration>
the tutorial i followed to make this project was using a helperclass to create the sessionfactory looking like this
public sealed class NHibernateHelper
{
private const string CurrentSessionKey = "nhibernate.current_session";
private static readonly ISessionFactory sessionFactory;
static NHibernateHelper()
{
sessionFactory = new Configuration().Configure().BuildSessionFactory();
}
public static ISession GetCurrentSession()
{
HttpContext context = HttpContext.Current;
ISession currentSession = context.Items[CurrentSessionKey] as ISession;
if (currentSession == null)
{
currentSession = sessionFactory.OpenSession();
context.Items[CurrentSessionKey] = currentSession;
}
return currentSession;
}
public static void CloseSession()
{
HttpContext context = HttpContext.Current;
ISession currentSession = context.Items[CurrentSessionKey] as ISession;
if (currentSession == null)
{
// No current session
return;
}
currentSession.Close();
context.Items.Remove(CurrentSessionKey);
}
public static void CloseSessionFactory()
{
if (sessionFactory != null)
{
sessionFactory.Close();
}
}
}
hibernate.cfg.xml and hibernate.hbm.xml are both located at the root of my project.
What am I doing wrong here ?
Your configuration is wrong.
<property name="connection.provider">NHibernate.Driver.MySqlDataDriver</property>
<property name="connection.driver_class">NHibernate.Driver.SqlServerCeDriver</property>
You've specified a driver for the connection provider, and a SQL Server CE driver when you're apparently using MySQL. Try:
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.driver_class">NHibernate.Driver.MySqlDataDriver</property>
besides the fault Jamie found i had to change the connection.provider property where i for some reason had put mysqldatadriver.
this is the working configuration i ended up with.
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="dialect">NHibernate.Dialect.MySQLDialect</property>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.driver_class">NHibernate.Driver.MySqlDataDriver</property>
<property name="connection.connection_string">connectionstring</property>
<property name='proxyfactory.factory_class'>NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
<mapping assembly="Mcgvd" />
</session-factory>
</hibernate-configuration>
Related
I am using TransactionScope with nHibernate. For working with nested transactions I have made a helper class along with TransactionScope . My SessionFactory:
public class SessionFactory
{
[ThreadStatic]
private static ISessionFactory iSessionFactory;
[ThreadStatic]
protected static ISession session;
private static object syncRoot = new Object();
private static void buildSessionFactory()
{
lock (syncRoot)
{
if (session == null)
{
if (iSessionFactory == null)
{
Configuration configuration = new Configuration().Configure("hibernate.cfg.xml");
Assembly assembly = Assembly.GetCallingAssembly();
iSessionFactory = configuration.BuildSessionFactory();
}
if (session != null && session.IsOpen)
session.Dispose();
CurrentSessionContext.Bind(iSessionFactory.OpenSession());
session = iSessionFactory.OpenSession();
}
}
}
public static ISession OpenSession
{
get
{
if (session == null || !session.IsOpen)
{
session = null;
buildSessionFactory();
}
return session;
}
}
}
Configuration file is named hibernate.cfg.xml and is:
<configuration>
<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.MySqlDataDriver
</property>
<property name="dialect">NHibernate.Dialect.MySQL55InnoDBDialect</property>
<property name="connection.connection_string">connection string here</property>
<property name="current_session_context_class">thread_static</property>
<property name="show_sql">true</property>
<property name="generate_statistics">true</property>
<mapping assembly="assembly name here"/>
<!-- Here -->
</session-factory>
</hibernate-configuration>
<system.transactions>
<machineSettings maxTimeout="00:00:60" />
</system.transactions>
</configuration>
Helper class for managing nested transactions:
public class TransactionScopeHelper : SessionFactory, iTransactionScopeHelper
{
public static int count = 0;
public TransactionScope getTransactionScope()
{
if (count == 0)
{
if (session != null)
session.Clear();
}
count++;
return new TransactionScope(TransactionScopeOption.Required);
}
public void complete(TransactionScope tx)
{
count--;
if (count == 0)
{
session.Flush();
session = null;
}
tx.Complete();
}
public void rollbackTransaction()
{
count = 0;
session = null;
}
}
Helper class is used only in services and not in repository
An example of usage of helper in service:
public void updateCategory(CategoryDto category_dto)
{
try
{
using (TransactionScope tx = transactionScopeHelper.getTransactionScope())
{
//works here
transactionScopeHelper.complete(tx);
}
}
catch(Exception)
{
transactionScopeHelper.rollbackTransaction();
throw;
}
}
An example of function in repository:
public T getById(long id)
{
ISession session = SessionFactory.OpenSession;
return session.Get<T>(id);
}
Whenever I update some entity , old data is shown after few refreshes and again after some refresh new data is retrieved. This is almost continuous. Why am I getting this problem? Any help would be appreciated.
There is so much "unusual" stuff going on here I barely know where to begin.
SessionFactory
NHibernate's session factory is generelly initialized ONCE on application startup (or when first needed) and then that instance will live for the duration of the program and shared among all threads. We would not typically expect to have a separate instance per thread (as ThreadStatic does). Initializing it repeatedly will be a severe performance penalty.
buildSessionFactory() will dispose the session if there is one - but it won't get to that code unless session is null, so I don't understand what the intention really is here.
At the end of buildSessionFactory(), iSessionFactory.OpenSession() is called twice! Once should be enough.
You are setting current_session_context_class in the configuration file and call CurrentSessionContext.Bind(). So there should be no need for you to maintain your own thread-static session variable. This is what CurrentSessionContext is for.
A session must eventually be disposed. Therefore, calling a method named like OpenSession implies that we get a new session that we are responsible for closing. But your own OpenSession() can return the same session many times, making it difficult to understand who exactly is responsible for closing it. Better to name it CurrentSession or similar.
TransactionScopeHelper
This is also not possible to understand. There is a reference to a variable session, but the definition and setting of this variable is not shown. Code is incomplete. At some points the session reference is set to null but no attempt to dispose it is made, which is mandatory.
Calling Clear() on the session will remove all state from the session and make NHibernate lose track of all loaded objects and therefore be unable to perform dirty check and persist automatically. Other code would need to remember to carefully re-add everything.
Code does not show how and when the session, transaction and transaction scope are actually created. Unable to tell if the interactions are proper. Is the session even aware of the transaction scope?
Finally, to answer your question: "Why am I getting this problem?"
Well, I'm sorry, but the whole situation looks like a mess. And messy code equals messy results. Unless of course the issues I mention above result from partial copy-paste that left out important parts.
I have a database, hbm mapping file and the App.config located in a class library. Now from a test project I reference that library and attempt to call a HibernateHelper class I create, at runtime the following error is thrown :
NHibernate.MappingException : Could not compile the mapping document: HibernateExample.Mappings.Products.hbm.xml
Please keep in mind that this is a class library that is being reference from a Test project.
If I change it output type to console application, it runs fine. But when I change it back to class library and reference it from my Test Project it throws the above mention error.
I tried adding config.Configure() but that throws a NhibernateDuplicateMapping exception.
FIXED:
Fixed the duplication mapping issue by removing from appconfig. and fixed the problem mapping entity by placing a hibernate.cfg.xml file in my Test project as well.
public sealed class NHibernateHelper
{
private static ISessionFactory _sessionFactory;
const string Connectionstring = "servicestring";
public static void OpenSession()
{
var config = new Configuration();
config.Configure();
config.AddAssembly(Assembly.GetCallingAssembly());
_sessionFactory = config.BuildSessionFactory();
}
public static ISession GetCurrentSession()
{
ISession session = null;
if (_sessionFactory == null)
OpenSession();
if (_sessionFactory != null)
{
session = _sessionFactory.OpenSession();
}
return session;
}
public static void CloseSessionFactory()
{
if (_sessionFactory != null)
{
_sessionFactory.Close();
}
}
// var dsn = ConfigurationManager.ConnectionStrings[Connectionstring].ConnectionString;
//config.SessionFactory().Integrate.Using<MsSqlCeDialect>().Connected.ByAppConfing(dsn);
// System.Diagnostics.Debug.WriteLine("My connection string: "+dsn);
//Get NHibernate configuration
//_sessionFactory = config.BuildSessionFactory();
//config.AddAssembly("HibernateExample");
}
Any ideas?
<?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.driver_class"> NHibernate.Driver.SqlServerCeDriver</property>
<property name="dialect">NHibernate.Dialect.MsSqlCeDialect</property>
<property name="connection.connection_string">Data Source=FirstSample.sdf;</property>
<property name="show_sql">true</property>
<mapping assembly="HibernateExample"/>
</session-factory>
</hibernate-configuration>
<connectionStrings>
<add name="testconnectionstring"
connectionString="Data Source=|DataDirectory|\FirstSample.sdf;Integrated Security=True"
providerName="Microsoft.SqlServerCe.Client.3.5" />
</connectionStrings>
<runtime>
<assemblyBinding xmlns="urnchemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Data.SqlServerCe" publicKeyToken="89845DCD8080CC91" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-9.0.242.0" newVersion="3.5.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="HibernateExample" namespace="HibernateExample.Domain" >
<class name="Product" table="Products">
<id name="Id" type="integer">
<generator class="identity"/>
</id>
<property name="Name" type="string"/>
<property name="Category" type="string"/>
<property name="Discontinued" />
</class>
</hibernate-mapping>
Exception Thrown:
Test 'NunitTest.TestClass.canquerydb' failed: NHibernate.MappingException : Could not compile the mapping document: HibernateExample.Mappings.Products.hbm.xml
----> System.InvalidOperationException : Could not find the dialect in the configuration
at NHibernate.Cfg.Configuration.LogAndThrow(Exception exception)
at NHibernate.Cfg.Configuration.AddDeserializedMapping(HbmMapping mappingDocument, String documentFileName)
at NHibernate.Cfg.Configuration.ProcessMappingsQueue()
at NHibernate.Cfg.Configuration.AddInputStream(Stream xmlInputStream, String name)
at NHibernate.Cfg.Configuration.AddResource(String path, Assembly assembly)
at NHibernate.Cfg.Configuration.AddAssembly(Assembly assembly)
at NHibernate.Cfg.Configuration.AddAssembly(String assemblyName)
NHibernateTest\NHibernateHelper.cs(21,0): at HibernateExample.NHibernateTest.NHibernateHelper.openSession()
NHibernateTest\NHibernateHelper.cs(28,0): at HibernateExample.NHibernateTest.NHibernateHelper.GetCurrentSession()
TestClass.cs(21,0): at NunitTest.TestClass.canquerydb()
--InvalidOperationException
at NHibernate.Dialect.Dialect.GetDialect(IDictionary`2 props)
at NHibernate.Cfg.Configuration.AddDeserializedMapping(HbmMapping mappingDocument, String documentFileName)
From the error, it appears that you are not configuring the Dialect before adding the mapping. This is required.
Here's a simple piece of basic configuration code:
var configuration = new Configuration();
configuration.SessionFactory().Integrate.Using<MsSql2012Dialect>()
.Connected.ByAppConfing("connName");//sic
//now you can add the mappings
I use Common.Logging as a wrapper around NLog 2.0. I've done this so that I can replace NLog with another logging provider in the future.
I also use PostSharp to not write a try catch block everytime I need one. I have a class that inherits the OnMethodBoundaryAspect:
[Serializable]
public class LogMethodAttribute : OnMethodBoundaryAspect
{
private ILog logger;
public LogMethodAttribute()
{
this.logger = LogManager.GetCurrentClassLogger();
}
public override void OnEntry(MethodExecutionArgs args)
{
logger.Debug(string.Format("Entering {0}.{1}.", args.Method.DeclaringType.Name, args.Method.Name));
}
public override void OnExit(MethodExecutionArgs args)
{
logger.Debug(string.Format("Leaving {0}.{1}.", args.Method.DeclaringType.Name, args.Method.Name));
}
public override void OnException(MethodExecutionArgs args)
{
logger.Error(args.Exception.Message,args.Exception);
}
}
I have configured Common.Logging as follows in my web.config:
<configSections>
<sectionGroup name="common">
<section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
</sectionGroup>
</configSections>
<common>
<logging>
<factoryAdapter type="Common.Logging.NLog.NLogLoggerFactoryAdapter, Common.Logging.NLog20">
<arg key="configType" value="FILE" />
<arg key="configFile" value="~/NLog.config" />
</factoryAdapter>
</logging>
</common>
NLog.Config looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
throwExceptions="true"
internalLogLevel="Debug"
internalLogToConsoleError="true"
internalLogFile="c:\new projects/nlog-app.txt"
>
<!--
See http://nlog-project.org/wiki/Configuration_file
for information on customizing logging rules and outputs.
-->
<targets>
<target name="database"
xsi:type="Database"
commandText="INSERT INTO LogEvent(EventDateTime, EventLevel, UserName, MachineName, EventMessage, ErrorSource, ErrorClass, ErrorMethod, ErrorMessage, InnerErrorMessage) VALUES(#EventDateTime, #EventLevel, #UserName, #MachineName, #EventMessage, #ErrorSource, #ErrorClass, #ErrorMethod, #ErrorMessage, #InnerErrorMessage)"
dbProvider="System.Data.SqlClient">
<connectionString>
Data Source=...;Initial Catalog=myDB;User Id=user;Password=pass;
</connectionString>
<installConnectionString>
Data Source=...;Initial Catalog=myDB;User Id=user;Password=pass;
</installConnectionString>
<!-- parameters for the command -->
<parameter name="#EventDateTime" layout="${date:s}" />
<parameter name="#EventLevel" layout="${level}" />
<parameter name="#UserName" layout="${identity}" />
<parameter name="#MachineName" layout="${machinename}" />
<parameter name="#EventMessage" layout="${message}" />
<parameter name="#ErrorSource" layout="${event-context:item=error-source}" />
<parameter name="#ErrorClass" layout="${event-context:item=error-class}" />
<parameter name="#ErrorMethod" layout="${event-context:item=error-method}" />
<parameter name="#ErrorMessage" layout="${event-context:item=error-message}" />
<parameter name="#InnerErrorMessage" layout="${event-context:item=inner-error-message}" />
<!-- commands to install database -->
<install-command>
<text>CREATE DATABASE myDB</text>
<connectionString> Data Source=...;Initial Catalog=myDB;User Id=user;Password=pass;</connectionString>
<ignoreFailures>true</ignoreFailures>
</install-command>
<install-command>
<text>
CREATE TABLE LogEvent(
EventId int primary key not null identity(1,1),
EventDateTime datetime,
EventLevel nvarchar(50),
UserName nvarchar(50),
MachineName nvarchar(1024),
EventMessage nvarchar(MAX),
ErrorSource nvarchar(1024),
ErrorClass nvarchar(1024),
ErrorMethod nvarchar(1024),
ErrorMessage nvarchar(MAX),
InnerErrorMessage nvarchar(MAX));
</text>
</install-command>
<!-- commands to uninstall database -->
<uninstall-command>
<text>DROP DATABASE myDB</text>
<connectionString> Data Source=...;Initial Catalog=myDB;User Id=user;Password=pass;</connectionString>
<ignoreFailures>true</ignoreFailures>
</uninstall-command>
</target>
</targets>
<rules>
<logger name="*" levels="Error" writeTo="database" />
</rules>
</nlog>
The problem is that nothing is inserted in my table. When I put a logger in for example my HomeController on the index page and I call my logger.Error("an error") it adds a record to my table.
Can somebody help me?
Are you decorating your controller methods with the LogMethodAttribute that you created?
Also, you'll want to adjust your logger rule to include more levels outside of just "Error", otherwise that's all you'll log.
Give this a try:
<rules>
<logger name="*" minLevel="Trace" writeTo="database" />
</rules>
Edit:
Have you tried moving your logger initialization into your method?
public override void OnEntry(MethodExecutionArgs args)
{
this.logger = LogManager.GetCurrentClassLogger();
logger.Debug(string.Format("Entering {0}.{1}.", args.Method.DeclaringType.Name, args.Method.Name));
}
Per Donald Belcham's Pluralsight course, aspect constructors are not executed at runtime, so perhaps your logger is not getting set properly.
add a static property logger in your class Aspect
public class LogAspect : OnMethodBoundaryAspect
{
/// <summary>
/// Gets or sets the logger.
/// </summary>
public static ILogger logger { get; set; }
set logger variable in your application init method with your ILogger class and exclude all methods before this initialization with AttributeExclude.
[LogAspect(AttributeExclude = true)]
protected void Application_Start()
{
_windsorContainer = new WindsorContainer();
ApplicationDependencyInstaller.RegisterLoggingFacility(_windsorContainer);
LogAspect.logger = _windsorContainer.Resolve<ILogger>();
Am I right in thinking that my QuartzJobObject can't have any DAO's or other Spring-managed objects injected into it?
Was hoping I could do something like this (orderService is what I want to inject):
<object name="checkPendingOrdersJob" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz">
<property name="JobType" value="Munch.ScheduledTasks.CheckPendingOrdersJob" />
<!-- We can inject values through JobDataMap -->
<property name="JobDataAsMap">
<dictionary>
<!--entry key="UserName" value="Alexandre" /-->
</dictionary>
</property>
<property name="orderService" ref="orderService"/>
</object>
...which I know doesn't make sense because of the type it is. But, I could do with being able to inject some DAO's, Services etc somehow. I can't figure it out though. How can I do this?
This is what I've ended up with and it works perfectly (hopefully useful to someone else)
Job factory that is aware of Spring's context
/// <summary>
/// A custom job factory that is aware of the spring context
/// </summary>
public class ContextAwareJobFactory : AdaptableJobFactory, IApplicationContextAware
{
/// <summary>
/// The spring app context
/// </summary>
private IApplicationContext m_Context;
/// <summary>
/// Set the context
/// </summary>
public IApplicationContext ApplicationContext
{
set
{
m_Context = value;
}
}
/// <summary>
/// Overrides the default version and sets the context
/// </summary>
/// <param name="bundle"></param>
/// <returns></returns>
protected override object CreateJobInstance(TriggerFiredBundle bundle)
{
return m_Context.GetObject(bundle.JobDetail.JobType.Name, bundle.JobDetail.JobType);
}
}
The job itself (checks the DB for records and if there are at least HomeManyMenuItemsIsOK of them, everything is good). Note: menuService is an injected spring-managed object that itself has several DAO's in it). HowManyMenuItemsIsOK is a static property that's passed in through the job data map.
public class CheckMenuIsHealthyJob : QuartzJobObject
{
private static readonly ILog log = LogManager.GetLogger(typeof(CheckMenuIsHealthyJob));
public IMenuService menuService { get; set; }
public int HowManyMenuItemsIsOK { get; set; }
/// <summary>
/// Check how healthy the menu is by seeing how many menu items are stored in the database. If there
/// are more than 'HowManyMenuItemsIsOK' then we're ok.
/// </summary>
/// <param name="context"></param>
protected override void ExecuteInternal(JobExecutionContext context)
{
IList<MenuItem> items = menuService.GetAllMenuItems();
if (items != null && items.Count >= HowManyMenuItemsIsOK)
{
log.Debug("There are " + items.Count + " menu items. Menu is healthy!");
}
else
{
log.Warn("Menu needs some menu items adding!");
}
}
}
And finally the Spring config
<!-- Scheduled Services using Quartz -->
<!-- This section contains Quartz config that can be reused by all our Scheduled Tasks ---->
<!-- The Quartz scheduler factory -->
<object id="quartzSchedulerFactory" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz">
<!-- Tell Quartz to use our custom (context-aware) job factory -->
<property name="JobFactory" ref="contextAwareJobFactory"/>
<!-- Register the triggers -->
<property name="triggers">
<list>
<ref object="frequentTrigger" />
</list>
</property>
</object>
<!-- Funky new context-aware job factory -->
<object name="contextAwareJobFactory" type="Munch.Service.ScheduledTasks.ContextAwareJobFactory" />
<!-- A trigger that fires every 10 seconds (can be reused by any jobs that want to fire every 10 seconds) -->
<object id="frequentTrigger" type="Spring.Scheduling.Quartz.CronTriggerObject, Spring.Scheduling.Quartz" lazy-init="true">
<property name="jobDetail" ref="checkMenuIsHealthyJobDetail" />
<property name="cronExpressionString" value="0/10 * * * * ?" />
</object>
<!-- Now the job-specific stuff (two object definitions per job; 1) the job and 2) the job detail) -->
<!-- Configuration for the 'check menu is healthy job' -->
<!-- 1) The job -->
<object name="checkMenuIsHealthyJob" type="Munch.Service.ScheduledTasks.CheckMenuIsHealthyJob" singleton="false">
<property name="menuService" ref="menuService"/>
</object>
<!-- 2) The job detail -->
<object name="checkMenuIsHealthyJobDetail" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz">
<property name="JobType" value="Munch.Service.ScheduledTasks.CheckMenuIsHealthyJob"/>
<property name="JobDataAsMap">
<dictionary>
<entry key="HowManyMenuItemsIsOK" value="20" />
</dictionary>
</property>
</object>
You can do property/constructor injection into your job by overiding CreateJobInstance of
AdaptableJobFactory and register your new JobFactory instead of the default one.
The passed in TriggerFiredBundle provides you with enough infos to ask the context for a matching job (based on conventions). bundle.JobDetail.JobType.Name and bundle.JobDetail.JobType fitted my need, so back in 2008 I ended up with sth. like this (the class is derived form AdaptableJobFactory and implements IApplicationContextAware to get the context injected):
public class ContextAwareJobFactory : AdaptableJobFactory, IApplicationContextAware
{
private IApplicationContext m_Context;
public IApplicationContext ApplicationContext
{
set
{
m_Context = value;
}
}
protected override object CreateJobInstance( TriggerFiredBundle bundle )
{
return m_Context.GetObject( bundle.JobDetail.JobType.Name, bundle.JobDetail.JobType );
}
}
You need to register the ContextAwareJobFactory using the following config:
<objects xmlns="http://www.springframework.net">
<!-- Some simple dependency -->
<object name="SomeDependency" type="Namespace.SomeDependency, Assembly" />
<!-- The scheduled job, gets the dependency. -->
<object name="ExampleJob" type="Namespace.ExampleJob, Assembly" singleton="false">
<constructor-arg name="dependency" ref="SomeDependency"/>
</object>
<!-- The JobDetail is configured as usual. -->
<object name="ExampleJobDetail" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz">
<property name="JobType" value="Namespace.ExampleJob, Assembly"/>
</object>
<!-- The new JobFactory. -->
<object name="ContextAwareJobFactory" type="Namespace.ContextAwareJobFactory, Assembly" />
<!-- Set the new JobFactory onto the scheduler factory. -->
<object id="quartzSchedulerFactory" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz">
<property name="JobFactory" ref="ContextAwareJobFactory"/>
</object>
</objects>
I don't know if there is sth. ootb since this was developed in 2008 and I did not followed the integration progress made for quartz.net.
Can anyone kindly provide me an example of using IoC (structureMap / Spring.Net) for swapping connection string in Data Access Layer in Development & Production? (In C# if possible)
Thanks
Don't know about Spring.Net but this is how I usually do it in ASP.Net, assuming that you have a DAL that accept a db connection string.
<connectionStrings>
<add name="Development" connectionString="Enlist=false;MultipleActiveResultSets=True;Data Source=MYPC\SQLEXPRESS;Initial Catalog=Development;Integrated Security=True" providerName="System.Data.SqlClient"/>
<add name="Production" connectionString="Enlist=false;MultipleActiveResultSets=True;Data Source=MYPC\SQLEXPRESS;Initial Catalog=Production;Integrated Security=True" providerName="System.Data.SqlClient"/>
</connectionStrings>
public class MySession : ISession
{
public MySession(string connectionName)
{
// ...
}
}
ObjectFactory.Initialize(
x =>
{
x.For<ISession>()
.Use<MySession>().Ctor<string>("connectionName").Is("Development");
//.Use<MySession>().Ctor<string>("connectionName").Is("Production");
}
Dude i wouldn't do that if i was you
When you deploy, your connection strings for all your environments will go out to all your environments (security issue)
You are straying from the standard implementation, which means pain in the long run
But if you really needed to, you would probably have to do something like this: (this might not even work)
<db:provider id="PRODDbProvider" provider="SqlServer-2.0" connectionString="whateveritis" />
<db:provider id="DEVDbProvider" provider="SqlServer-2.0" connectionString="whateveritis" />
<object id="genericAdoTemplate" type="CustomAdoTemplate">
<property name="DbProviders">
<dictionary>
<entry key="PROD" value="PRODDbProvider" />
<entry key="DEV" value="DEVDbProvider" />
</dictionary>
</property>
</object>
Then have a custom AdoTemplate
public class CustomAdoTemplate : Spring.Data.Generic.AdoTemplate {
public object DbProviders {
get;
set;
}
public override object DbProvider {
get {
return DbProviders[GetCurrentEnvironmentKey()];
}
}
}