locked
number of returned elements =1 -> query becomes a function? RRS feed

  • Question

  • Hi,

    I have an entity "MyUsers", and the corresponding query "CurrentUser". My PreProcessQuery looks like:

    Private Sub CurrentUser_PreprocessQuery(ByRef query As System.Linq.IQueryable(Of LightSwitchApplication.MyUser))
        query = From aMyUser In query
                Where aMyUser.UserName = Application.Current.User.Name
                Select aMyUser
    End Sub
    

    the CurrentUser normally always is only one person

    I am able to adress this from all over my program.

    Private Sub Document_Created()
        Me.Author = Me.DataWorkspace.ApplicationData.CurrentUser.SingleOrDefault.Name
        '...
    End Sub
    

    Now I found a new option in the properties Editor of the CurrentUser-query it is possible to select the number of returned elements from "many" to "1". I tried this, and Lightswitch makes a function out of my query, my code then gets a bit simpler:

    Private Sub Document_Created()
        Me.Author = Me.DataWorkspace.ApplicationData.CurrentUser.Name
        '...
    End Sub
    

    But when I run the code I get a ValidationException, I do understand, a query is not a function, but how to use this option?

    what is it good for?

    regards

    Oliver

    Wednesday, September 18, 2013 12:30 PM

Answers

  • Hi Oliver,

    It looks like the exception is being thrown from your call to dws.Application.SaveChanges.  I assume it is because the GTCLoggedLogin entity instance you are trying to insert is invalid.  Does this entity have any required fields or custom validation logic?  It does seem weird that you are inserting an empty entity.

    To debug this I would suggest turning on "Break on unhandled exception" (Tools > Exceptions > check "Thrown" for Common Language Runtime Exception) then when the validation exception is thrown look at it within the debugger.  You will want to look at the ValidationResults member of the ValidationException.

    • Marked as answer by OlimilO Thursday, September 19, 2013 4:12 AM
    Wednesday, September 18, 2013 3:46 PM

All replies

  • Hi Oliver,

    Can you include the ValidationException information?  What is the message and what are the ValidationResults?

    Thanks

    Wednesday, September 18, 2013 1:59 PM
  • Hi Oliver,

    I suspect the ValidationException is coming from someplace else within your code.  The Number of Results Returned option of the query does just what you observed in that a "One" query is considered a singleton query in that it must return zero or one results.  The programming model for invoking a singleton query is slightly different.  The main reason for this is that you cannot compose additional operators on top of a singleton query.  If more than one result is returned from a singleton query, an InvalidOperationException will be thrown when executed.

    One a side note, I noticed you used the SingleOrDefault operator on your "many" query - Me.Author = Me.DataWorkspace.ApplicationData.CurrentUser.SingleOrDefault.Name.  In this particular scenario, I suggest would using the Single operator instead.  It may make it easier to debug your code in the future.  The reason I say this is that SingleOrDefault will return null if no rows match the query.  You then immediately dereference the results to access Name.  This would cause a NullReferenceException if no rows are returned.  However if you used the Single operator and no rows were returned an InvalidOperationException will be thrown which will more clearly indicate what the problem is.

    Wednesday, September 18, 2013 3:33 PM
  • Hi snomis,

    thank you.

    in the meanwhile I reworked my code, and i must say sorry, it has to do with something different

    my original code during startup of default screen:

    Private Sub ProjekteListe_Created()
        Dim s As GTComSetting
        s = Me.DataWorkspace.ApplicationData.GTComSettings.SingleOrDefault
        If s Is Nothing Then
            s = DataWorkspace.ApplicationData.GTComSettings.AddNew
        End If
        If s.LogLogins Then
            Dim dws As DataWorkspace = Application.CreateDataWorkspace
            Dim ll As GTCLoggedLogin = dws.ApplicationData.GTCLoggedLogins.AddNew() 
            dws.ApplicationData.SaveChanges()
        End If
        Dim gtb As GTCBenutzer = Me.DataWorkspace.ApplicationData.CurGTCBenutzer.SingleOrDefault()
        If gtb.CurProjektId.HasValue Then
            Me.Projekte.SelectedItem = Me.DataWorkspace.ApplicationData.Projekte_Single(gtb.CurProjektId)
        End If
        If gtb.CurBaustelleId.HasValue Then
            Me.Baustellen.SelectedItem = Me.DataWorkspace.ApplicationData.Baustellen_Single(gtb.CurBaustelleId)
        End If
        _duringStart = False 
    End Sub
    

    the exception only occurs when LogLogins is true, the exception occurs in this line

    Dim gtb As GTCBenutzer = Me.DataWorkspace.ApplicationData.CurGTCBenutzer.SingleOrDefault()

    but now I guess it has something to do with "CreateDataworkspace"

    These are the excetion details that I copied to clipboard, I hope it is helpful even though it is german.

    C:\GeoTechControl\GTCom\CustomLightSwitchControls_MF\Bin\Release\System.Windows.Controls.Input.Toolkit.dll
    
    Microsoft.LightSwitch.ValidationException wurde nicht von Benutzercode behandelt.
      Message=Der Vorgang kann nicht ausgeführt werden, da mindestens ein Objekt ungültig ist. Rufen Sie die ValidationException.ValidationResults-Eigenschaft ab, um weitere Informationen zu erhalten.
      StackTrace:
           bei Microsoft.LightSwitch.Framework.Base.ExecutableObject.Execute(Boolean allowJoin)
           bei Microsoft.LightSwitch.Framework.Base.ExecutableObject.Execute()
           bei Microsoft.LightSwitch.Details.Framework.Base.MethodInvocation`2.Execute()
           bei Microsoft.LightSwitch.Framework.Base.DataService`2.SaveChanges()
           bei LightSwitchApplication.ProjekteListe.ProjekteListe_Created()
           bei LightSwitchApplication.ProjekteListe.DetailsClass.__ProjekteListe_InvokeCreated(ProjekteListe s)
           bei Microsoft.LightSwitch.Details.Framework.Client.ScreenDetails`2.<Microsoft.LightSwitch.Client.Implementation.Internal.IScreenDetailsImplementation.OnScreenUILoaded>b__1a()
           bei Microsoft.LightSwitch.Utilities.Internal.UserCodeHelper.CallUserCode(Type sourceType, String methodName, String instance, String operation, ILoggingContext context, Action action, String additionalText, Func`1 getCompletedMessage, Boolean tryHandleException, Boolean swallowException, Exception& exception)
      InnerException: System.Data.Services.Client.DataServiceClientException
           Message={"odata.error":{"code":"4","message":{"lang":"de-DE","value":"<?xml version=\"1.0\" encoding=\"utf-16\"?><ExceptionInfo><Message>Der Vorgang kann nicht ausgef\u00fchrt werden, da mindestens ein Objekt ung\u00fcltig ist. Rufen Sie die ValidationException.ValidationResults-Eigenschaft ab, um weitere Informationen zu erhalten.</Message><ValidationResults><ValidationResult><Message>Die Daten im Datensatz \"GTCLoggedLogin\" sind ung\u00fcltig.</Message><Id>Microsoft.LightSwitch.EntityObject.GeneralConstraintViolation</Id><Target>$1</Target></ValidationResult></ValidationResults><StackTrace>   bei Microsoft.LightSwitch.ServerGenerated.Implementation.DataProvider.LinqToEntitiesDataProvider`1.SubmitCore(IEnumerable`1 changes)\r\n   bei Microsoft.LightSwitch.ServerGenerated.Implementation.DataProvider.DataProvider.Submit(IEnumerable`1 changes)\r\n   bei Microsoft.LightSwitch.ServerGenerated.Implementation.DataServiceImplementation`1.PerformPersistCore(IEnumerable`1 eventsChangeSetItems)\r\n   bei Microsoft.LightSwitch.ServerGenerated.Implementation.DataServiceImplementation`1.&lt;&gt;c__DisplayClass46.&lt;PerformPersist&gt;b__45()\r\n   bei Microsoft.LightSwitch.Threading.DualDispatcherObject.Mutate(IDispatcher logicDispatcher, MutatorHost host, Action mutator)\r\n   bei Microsoft.LightSwitch.ServerGenerated.Implementation.DataServiceImplementation`1.PerformPersist(IEnumerable`1 eventsChangeSetItems)\r\n   bei Microsoft.LightSwitch.ServerGenerated.Implementation.DataServiceImplementation`1.Microsoft.LightSwitch.ServerGenerated.Implementation.IServerDataServiceImplementationCore.Submit()\r\n   bei Microsoft.LightSwitch.ServerGenerated.Implementation.DataService`1.&lt;&gt;c__DisplayClasse.&lt;Microsoft.LightSwitch.ServerGenerated.Implementation.IODataService.SaveChanges&gt;b__c()\r\n   bei Microsoft.LightSwitch.ServerGenerated.Implementation.DataServiceImplementation`1.InvokeOperationCore[T](String operationName, Object[] args, Boolean invokedFromODataClient, Func`1 invokeOperation, Action catchCallback, Action`2 serializeCustomExceptionInfo)</StackTrace></ExceptionInfo>"}}}
           StatusCode=500
           StackTrace:
                bei System.Data.Services.Client.BatchSaveResult.<HandleBatchResponse>d__a.MoveNext()
           InnerException: 
    

    regards

    Oliver

    Wednesday, September 18, 2013 3:36 PM
  • Hi Oliver,

    It looks like the exception is being thrown from your call to dws.Application.SaveChanges.  I assume it is because the GTCLoggedLogin entity instance you are trying to insert is invalid.  Does this entity have any required fields or custom validation logic?  It does seem weird that you are inserting an empty entity.

    To debug this I would suggest turning on "Break on unhandled exception" (Tools > Exceptions > check "Thrown" for Common Language Runtime Exception) then when the validation exception is thrown look at it within the debugger.  You will want to look at the ValidationResults member of the ValidationException.

    • Marked as answer by OlimilO Thursday, September 19, 2013 4:12 AM
    Wednesday, September 18, 2013 3:46 PM
  • hi snomis,

    thank you very much for your help. I found my mistake.

     my code now looks like:

        Try
            If s.LogLogins Then
                Dim dws As DataWorkspace = Application.CreateDataWorkspace
                Dim sets As GTComSetting = dws.ApplicationData.GTComSettings.SingleOrDefault
                If sets IsNot Nothing Then
                    Dim ll As GTCLoggedLogin = sets.GTCLoggedLogins.AddNew
                    dws.ApplicationData.SaveChanges()
                End If
            End If
        Catch ex As ValidationException
            For Each vr In ex.ValidationResults
                ShowMessageBox(vr.Message)
            Next
        End Try
    End Sub
    

    GTCLoggedLogins has relationship to GTComSettings, the vr.Message simply was "the entity has invalid data"

    filling the GTCLoggedLogin is done in GTCLoggedLogin_Created.

    now I try again with the new option mentioned above. . .:)

    regards

    Oliver

    Thursday, September 19, 2013 4:12 AM