So, Marckus, you are suggesting that, in my particular scenario, I should not rely on AR for any ops (find, create, save or delete); but to construct my own HQL queries in order to do so while mapping my non AR entities straight to hibernate, right? That sounds pretty logical, I'll try that one, thanks!!!
However, how can I query all those many-to-many relations?? I mean, the relations are stored in a intermediate table that I should not query (or should I?) so how can I find all the OperatingSystem linked with a specific FileInstance? Thanks again for all these effords! On May 1, 3:01 pm, Markus Zywitza <[email protected]> wrote: > Performancewise the best result is a query that defines the data that will > be loaded in one roundtrip to the database. If you use lazy loading on 25 > rows of the root entity, you will have the N+1 problem, in this case you > have 1 call to load the 25 rows and 25 more calls to load each lazily loaded > collection. This is one reason to constraint the number of bidirectional > relations. > > So if you can use a query like "from Root r join fetch r.Children where > r.Prop = :whatever", you will get the best performance possible,loading all > required data (and only the required data) in one call. > > However, if you have to map to an external entity nonetheless, did you try > to map those entity with "naked" NHibernate to the database tables. This > works of course only if you are allowed to make the properties virtual and > have a public parameterless constructor for those entities. It saves you > manually mapping the AR types to the entities and allows you to use > StatelessSession to enhance performance even more. > > -Markus > > 2009/4/30 Corisco <[email protected]> > > > > > As a test, I've tried modifying directly the web appp in order to > > provide session per request strategy but it seriously unstabilizes the > > webapp (it's a complex and maybe not too well designed one). That > > leads me to think that this is not a valid approach. > > > Markus, thanks you too for the tips. But, will this configuration help > > impovring performance? Or is it just for correctness on the design? I > > say so because I have to translate the AR entity into another kind of > > objects accessible outside the dll (another mandatory constraint). So > > I do just use find, create and save ops. Each one of these ops > > translates the AR entity obtained and its one-step relationated > > entities. > > > I've been profiling the app and realized that most of the time is lost > > calling ReleaseSession that in turn calls > > NHibernate.Utils.CollectionHelper.CollectionEquals and that is the > > method that is spending most of the time. I've tried encapsulating all > > read-only calls inside a "using ( new SessionScope > > ( FlushAction.Never ) )" and it improves a lot but not enough when the > > DB in relatively loaded (20-25 rows per table with the corresponding > > relations). > > > Any help please?? > > > Best regards! > > > On Apr 28, 9:21 pm, Markus Zywitza <[email protected]> wrote: > > > Having three types (application, category and package) reference each > > other > > > bidirectionally is not really a good idea. At least, one side of each > > > relation should be marked as inverse. Additionally, you are getting into > > > trouble as soon as you are updating or deleting data with such a model. > > > > I recommend making the relations to category unidirectional, such that > > > category does not have a list of applications or packages. If you need to > > > find packages or applications for a category, you can use a query. If the > > > relation between application and package remains bidirectional, you > > should > > > mark one side of it as inverse (presumably package). > > > > On the type that has the inverse end of the relation, the collection > > > property should be protected internal, offering only ReadOnlyCollection > > or > > > IEnumerable<T> publicly. This is by the way recommended for all > > > bidirectional collection-valued properties, with Add/Remove-methods for > > all > > > publicly available collections, that also set the inverse end of the > > > relation so that all relations are always synchronized. > > > > As for the SessionScope and the DAL, you can always build a fools > > > indirection, using SessionScope by delegation in your own type. > > > Oversimplified example: > > > > public class UnitOfWork : IDisposable > > > { > > > private SessionScope scope; > > > public UnitOfWork() > > > { > > > scope = new SessionScope(); > > > } > > > public void Dispose() > > > { > > > if (scope != null) scope.Dispose(); > > > } > > > > } > > > > -Markus > > > > 2009/4/28 Corisco <[email protected]> > > > > > Jason, thanks for the tip, I'll give it a try. However, if anyone else > > > > have a different idea all the help is welcomed > > > > > By the way, sorry for the duplicated post!! > > > > > On Apr 28, 2:42 pm, Jason Meckley <[email protected]> wrote: > > > > > just because the data access is located in a remote dll doesn't mean > > > > > you cannot use Session/Request. You can use another object to > > delegate > > > > > the creation/destruction of the session in relation to the request > > > > > which references the DAL assembly. For more information see how > > > > > Caste.NHibernateFacility.SessionManager works. > > > > > > If this isn't an option then you need to preload all the data you > > need > > > > > when you make the call to the DAL. Either than or pass the entity > > back > > > > > to the DAL, merge with the current session, and then load other > > > > > properties. > > > > > > On Apr 28, 6:09 am, Corisco <[email protected]> wrote: > > > > > > > I am developing somekind of CMS web app. After few additions to the > > DB > > > > > > it experiences huge performance problems. I'm new to the > > > > > > ActiveRecord / NHibernate world. So probably I'm making some > > > > > > configuration mistakes, but I'm not able to solve it. > > > > > > > I have tried using lazy relations and it seems to improve a lot. > > But > > > > > > now I'm getting the famous 'Failed to lazily initialize a > > collection - > > > > > > no session' error. However, I have to encapsulate all db related > > > > > > actions in a dll apart so I cannot enable the session-per-request > > as > > > > > > suggested inhttp:// > > > > using.castleproject.org/display/AR/Enable+Session+per+Request > > > > > > > I don't even know if the lazy relations solution is the correct > > > > > > approach. Any clue? > > > > > > > Thanks in advance!! > > > > > > > I'm initializing ActiveRecord through an > > InPlaceConfigurationSource. > > > > > > The basic scheme, designed with ActiveWriter, looks like this > > > > > > (summarized) > > > |------------(n-m)--------------------->>CMSTransientCategory<<-----------------(n-m) > > > > --------| > > > > > > > | > > > > > > | > > > > > > | > > > > > > | > > > |--->>CMSTransientApplication<<---------(n-m)------------->>CMSTransientPackage<<---| > > > > > > > | > > > > > > | > > > > > > | > > > > > > |---------(1-n)----->>CMSTransientFileInstance<<----(n- > > > > > > m)----->>CMSTransientOperatingSystem > > > > > > > | | > > > > > > > | | > > > > > > CMSTransientFileInformation<<----(1-n)----| |---(1-n)-- > > > > > > > >>CMSTransientContentType > > > > > > > These are the parameters used for initialization > > > > > > > isWeb=True > > > > > > isDebug=False > > > > > > hibernate.connection.driver_class=NHibernate.Driver.SqlClientDriver > > > > > > hibernate.dialect=NHibernate.Dialect.MsSql2005Dialect > > > hibernate.connection.provider=NHibernate.Connection.DriverConnectionProvider > > > hibernate.connection.connection_string=Server=192.168.1.202\sqlexpress;Database=mssf;Uid=******;Pwd=*********; > > > > > > > And the generated classes are > > > > > > > [ActiveRecord()] > > > > > > public partial class CMSTransientCategory : > > > > > > CMSTransientEntity<CMSTransientCategory> { > > > > > > > private IList<CMSTransientPackage> _packages; > > > > > > private IList<CMSTransientApplication> _applications; > > > > > > > [HasAndBelongsToMany(typeof(CMSTransientPackage), > > > > > > ColumnRef="PackageId", ColumnKey="CategoryId", > > > > > > Table="Packages2Categories")] > > > > > > public virtual IList<CMSTransientPackage> Packages { > > > > > > get {return this._packages;} > > > > > > set {this._packages = value;} > > > > > > } > > > > > > > [HasAndBelongsToMany(typeof(CMSTransientApplication), > > > > > > ColumnRef="ApplicationId", ColumnKey="CategoryId", > > > > > > Table="Applications2Categories")] > > > > > > public virtual IList<CMSTransientApplication> Applications > > { > > > > > > get {return this._applications;} > > > > > > set{this._applications = value;} > > > > > > } > > > > > > } > > > > > > > [ActiveRecord()] > > > > > > public partial class CMSTransientPackage : > > > > > > CMSTransientEntity<CMSTransientPackage> { > > > > > > > private IList<CMSTransientCategory> _categories; > > > > > > private IList<CMSTransientApplication> _applications; > > > > > > > [HasAndBelongsToMany(typeof(CMSTransientCategory), > > > > > > ColumnRef="CategoryId", ColumnKey="PackageId", > > > > > > Table="Packages2Categories")] > > > > > > public virtual IList<CMSTransientCategory> Categories { > > > > > > get {return this._categories;} > > > set{this._categories = > > > > value;} > > > > > > } > > > > > > > [HasAndBelongsToMany(typeof(CMSTransientApplication), > > > > > > ColumnRef="ApplicationId", ColumnKey="PackageId", > > > > > > Table="Applications2Packages")] > > > > > > public virtual IList<CMSTransientApplication> Applications > > { > > > > > > get {return this._applications;} > > > set{this._applications > > > > = value;} > > > > > > } > > > > > > } > > > > > > > [ActiveRecord()] > > > > > > public partial class CMSTransientApplication : > > > > > > CMSTransientEntity<CMSTransientApplication> { > > > > > > > private bool _isExecutable; > > > > > > private bool _isRam; > > > > > > private IList<CMSTransientFileInstance> _fileInstances = > > new > > > > > > List<CMSTransientFileInstance>(); > > > > > > private IList<CMSTransientCategory> _categories; > > > > > > private IList<CMSTransientPackage> _packages; > > ... > > read more » --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Castle Project Users" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/castle-project-users?hl=en -~----------~----~----~----~------~----~------~--~---
