locked
Access to original data from the server data context RRS feed

  • Question

  • Here's the scenario, I have a UserAccount table that stores some bits about a user, I use ASP.Net Membership for authorisation and authentication.

     

    When I save a UserAccount, I intercept the change with a ChangeInterceptor and then call Membership.CreateUser().  Bit clunky but all good so far.  Next I want to add the user to a role, still fine.

     

    Say that now I want to remove the user from a role.  I send through the UserAccountRole record for deletion but because the associated UserAccount has already been removed from the UserAccountRole I have no direct access to the username with which to call RoleProvider.RemoveUsersFromRoles (because it needs a username and all I have is a UserId unique key).

     

    Short of firing up another context and selecting it in again is there a place to get to the original data?

     

    Thanks in advance

    Wednesday, December 10, 2008 1:53 AM

Answers

  • Have you tried querying for the object against the database using the same context but with a "no tracking" query from your change interceptor, such that the EF does not try to resolve entities to those in the state manager? (no tracking is set by using the MergeOption property in ObjectQuery<T>). That should give you access to the object as it is in the database (provided that it hasn't been deleted by some other client already).

    -pablo


     


    This posting is provided "AS IS" with no warranties, and confers no rights.
    • Marked as answer by Jif Thursday, November 12, 2009 9:02 PM
    Monday, December 15, 2008 5:43 PM
    Moderator

All replies

  • When you send the UserAccountRole record for deletion, can you access that in your change interceptor and look at the associated useraccount and get the user name. When the change interceptor is fired, the current object is passed in the interceptor, with all the original values. I am assuming that you need to call RoleProvider.RemoveUsersFromRoles in your change interceptor. Right?

    Am i missing something?

    Thanks
    Pratik
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Thursday, December 11, 2008 5:32 PM
    Moderator
  • The problem is that the original entity is indeed passed into the change interceptor however the related entities are not loaded and attempting to load them throws a:

    The Load method cannot return the EntityReference when the related object is in a deleted state.

    So there is no (easy) way to access the related data.

    Friday, December 12, 2008 4:31 AM
  • Interesting. This seems like a limitation in the underlying provider. Looking at the error, i can see you are using EF as the underlying data provider? i can follow up with them and see if they can fix this in their future release.

    If you are using EF, then you can use the following workaround: detach and attach the object again, query the entityreference, and call delete on the object again.

    Hope this helps.

    Thanks
    Pratik


    This posting is provided "AS IS" with no warranties, and confers no rights.
    Monday, December 15, 2008 2:20 AM
    Moderator
  • I am using EF, it seems like a pratical thing to do, could you please follow up with them.

    My workaround at the moment is to query the entity in another context on the server and then get the reference data from there.  I'll leave it like that for the time being.
    Monday, December 15, 2008 2:56 AM
  • Have you tried querying for the object against the database using the same context but with a "no tracking" query from your change interceptor, such that the EF does not try to resolve entities to those in the state manager? (no tracking is set by using the MergeOption property in ObjectQuery<T>). That should give you access to the object as it is in the database (provided that it hasn't been deleted by some other client already).

    -pablo


     


    This posting is provided "AS IS" with no warranties, and confers no rights.
    • Marked as answer by Jif Thursday, November 12, 2009 9:02 PM
    Monday, December 15, 2008 5:43 PM
    Moderator
  • We solved it using following query. The join is somewhat interesting: join c in db.Customers on u.Customer.Id equals c.Id 

            [ChangeInterceptor("Users")]
            public void OnChangeUsers(User user, UpdateOperations ops)
            {
                Customer customer = GetCustomerByUser(user);

                if (customer.Id != _currentCustomer.Id)
                {
                    throw new DataServiceException(401, "You can only modify your own entities");
                }
            }

            private Customer GetCustomerByUser(User user)
            {
                NarrowCastingEntities db = new NarrowCastingEntities();
                var customer = (from u in db.Users
                                join c in db.Customers on u.Customer.Id equals c.Id
                                where u.Id == user.Id
                                select c).FirstOrDefault<Customer>();

                if(customer == null) throw new DataServiceException(401, "Can't get the Customer for this user");

                return customer;
            }
    Tuesday, October 20, 2009 4:18 PM