Error when running Ent Lib 5 Data Access Block in SIngleton object

Topics: Data Access Application Block
Feb 9, 2012 at 4:55 AM
Edited Feb 10, 2012 at 1:14 AM

[Issue created at Issue Tracker]


Dear all,

i hav data access code in a singleton object, and Initialize Accessors once and reuse many times. however after few  days running in windows service, the code will throw error  :

Object reference not set to an instance of an object. at System.Data.SqlClient.SqlDataReader.Bind(TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
at Microsoft.Practices.EnterpriseLibrary.Data.Database.DoExecuteReader(DbCommand command, CommandBehavior cmdBehavior) in e:\Builds\EntLib\Latest\Source\Blocks\Data\Src\Data\Database.cs:line 460
at Microsoft.Practices.EnterpriseLibrary.Data.Database.ExecuteReader(DbCommand command) in e:\Builds\EntLib\Latest\Source\Blocks\Data\Src\Data\Database.cs:line 846
at Microsoft.Practices.EnterpriseLibrary.Data.CommandAccessor`1.<Execute>d__0.MoveNext() in e:\Builds\EntLib\Latest\Source\Blocks\Data\Src\Data\CommandAccessor.cs:line 68
at MailDelivery.Service.MailManager.GetAllMail() in C:\Source Code\MailDelivery\MailManager.cs:line 338





that piece of code is an important entry point code and being used a lot,  the error only happen occasionally.

any thoughts ?

and once the first error is hit, each and every other Data Access code written in Ent Lib which uses Accessors and column mapping will fail with the column not found error.

code :

public IEnumerable<EmailAccount> GetAllEmailAccounts()
IEnumerable<EmailAccount> emailAccountList;

if (MemoryCache.Default.Contains(CacheKeyConstant.EmailAccountCacheKey)
&& MemoryCache.Default[CacheKeyConstant.EmailAccountCacheKey] != null)
emailAccountList = MemoryCache.Default[CacheKeyConstant.EmailAccountCacheKey] as IEnumerable<EmailAccount>;
emailAccountList = _getAllEmailAccAccessor.Execute();
MemoryCache.Default.Add(CacheKeyConstant.EmailAccountCacheKey, emailAccountList
, new CacheItemPolicy { SlidingExpiration = new TimeSpan(0, minutes: cacheTimeOutMinutes, seconds: 0) });

return emailAccountList;

private DataAccessor<EmailAccount> _getAllEmailAccAccessor;


EmailAccountAccess emailAccountAccess = new EmailAccountAccess();
_getAllEmailAccAccessor = emailAccountAccess.InitializeGetAllEmailAccountAccessors();


public DataAccessor<EmailAccount> InitializeGetAllEmailAccountAccessors()
Database db = EnterpriseLibraryContainer.Current.GetInstance<Database>();

DataAccessor<EmailAccount> emailAccountAccessor = db.CreateSprocAccessor("sp_GetAllEmailAccounts",
.Map(p => p.EmailAccount_Id).ToColumn("acc_id")
.Map(p => p.Prov_id).ToColumn("prov_id")
.Map(p => p.Username).ToColumn("acc_username")
.Map(p => p.Password).ToColumn("acc_password")
.Map(p => p.InsertBy).ToColumn("InsertBy")
.Map(p => p.InsertDate).ToColumn("InsertDate")
.Map(p => p.UpdateBy).ToColumn("UpdateBy")
.Map(p => p.UpdateDate).ToColumn("UpdateDate")

return emailAccountAccessor;

Feb 10, 2012 at 4:13 AM

Just curious about the error you are receiving.  Originally you posted that you were getting and IndexOutOfRangeException which seemed to indicate that the DataReader didn't contain a column.  Now you've posted that you are receiving a NullReferenceException.

Are you first receiving a NullReferenceException and then you get IndexOutOfRangeException after the NullReferenceException?  

Thanks for providing more code. What object is the singleton you mention?  Is the GetAllEmailAccounts method called?  In the stack trace it's indicating that the GetAllMail() is what is calling the accesor.

As an aside it's not recommended to prefix stored procedure names with sp_.

Randy Levy
Enterprise Library support engineer 

Feb 10, 2012 at 5:08 AM

hi Randy,

Sorry about the confusion about the error message, as I found that the original error which i posted "IndexOutOfRangeException" is the second error.

The second error will happen to all DataAccess code with mapping , after the first error happens, which is "Object reference not set to an instance of an object. at System.Data.SqlClient.SqlDataReader.Bind".

Within the function "GetAllMail()" which executes a DataAccessor, and when the code iterates through the Ienumerable result from the query, then the error happened.

I have posted my code and database at

By the way, thanks for the advise on the stored proc prefix.


Feb 11, 2012 at 3:42 AM

Just curious if there is anything that you think is happening when you see the issue?  E.g. many requests running or machine load or database load or something else?  You say that it happens when the service is running for days.  Does the issue occur if the service is recycled on a schedule (like every day)? Have you been able to reproduce the issue any other way?

Randy Levy
Enterprise Library support engineer 

Feb 12, 2012 at 11:35 PM

the windows service is running on timer, and execute by the timer only.

I can observe the problem happen more frequently on a windows server 2003 R2 if i remove the "lock (syncRoot)" on timer event, and set the timer interval to 1 second.

Sometimes the error happen within 24 hours after the service is recycled due to that error.

Is there any guidelines where the Initialized Accessors have to be recycled on a fixed interval ? Or using like that on a singleton object is bad idea ?

Well I put it into Singleton object is because of initializing those accessors takes longer time.

Feb 14, 2012 at 3:04 AM

Is it the accessor that takes a long time or is it the parameter and row mappers?

I found this recommendation from the Developer's Guide:

Inferring the details required to create the correct mappings means that the default parameter and output mappers can have an effect on performance. You may prefer to create your own custom mappers and retain a reference to them for reuse when possible to maximize performance of your data access processes when using accessors. 

I'm not 100% sure what is going on but it sounds like some sort of race condition.  What if you only cache the mappers and use a new accessor instance?

Randy Levy
Enterprise Library support engineer 

Feb 14, 2012 at 8:00 AM

A typical DataSccessor takes 3 millisecond to initialize, including ParameterMapper and MapBuilder

MapBuilder alone took 2 milisecond , so I guess MapBuilder is the expensive operation here.

Well caching MapBuilder might be a good idea, but my code is in pre-prodcution run, is a little risky to change that now.

I will try to change to MapBuilder caching and test to see if the error still happens.

Is it the DataAccessor is not thread safe ? And when executed by by several thread will cause problem ?

Feb 15, 2012 at 12:47 AM

ADO.NET is not thread safe, so accessors aren't either.

Feb 15, 2012 at 1:01 AM

oh ok, then i guess the problem comes from my part where i let multiple thread share the same data accessors.

i will change my code then, thanks for the help

Feb 15, 2012 at 1:44 AM

just 1 more question, if I cache the MapBuilder and share across thread, will that be alright ? i mean will there be thread safe issue ?

Feb 15, 2012 at 3:18 AM
Edited Feb 15, 2012 at 3:18 AM

I would have thought that you would cache the IRowMapper<T> (the output of the MapBuilder).   

IRowMapper<T> (implemented as ReflectionRowMapper<T>) looks to be threadsafe. 

Randy Levy
Enterprise Library support engineer 

Feb 15, 2012 at 4:13 AM

ok, thanks for the help