What ScopeType should be used during construction of seam objects - seam

UserList userList = (UserList) Component.getInstance(UserList.class);
return userList.getUserByLoginId(loginId);
A sample code usage of fetching a user by login id is given below. I instantiate the UserList class to call the method. What ScopeType should I use here specifically so that the object's scope is minimal.

If you want to access authenticated users via your UserList object you must keep it in application scope. But, it is alive during the entire application life. So, it is not minimal.
Another approach may store logged-in users in a database table and you can query this table via an event scoped component. Event scope is equivalent of Http's "request" scope. So, it is killed after each server request.

Related

Change tracking information using DbContext

In reading an article on N-Tiered Applications, I came across information regarding concurrency tokens and change tracking information:
Another important concept to understand is that while the
default-generated entities support serialization, their
change-tracking information is stored in the ObjectStateManager (a
part of the ObjectContext), which does not support serialization.
My question is three-fold:
Is there the same thing when using DbContext?
If the only interaction with the database is in a Repository class within a using statement, does closing the database connection when the program leaves the using statement get rid of any option for change tracking?
Can this be leveraged as/with a Concurrency Token?
Yes. DbContext is just wrapper around ObjectContext and it exposes change tracking information through ChangeTracker property (returns DbChangeTracker) and for particular entity through calling Entry method (returns DbEntityEntry<T>).
Yes. Closing context will remove all change tracking information.
Concurrency token and change tracking are two completely different concepts. Change tracking tells context what operations it has to execute on database when you call SaveChanges. It tracks changes you did on your entities since you loaded them into current context instance. Concurrency token resolves optimistic concurrency in the database => it validates that another process / thread / user / context instance didn't change the same record your context is going to modify during SaveChanges.

Symfony2: Is better to use session object or my own manager?

Related to that question.
I've understood that I have to create some services for handle my entity and so on. That's because I have to "move" my logic away from controllers and place into "managers" (i.e. services)
Now I have a service that have some logic into it. In that service I, depending on user, return a list of "associated object" - say that those object are sport's team.
Let's say that first element of my list (generated from a repository somehow) is the "default" team and say that I have a page were I can change it FOR all session long.
After log out or sessions stale, I want to return at "default" situation.
So my idea was: "since I've wrote a manager for this entity, I'll write a private attribute in this class where load (from db) this property and store (temporarily, with setter method) my changes."
This doesn't affect my db and I can keep my information for all session long.
But a thought came into my mind: how about session object? (is a service, if I didn't understood wrong)
Is my solution a good solution, or is better to store my information into session object?
From my point of view it's the same except that I can read session's variables directly from twig by using app.session. Am I wrong?
Moreover, if I'm not wrong, how can I access my object properties from twig without each time pass them from controller? (is much like having a global variable that I want to display everywhere into my application pages).
Edit:
More information can be found in this chat transcript.
If you want to store a variable for the duration of a session (for example, login until logout or as long as the user doesn't close his browser window) you have to store it in the session object. If you want to store a variable for the duration of a request, you can store it in the manager service.
However, you can use the manager service to load the session variable and make it available to the controller.
Just like it is a good idea to decouple the controller from the database/Doctrine it is also a good idea to decouple the controller from the session.
Update: As mentioned in the comments when looking at REST it is not a good idea to do the session stuff in the service. However, you should still store the variables in the session and use the controller to set the value in the service.

Custom IIdentity or IPrincipal Or something else

I'm finding that in the current application I'm working with, I'm retrieving several entities (related to the authenticated users account) in almost every controller. These entities are cached at the orm layer however, it seems that these entities would be a good candidate to load once at authentication time and add a few properties to the applications custom IPrincipal object.
Another option I was thinking of was creating a custom context object (with the users related account objects) and passing it around with the current request.
Benefits / drawbacks to either approach? Is there another way of dealing with commonly used objects like this?
It sounds like you miss the fact that the instance of IPrincipal/IIdentity is recreated upon every request. It is not persisted anywhere if you not persist it in an explicit way.
I don't think then there's performance difference between a custom principal class holding the data vs a cached ambient property.
On the other hand, the drawback of a custom authentication classes is that you have to provide a custom authentication module so that these instances are recreated during AuthenticateRequest event in the processing pipeline. In other words, you'd have to replace FormsAuthenticationModule with your own one. This is not difficult but I wouldn't do this if it is not absolutely necessary.
Note also that some data can be persisted in the UserData section of the forms cookie. This means that you can have it as long as the cookie is valid and create it only once.

NHibernate ISession specific event listener

I'm creating a multi-tenant ASP.NET application using NHibernate (shared schema). I had intended to use NHibernates Event Listeners to inspect/modify entities prior to saving to ensure that the current tenants ID was being saved against the entity.
The authentication token containing the tenant ID is managed higher up and passed down into the data layer.
My problem is that Event Listeners are configured against an NHibernate Configuration rather than a specific ISession. This means that there's no way to pass in any identifiers for it to use, although I can access the ISession that caused the event to fire.
How can I go about passing ISession specific data into the Event Listener?
You might be able to do this with an IInterceptor implementation because ISessionFactory has an overloaded OpenSession method that accepts an IInterceptor. Usage would be something like:
var interceptor = new MyInterceptor(tenantId);
var session = factory.OpenSession(interceptor);
Unfortunately there's no overload that accepts listeners.

does it make sense to cache nhibernate entities in httpcontext.current.session?

I'm learning NHibernate and was looking at some code recently where NHibernate was used in an ASP.Net MVC project.
In a certain part of this app, entities loaded from NH are being kept in the (HttpContext) Session. Is this OK, or are there any dangers with this if you use (NHibernate) Session-per-request pattern?
I wouldn't recommend it unless you really know what you're doing. Off the top of my head:
Entities stored in httpsession would have to be fully serializable, otherwise non-inproc session storage would break.
Lazy loading would break unless you explicitly reattach the entity to the new session.
If you want to have cross-request conversations check out NHibernate.Burrow which is a framework designed for this specific purpose.
"Session per request" with NHibernate does not have a relationship with HttpSession. "Session" in session per request is the NHibernate ISession. It's safe to store NHibernate.ISession in HttpContext.Current.Items at the beginning of the request and dispose it at the end of the request.
Yes you can and it does make sense to cache a frequently used object if you are fetching it based on a property that is not the primary key.
My site has a Person class which represents a specific user on the site. On any given web request I need to fetch the current logged-in user object several times to access various configuration settings and properties that are specific to the current user. Rather than hitting the database every time, I store the current user in HttpContext.Items[] and I have a static method that checks if the Items cache contains the current user. If it does, return it, if it doesn't get it from the database and add it to the cache so its available next time:
public static Person CurrentUser
{
get
{
if(!IsAuthenticated) return null;
Person person = (Person) HttpContext.Current.Items[HttpContext.Current.User.Identity.Name];
if(person != null) return person;
IPersonDao personDao = new PersonDao();
person = personDao.getByUsernameEmail(HttpContext.Current.User.Identity.Name);
if(person==null)
{
FormsAuthentication.SignOut();
HttpContext.Current.Response.Redirect("/");
}
HttpContext.Current.Items[HttpContext.Current.User.Identity.Name] = person;
return person;
}
}
I also store my NHibernate session object in HttpContext.Items so the session and the cached object will be garbage collected at the same time at the end of the HttpRequest, what you don't want is for the object to survive past the lifetime of the session, otherwise a new session may start and NHibernate will barf with a NHibernate.NonUniqueObjectException because the object is bound to another session.
Its worth pointing out that the NHibernate's 1st level cache keeps all objects accessed by the session cached by ID. If I was calling session.get(id) there is no need to cache as NHibernate's 1st level cache maintains objects by their id. But in the above case where I am fetching the person object by the User.Identity.Name the 1st level cache doesn't work as the user's username is not the primary key of the object.
More info on HttpContext.Items https://web.archive.org/web/20210608183011/http://aspnet.4guysfromrolla.com/articles/060904-1.aspx
DO NOT use HttpContext.Cache, which for some reason lasts beyond the Http Request.

Resources