c# - Intermittent error Linq to NHibernate Sequence Contains no Elements -
this may sound duplicate question, don't believe is.
this error i'm getting, sounds common. i'm getting error intermittently. number of users site, i'm estimating occurs 5% of time.
here's code:
private topwrestlers filltopwrestlers() { try { var mostrecent = _wrestlerrankingrepo.query().orderbydescending(wr => wr.season).first().season; var currentseason = _configservice.getcurrentseason(); if (mostrecent > currentseason) return null; var tws = _wrestlerrankingrepo.getrankedwrestlers(currentseason) .where(wr => wr.rank <= 3) .orderby(wr => wr.rank) .select(wr => wr.wrestler); return new topwrestlers { _125 = tws.firstordefault(w => w.roster.weightclass == 125), _133 = tws.firstordefault(w => w.roster.weightclass == 133), _141 = tws.firstordefault(w => w.roster.weightclass == 141), _149 = tws.firstordefault(w => w.roster.weightclass == 149), _157 = tws.firstordefault(w => w.roster.weightclass == 157), _165 = tws.firstordefault(w => w.roster.weightclass == 165), _174 = tws.firstordefault(w => w.roster.weightclass == 174), _184 = tws.firstordefault(w => w.roster.weightclass == 184), _197 = tws.firstordefault(w => w.roster.weightclass == 197), _285 = tws.firstordefault(w => w.roster.weightclass == 285) }; } catch (exception ex) { _errorservice.logerror(new exception("exception occurred trying retrieve top wrestlers each weight on home page. " + ex.message, ex)); return null; } }
i'm getting error on first line:
_wrestlerrankingrepo.query().orderbydescending(wr => wr.season).first().season;
i know repo has data. since returns fine 95% of time.
any on how can figure out how fix bug? i'm not able re-create issue. on homepage of site. don't believe has new session firing up....i'm @ loss here.
here's base repo code:
public abstract class baserepository<trecord, tmap> : ibaserepository<trecord> trecord : class, ientity tmap : classmap<trecord>, new() { private static member _primarykeymember; protected isession session; protected iuseridentity useridentity; public baserepository(isession session) { session = session; } public baserepository(isession session, iuseridentity useridentity) { session = session; useridentity = useridentity; } public void delete(trecord obj) { session.delete(obj); session.flush(); } public void save(trecord value) { session.saveorupdate(value); session.flush(); } public void save(ienumerable<trecord> values) { using (itransaction sessiontransaction = session.begintransaction()) { try { foreach (trecord value in values) session.saveorupdate(value); sessiontransaction.commit(); session.flush(); } catch { sessiontransaction.rollback(); throw; } } } public virtual iqueryable<trecord> query() { return session.query<trecord>(); } } public interface ibaserepository<trecord> trecord : ientity { void delete(trecord obj); void save(trecord value); void save(ienumerable<trecord> values); iqueryable<trecord> query(); }
and here's wrestlerrankingrepo code:
public class wrestlerrankingrepository : baserepository<wrestlerranking, wrestlerrankingmap>, iwrestlerrankingrepository { public wrestlerrankingrepository(isession session) : base(session) { } public iqueryable<wrestlerranking> getrankedwrestlers(int season) { return base.query() .where(wr => wr.rank != null) .where(wr => wr.season == season) .where(wr => wr.iscurrent) .where(wr => !wr.wrestler.lastname.startswith("(")); } public iqueryable<wrestlerranking> getrankedwrestlers(int season, int weight) { return getrankedwrestlers(season) .where(wr => wr.weightclass == weight); } public iqueryable<wrestlerranking> getrankedwrestlerswithmatches(int season) { return getrankedwrestlers(season); // reason hates this: .where(w => w.currentstats != null) } public iqueryable<wrestlerranking> getrankedwrestlerswithmatches(int season, int weight) { return getrankedwrestlers(season) .where(w => w.weightclass == weight); // reason hates this: .where(w => w.currentstats != null) } } public interface iwrestlerrankingrepository : ibaserepository<wrestlerranking> { iqueryable<wrestlerranking> getrankedwrestlers(int season); iqueryable<wrestlerranking> getrankedwrestlers(int season, int weight); iqueryable<wrestlerranking> getrankedwrestlerswithmatches(int season); iqueryable<wrestlerranking> getrankedwrestlerswithmatches(int season, int weight); }
sessionfactory code:
public static class sessionfactory { private static isessionprovider _instance; public static isessionprovider instance { { if (_instance == null) { string sessionclass = configurationmanager.appsettings["sessionprovider"]; if (string.isnullorwhitespace(sessionclass)) throw new configurationerrorsexception("session provider must specified in app.config"); _instance = (isessionprovider)activator.createinstance(type.gettype(sessionclass)); } return _instance; } } [obsolete] public static isession getcurrentsession() { return getsession(); } public static isession getsession() { return instance.getsession(); } public static string getconnectionstring() { return configurationmanager.connectionstrings["wrestlestat"].connectionstring; } public static ipersistenceconfigurer buildconfig() { return mssqlconfiguration.mssql2008.connectionstring(getconnectionstring()); } public static void buildmappings(mappingconfiguration mappings) { mappings.fluentmappings.addfromassembly(assembly.getexecutingassembly()); } } public class sqlstatementinterceptor : emptyinterceptor { public override sqlstring onpreparestatement(sqlstring sql) { trace.writeline(sql.tostring()); return sql; } } public interface isessionprovider { isession getsession(); isession opensession(); void closesession(); }
here's ninject impelementation:
private static void registerservices(ikernel kernel) { kernel.bind(scanner => scanner .from(new list<assembly> { typeof (homecontroller).assembly, typeof (match).assembly }) .selectallclasses() .bindallinterfaces() .configure(b => b.intransientscope()) ); kernel.rebind<isession>().tomethod(icontext => sessionfactory.getsession()).inrequestscope(); //kernel.rebind<iuseridentity>().tomethod(i => mvcapplication.getwebidentity()).inrequestscope(); }
another spot that's relevant...
public class corewebsessionmodule : ihttpmodule { public void init(httpapplication context) { context.beginrequest += opensession; context.endrequest += closesession; } private static void opensession(object sender, eventargs e) { sessionfactory.instance.opensession(); } private static void closesession(object sender, eventargs e) { sessionfactory.instance.closesession(); } public void dispose() { } }
one more
public class corewebsessionprovider : isessionprovider { private static isessionfactory _holder; private static isessionfactory mysessionfactory { { if (_holder == null) { _holder = getfluentconfiguration().buildsessionfactory(); } return _holder; } } public isession getsession() { return httpcontext.current != null ? mysessionfactory.getcurrentsession() : null; } public isession opensession() { var session = mysessionfactory.opensession(); managedwebsessioncontext.bind(httpcontext.current, session); return session; } public void closesession() { var session = managedwebsessioncontext.unbind(httpcontext.current, mysessionfactory); if (session != null) { if (session.transaction != null && session.transaction.isactive) session.transaction.rollback(); //else // session.flush(); if (session.isopen) session.close(); } } private static fluentconfiguration getfluentconfiguration() { return fluently.configure() .database(sessionfactory.buildconfig()) .exposeconfiguration(buildschema) .mappings(sessionfactory.buildmappings); } public static configuration getconfiguration() { return getfluentconfiguration().buildconfiguration(); } private static void buildschema(configuration config) { config.setproperty("current_session_context_class", "managed_web"); } public istatelesssession getstatelesssession() { return mysessionfactory.openstatelesssession(); } }
from nhibernate documentation
(emphasis mine):
an isessionfactory expensive-to-create, threadsafe object intended shared application threads. isession inexpensive, non-threadsafe object should used once, single business process, , discarded
so should not sharing session object around this. if possible, create 1 when needed , destroy possible.
some excellent further reading here talks context , lifetime, including nhibernate.
Comments
Post a Comment