locked
PreProcessQuery Recursive Execution RRS feed

  • Question

  • I have following Entities

    Offices (Id, OfficeName)

    CustomUsers (Id, UserName)

    CustomUserOffices (Id, CustomUser, Office)

    CustomUserOffices is a Junction Table for many to many relationship b/w Offices and CustomUsers

    I have added 1 User in CustomUsers table which is "TestUser". And have added Office1, Office2, Office3 in Offices.

    In CustomUserOffices, I added

    TestUser, Office1

    TestUser, Office2

    As you can understand from above scenario, I am trying to restrict currently logged in user to select only Office1 and Office2 everywhere in Application.

    I understand that in PreProcessQuery we can't join the query, we can only do filtering so, I would like to do something like this,

    In Offices_All_PreprocessQuery()

    var offices = from x in DataWorkspace.ApplicationData.CustomUserOffices 
                  where x.CustomUser.UserName == Application.Current.User.Name
                  select x;
    List<int> officeIDs = new List<int>();
    foreach(CustomUserOffice objCUO in offices)
        officeIDs.Add(objCUO.Office.Id);
    
    query = from x in query
            where officeIDs.Contains(x.Id)select x;

    But when above query gets executed, it executed recursively. I think this is because we are accessing the Office entity within the loop, maybe this the thing which is causing this issue.

    A workaround can be do put a static boolean flag which we can set to true when we get in the function, then on function's start we can test that flag, if true then just return. But this is obviously a bad idea to me.

    Can anyone guide me in the correct direction?

    Thanks


    Thursday, June 21, 2012 7:50 PM

Answers

  • Instead of getting all applicable CustomUserOffice instances and then finding the Office instances that match, think of it in the other direction. Find all Office instances where any CustomUserOffice contains a CustomUser instance that corresponds to the current user:

    string userName = this.Application.Current.User.Name;
    query = query.Where(o => o.CustomUserOffices.Any(cuo => cuo.CustomUser.UserName.Equals(userName)));

    This way, you do not reinvoke the Offices_All query because this entire expression is executed at the data source.

    Justin Anderson, LightSwitch Development Team

    Thursday, June 21, 2012 8:23 PM
    Moderator

All replies

  • Instead of getting all applicable CustomUserOffice instances and then finding the Office instances that match, think of it in the other direction. Find all Office instances where any CustomUserOffice contains a CustomUser instance that corresponds to the current user:

    string userName = this.Application.Current.User.Name;
    query = query.Where(o => o.CustomUserOffices.Any(cuo => cuo.CustomUser.UserName.Equals(userName)));

    This way, you do not reinvoke the Offices_All query because this entire expression is executed at the data source.

    Justin Anderson, LightSwitch Development Team

    Thursday, June 21, 2012 8:23 PM
    Moderator
  • Many thanks Justin.

    Just a little correction in your code. 

    this.Application.Current.User.Name;  <- Here we will NOT be using Current I guess.


    Friday, June 22, 2012 5:57 AM