New Posts New Posts RSS Feed: Multiple UserBase implementations
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Multiple UserBase implementations

 Post Reply Post Reply
Author
stephenmcd1 View Drop Down
DevForce MVP
DevForce MVP


Joined: 27-Oct-2009
Location: Los Angeles, CA
Posts: 166
Post Options Post Options   Quote stephenmcd1 Quote  Post ReplyReply Direct Link To This Post Topic: Multiple UserBase implementations
    Posted: 18-May-2010 at 12:15pm
Along the lines of this post, I have a "guest" account used to access the BOS during the logon process.  Once the user authenticates, I switch to a standard account.

To implement this scenario, I have two custom classes that extend UserBase.  This used to work fine in 6.0.1.0 but seems to randomly break in 6.0.2.0 (I'm sure it's not actually random, but it seems that way). 

Using my good friend Reflector, I see this line of code in UserBase.GetCustomUserType():
Type type = ReflectionFns.GetTypeImplementing(typeof(UserBase), IdeaBladeConfig.Instance.GetAllProbeAssemblyNames(), Cardinality.ZeroOrOne, true);

So it appears you are now expecting only zero or one custom UserBase implementations (that is, you don't expect two like in my case).

What is particularly weird is that sometimes my app works fine...I'm not sure if it has to do with when things get probed or what, but at least in some cases it's a fatal error that breaks my logon process.

Back to Top
kimj View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 1391
Post Options Post Options   Quote kimj Quote  Post ReplyReply Direct Link To This Post Posted: 18-May-2010 at 2:36pm
Actually, we supported only a single custom UserBase implementation in 6.0.1, as we do in 6.0.2.  In 6.0.1 we weren't looking at the correct list of assemblies, and this logic was also located in the AspAuthenticatingLoginManager class instead of UserBase.  In 6.0.1 we also returned the standard UserBase type for anonymous users - in 6.0.2 we return the custom UserBase type if one is found. 
 
We support only a single custom UserBase because the AspAuthenticatingLoginManager only knows to return the standard UserBase or the one and only custom UserBase.  If you need multiple UserBase classes you'll need to sub-class the AspAuthenticatingLoginManager and override the CreateUserCore() method(s) to return the correct UserBase.  If you're not using ASP.NET security, or don't want to use the AspALM, then you can implement a custom IEntityLoginManager implementation where you'll have full control over this.
Back to Top
stephenmcd1 View Drop Down
DevForce MVP
DevForce MVP


Joined: 27-Oct-2009
Location: Los Angeles, CA
Posts: 166
Post Options Post Options   Quote stephenmcd1 Quote  Post ReplyReply Direct Link To This Post Posted: 18-May-2010 at 3:28pm
I'm confused...you say "we supported only a single custom UserBase implementation" but does that only apply if we're using the AspALM?  Otherwise you do support multiple?

I guess we didn't run into the problem in 6.0.1 because we aren't using the AspALM so this check didn't get hit but then you moved the check to UserBase so now we hit it (if I understand correctly).

We aren't using ASP.NET security and don't use AspALM and also implement our own custom IEntityLoginManager...however, we seem to still hit the limitation of on multiple UserBase's.  The UserBase class checks to make sure there is only one custom UserBase as part of it's static constructor so I can't really do anything related to UserBase without getting an exception (in my case, I'm trying to new up an instance of my custom UserBase class but that doesn't work).

Hope that made sense...
Back to Top
kimj View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 1391
Post Options Post Options   Quote kimj Quote  Post ReplyReply Direct Link To This Post Posted: 18-May-2010 at 4:03pm

Ah, OK, there is a problem with the type initializer on UserBase.  We'll get this fixed in 6.0.3 (coming in early June).  Until then, you can use only the standard UserBase and one custom UserBase type.  Sorry for the inconvenience.

Back to Top
pk55 View Drop Down
Senior Member
Senior Member


Joined: 22-Jul-2009
Location: CA
Posts: 105
Post Options Post Options   Quote pk55 Quote  Post ReplyReply Direct Link To This Post Posted: 18-May-2010 at 5:40pm
Just to chime in with Stephen (we work together); this 'seems' to only manifest itself (in 6.0.2) as a problem when using a PassThruESQLQuery on the server-side (6.0.1 worked fine).  As part of our intial load of data, we call an RPC method to load up the server-side EntityManager cache with all the necessary entities and then ship the cache back to the client where it's merged back into the client-side EntityManager.
 
As part of this process on the server, we use ESQL to generically load the entities so you get something like this being executed for each entity to load:
IEntityQuery query = new PassthruEsqlQuery (typeof(MyEntity), "SELECT VALUE u FROM MyEntitySet AS u");
manager.ExecuteQuery(query);
 
For one of our 6 data models (the one that comes from a different database than the other 5), the ESQL will throw an error about:
 
Caught exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> IdeaBlade.EntityModel.EntityServerException: 'MyEntitySet' could not be resolved in the current scope or context.

If I switch that from ESQL to this, it works fine in the model:
 
IEntityQuery query = manager.MyEntitySet;
manager.ExecuteQuery(query);
 
Back to Top
pk55 View Drop Down
Senior Member
Senior Member


Joined: 22-Jul-2009
Location: CA
Posts: 105
Post Options Post Options   Quote pk55 Quote  Post ReplyReply Direct Link To This Post Posted: 21-Jun-2010 at 3:24pm
In 6.0.3.1, I still see the same Zero or One test for EntityModel.dll UserBase that Stephen reported:
 
 
Does this mean you didn't fix the type initializer problem?  I'm confused if this 0 or 1 test was causing the problem or if you said that was correct but the problem was somewhere else that didn't allow more than one custom UserBase types.
 
I'm still getting the same odd behavior that I can't access a second database/edmx in one session of server-sid RPC method using ESQL.  The method first loads entities from one db/edmx and then loads the rest from the other db/edmx.  When the second entities try to load, they get an error:
 
'MyEntity' could not be resolved in the current scope or context. Make sure that all referenced variables are in scope, that required schemas are loaded....
 
Looking at the debug log, I see EdmKey::FindClientAssembly called for first db/datasource key and then the ESQL issued for each entity is executed but there isn't a second call to FindClientAssembly for the second db/datasource key entities (just the error). 
 
If however, I set a breakpoint in the code after all the first entities are loaded and then open the local variables for the server-side EntityManager and expand the DataSourceResolver > DataSourceKeys > Results View > (in our case, this models key is in the 0 index) > EdmKey and then hit F5 to continue, the remaining entities load without an issue and the debug log shows the second call to FindClientAssembly for that other datasource key.  If I close the app and leave the dev web server up and then run it again (removing the debug stop), it works fine.
 
I've tried duplicating this in another project that doesn't use a custom IEntityLoginManager but does use mutliple datasource keys and never have the problem there.
Back to Top
pk55 View Drop Down
Senior Member
Senior Member


Joined: 22-Jul-2009
Location: CA
Posts: 105
Post Options Post Options   Quote pk55 Quote  Post ReplyReply Direct Link To This Post Posted: 22-Jun-2010 at 4:41pm
The problem I'm having does not appear to be related to UserBase.  It seems to be an issue with using a custom login manager and multiple EDMX datasources that use datasource key extensions (a multi-tenant app).
 
I've been able to duplicate the problem by modifying your Security sample app (which is in C:\Program Files\DevForce 2010\Learning Resources\100_Security\Samples\300COR\CodeCS\DatabaseLookup_ConsoleUI\Security.sln) which doesn't return a UserBase but just returns an IPrincipal credential.
 
If you first authenticate without using any datasource key extensions (which seems to be the only way to do that) and during that login process, query the database (like you do for Users in that example and we do as well), any entities in the EDMX associated with that datasource key that was used during login won't be loaded when you make subsequent calls to a server-side RPC method using ESQL (they will work using just DevForce Linq queries) where the Entity Manager has been created using a datasource key extenstion for the same EDMX.
 
I've opened a support ticket for this (#7066) and have attached the sample solution.
 
Back to Top
ting View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 27-Mar-2009
Location: San Francisco
Posts: 427
Post Options Post Options   Quote ting Quote  Post ReplyReply Direct Link To This Post Posted: 22-Jun-2010 at 7:45pm
The console app you submitted with the NorthwindIB database was very clean.  This helps a lot in tracking it down and we are working on it.  Thanks!
Back to Top
pk55 View Drop Down
Senior Member
Senior Member


Joined: 22-Jul-2009
Location: CA
Posts: 105
Post Options Post Options   Quote pk55 Quote  Post ReplyReply Direct Link To This Post Posted: 28-Jun-2010 at 12:40pm
Any progress on this or a timeline when it might be fixed? 
Back to Top
ting View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 27-Mar-2009
Location: San Francisco
Posts: 427
Post Options Post Options   Quote ting Quote  Post ReplyReply Direct Link To This Post Posted: 28-Jun-2010 at 8:00pm
We will have this fixed in the next release (scheduled for the last two weeks in July).
 
I'll send you a workaround as a follow up to the support case you submitted.
 


Edited by ting - 28-Jun-2010 at 8:00pm
Back to Top
pk55 View Drop Down
Senior Member
Senior Member


Joined: 22-Jul-2009
Location: CA
Posts: 105
Post Options Post Options   Quote pk55 Quote  Post ReplyReply Direct Link To This Post Posted: 30-Jun-2010 at 1:45pm
Thanks, the work-around works for both ESQL and for Stored Procedure calls.
 
I didn't mention the SP issue before because it threw a different message but I was pretty sure it was related as it returned an entity that was in the container for the datasourcekey that wasn't getting initialized correctly.
 
I'm pasting your work-around in case anyone else needs it.  Just make sure you add references to your project for IdeaBlade.EntityModel.Edm.dll, IdeaBlade.EntityModel.Edm.Metadata.dll (wasn't sure if metadata was really needed but I added it) and System.Data.Entity.dll and add the using statements in the server class:
 

using System.Data.Metadata.Edm;    // for the key.EntityContainer

using IdeaBlade.EntityModel.Edm;
 

Here's the workaround until the next release.  Basically, you need to access the EntityContainer which will force the correct initialization.  Here's some sample code written as an RPC call to the server, but you could also put this in the EntityServerQueryInterceptor.

public static EntityCacheState LoadInitialData(IPrincipal principal, EntityManager serverEm, params object[] args) {

  var manager = (NorthwindIBEntities)serverEm;

 

  // Hack -

  // Get the DataSourceKey used by the problem query.  It's a server-side EdmKey.  Accessing the EntityContainer forces initialization.

  var key = manager.DataSourceResolver.GetDataSourceKey(typeof(Customer)) as IdeaBlade.EntityModel.Edm.EdmKey;

  var ec = key.EntityContainer;

      …..

}

Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down