Creating an object in VB.NET behaves differently on different SQL servers - vb.net

I have following code which is behaving differently on different servers. In the below method if i write this line of code:
Dim customerPositionsFromPaid = vwCustomerPositionInPaid.SelectAll().Where(conditions).Select(Function(o) New CustomerPositionFromPaidDto(o.FundingYearId.Value, o.DsoId.Value, o.CustomerId.Value, o.CustomerPosition.Value)).ToList()
it returns result on one sql instance but does not return result on other sql instance.
However if i replace the above line with the following, it returns result on both sql instances.
Dim customerPositionsFromPaid = vwCustomerPositionInPaid.
SelectAll().
Where(conditions).
Select(Function(o) New CustomerPositionFromPaidDto() With {.FundingYearId = o.FundingYearId.Value, .DsoId = o.DsoId.Value, .CustomerId = o.CustomerId.Value, .CustomerPosition = o.CustomerPosition.Value}).
ToList()
Could it be because sql server instances have different settings or it's something to do with the code itself?
--Function
Private Shared Function GetCustomerPositionsFromPaid(ByVal customerID As Integer, ByVal fundingYearID As Integer) As IEnumerable(Of CustomerPositionFromPaidDto)
Dim conditions = PredicateBuilder.True(Of vwCustomerPositionInPaid)()
conditions = conditions.And(Function(o) o.CustomerId.Equals(customerID))
conditions = conditions.And(Function(o) o.FundingYearId.Equals(fundingYearID))
conditions = conditions.And(Function(o) o.DsoId.HasValue)
'Dim customerPositionsFromPaid = vwCustomerPositionInPaid.SelectAll().Where(conditions).Select(Function(o) New CustomerPositionFromPaidDto(o.FundingYearId.Value, o.DsoId.Value, o.CustomerId.Value, o.CustomerPosition.Value)).ToList()
'Dim customerPositionsFromPaid = vwCustomerPositionInPaid.SelectAll().Where(conditions).Select(Function(o) New With {.FundingYearId = o.FundingYearId.Value, .DsoId = o.DsoId.Value, .CustomerId = o.CustomerId.Value, .CustomerPosition = o.CustomerPosition.Value}).ToList().Select(Function(o) New CustomerPositionFromPaidDto(o.FundingYearId, o.DsoId, o.CustomerId, o.CustomerPosition)).ToList()
Dim customerPositionsFromPaid = vwCustomerPositionInPaid.
SelectAll().
Where(conditions).
Select(Function(o) New CustomerPositionFromPaidDto() With {.FundingYearId = o.FundingYearId.Value, .DsoId = o.DsoId.Value, .CustomerId = o.CustomerId.Value, .CustomerPosition = o.CustomerPosition.Value}).
ToList()
Return customerPositionsFromPaid
End Function
--Select All
Public Shared Function [SelectAll](ByVal conditions As Expression(Of Func(Of T, Boolean))) As IEnumerable(Of T)
Return [SelectAll]().Where(conditions)
End Function
Public Shared Function [SelectAll]() As IQueryable(Of T)
Return Table
End Function
Private Shared ReadOnly Property Table() As Table(Of T)
Get
Return Context.GetTable(Of T)()
End Get
End Property

I manage to solve the above by writing the following code. Looks like because customerid and fundingyearid are nullable objects, i had to use .Value attribute but still not sure why the previous code will work on one server and not on the other one.
Private Shared Function GetCustomerPositionsFromPaid(ByVal customerID As Integer, ByVal fundingYearID As Integer) As IEnumerable(Of CustomerPositionFromPaidDto)
Dim conditions = PredicateBuilder.True(Of vwCustomerPositionInPaid)()
conditions = conditions.And(Function(o) o.CustomerId.Equals(customerID.Value))
conditions = conditions.And(Function(o) o.FundingYearId.Equals(fundingYearID.Value))
conditions = conditions.And(Function(o) o.DsoId.HasValue)
Dim customerPositionsFromPaid = vwCustomerPositionInPaid.
SelectAll().
Where(conditions).
Select(Function(o) New CustomerPositionFromPaidDto() With {.FundingYearId = o.FundingYearId.Value, .DsoId = o.DsoId.Value, .CustomerId = o.CustomerId.Value, .CustomerPosition = o.CustomerPosition.Value}).
ToList()
Return customerPositionsFromPaid
End Function

Related

Custom function(s) in LINQ to Entities? How to write acceptable code?

Use of my simple function causes app to exit all the nested Using blocks and returns control to very outer End Using statement. But built-in function works fine. How to bypass this strange situation?
Public Shared ReadOnly GlobalSettingsKeyList As New HashSet(Of String)
Public Shared Function IsGlobalSetting(key As String) As Boolean
Return GlobalSettingsKeyList.Contains(key)
End Function
What doesn't work:
Using db = powerEntities.Open()
dim userID = 1
dim dbSettingsFound = (From setting In db.SETTINGS
Where setting.idUsers = If(IsGlobalSetting(setting.Name), Nothing, userID)
Where setting.Name.Contains(keyToMatch)) _
.ToDictionary(Function(x) x.Name, Function(y) y.Value)
End Using
What works fine:
Using db = powerEntities.Open()
dim userID = 1
dim dbSettingsFound = (From setting In db.SETTINGS
Where setting.idUsers = If(GlobalSettingsKeyList.Contains(setting.Name), Nothing, userID)
Where setting.Name.Contains(keyToMatch)) _
.ToDictionary(Function(x) x.Name, Function(y) y.Value)
End Using
{"LINQ to Entities does not recognize the method 'Boolean IsGlobalSetting(System.String)' method, and this method cannot be translated into a store expression."}
Done! Thanks to Jarekczek's answer here and his LinqExprHelper
So there is a way!
Private Shared Function GetDefaultKey(key As String) As String
If key.Contains("Station") Then
Return $"default{key.Substring("Station")}" 'my String Extension
Else
Return $"default{key}"
End If
End Function
Public Shared Function GetDefaultKeyAndCompareSetting(ByVal key As String) As Expression(Of Func(Of Settings, Boolean))
key = GetDefaultKey(key)
Return LinqExprHelper.NewExpr(Function(u As Settings) u.Name.Equals(key))
End Function
used like this...
Shared Sub Example(key As String)
...
Dim masterExpr = LinqExprHelper.NewExpr(Function(u As Settings, ByVal formatCompare As String) (formatCompare))
Dim isSameAsDefKey = masterExpr.ReplacePar("formatCompare", GetDefaultKeyAndCompareSetting(key).Body)
Dim result = (From def In db.Settings
Where def.idUsers Is Nothing).
Where(CType(isSameAsDefKey, Expression(Of Func(Of Settings, Boolean)))).FirstOrDefault
...
End Sub
...works like a charm

List of IEnumerables

Please see the code below, which was written by someone else and works very well:
Public Function GetMembers(Optional ByVal sortExpression As String = "MemberId ASC") As List(Of Member) Implements IMemberDao.GetMembers
Dim sql As String =
" SELECT MemberId, Email, CompanyName, City, Country" &
" FROM [Member] ".OrderBy(sortExpression)
Return db.Read(sql, Make).ToList()
End Function
Public Iterator Function Read(Of T)(ByVal sql As String, ByVal make As Func(Of IDataReader, T), ParamArray ByVal parms() As Object) As IEnumerable(Of T)
Using connection = CreateConnection()
Using command = CreateCommand(sql, connection, parms)
Using reader = command.ExecuteReader()
Do While reader.Read()
Yield make(reader)
Loop
End Using
End Using
End Using
End Function
Private Shared Make As Func(Of IDataReader, Member) =
Function(reader) _
New Member() With {
.MemberId = Extensions.AsId(reader("MemberId")),
.Email = Extensions.AsString(reader("Email")),
.CompanyName = Extensions.AsString(reader("CompanyName")),
.City = Extensions.AsString(reader("City")),
.Country = Extensions.AsString(reader("Country"))
}
I understand that Make is a delegate that populates the Member objects with values, but I do not understand how a list of Persons is returned by the Read function? (a list is returned and works very well).
it does this by the yield keyword. This is generally how it works when you are iterating over a collection. Take a look here:
http://msdn.microsoft.com/en-us/library/vstudio/hh156729.aspx
This should give you a good/simple understanding.

Linq return result as list

Hi I am stuck with return the linq result as list. I try to convert but failed to return as the list. Below is my code. Please help. Thanks
Public Function GetConfigList(ByVal aConfig As TT_GENERAL_CONFIGURATION) As List(Of Config)
Dim Data = From p In Db.TT_GENERAL_CONFIGURATION _
Select p
If Data IsNot Nothing Then
ConvertGeneralConfig(Data)
Else
Return Nothing
End If
End Function
Private Function ConvertGeneralConfig(ByVal aConfig As TT_GENERAL_CONFIGURATION) As List(Of Config)
Dim pConfig As New Config
pConfig.ConfigID = aConfig.INTERNAL_NUM
pConfig.ConfigType = aConfig.CONFIG_TYPE
pConfig.ConfigName = aConfig.CONFIG_NAME
pConfig.ConfigValue = aConfig.CONFIG_VALUE
Return pConfig
End Function
Seems like you might want to use
If Data IsNot Nothing Then
Return ConvertGeneralConfig(Data)
Else
Return Nothing
End If
If you only expect one result - then use First() or a FirstOrDefault()
Dim Data = (From p In Db.TT_GENERAL_CONFIGURATION _
Select p)
.FirstOrDefault();
your Data now only contains the first element of the result. If none was found Data is nothing.
UPDATE
If you want your function to return a list then you have to create a list, and return it:
Private Function ConvertGeneralConfig(ByVal aConfig As TT_GENERAL_CONFIGURATION) As List(Of Config)
Dim pConfig As New Config
pConfig.ConfigID = aConfig.INTERNAL_NUM
pConfig.ConfigType = aConfig.CONFIG_TYPE
pConfig.ConfigName = aConfig.CONFIG_NAME
pConfig.ConfigValue = aConfig.CONFIG_VALUE
Dim lst As New List(Of Config) 'Creates a list
lst.Add(pConfig) ' add the object to the list
Return lst ' returns the list
End Function

Getting an invalid cast exception when trying to order a list of objects with linq

I'm trying to sort a list of tweets (class: SimpleTweet), which each have ID associated with them (x.ID where x is an object of class SimpleTweet). I'm using linq to sort this, using "OrderByDescending", but am getting an error on the line where I set a new object of type List(Of SimpleTweet) equal to the sorted list. The error I am getting is, "System.InvalidCastException: Unable to cast object of type 'System.Linq.OrderedEnumerable2[SimpleTweet,System.Int64]' to type 'System.Collections.Generic.List1[SimpleTweet]'".
The code:
<WebMethod()> _
Public Function GetTweetsByUserID(ByVal userID As Integer) As List(Of SimpleTweet)
Dim result As New List(Of SimpleTweet)
Dim urlTwitter As String = "https://api.twitter.com/1/statuses/user_timeline.xml?include_entities=true&include_rts=true&screen_name={0}&count=3"
'Dim twitterfeed As String = utils.GetUserTwitterFeeds(userID, "docphin")
Dim lq As New lqDFDataContext
Dim var = lq.web_GetTweetsByUserID(userID).ToList()
Dim sortedresult As New List(Of SimpleTweet)
If Not var Is Nothing Then
For Each twitterfeed In var
Dim listURL As String = String.Format(urlTwitter, twitterFeed.TweeterFeed)
Dim tweetXML As XmlDocument = utils.GetXMLForURL(listURL)
Dim tweetnodelist As XmlNodeList = tweetXML.ChildNodes(1).ChildNodes
For Each node As XmlNode In tweetnodelist
Dim tweet As New SimpleTweet
tweet.CreatedAt = node.SelectSingleNode("created_at").InnerText
tweet.HTMLText = utils.ReturnTextWithHRefLink(node.SelectSingleNode("text").InnerText)
tweet.ID = node.SelectSingleNode("id").InnerText
tweet.Name = node.SelectSingleNode("user/name").InnerText
tweet.ScreenName = node.SelectSingleNode("user/screen_name").InnerText
tweet.Text = node.SelectSingleNode("text").InnerText
tweet.UserID = node.SelectSingleNode("user/id").InnerText
tweet.ProfileImageURL = node.SelectSingleNode("user/profile_image_url_https").InnerText
result.Add(tweet)
Next
Next
sortedresult = result.OrderByDescending(Function(tweet) tweet.ID)
End If
Return sortedresult
End Function
You need to materialize the result with a call to .ToList(). Add it to the end of this line:
sortedresult = result.OrderByDescending(Function(tweet) tweet.ID)
sortedResult is of type List(Of SimpleTweet) and OrderByDescending returns an IOrderedEnumerable(Of SimpleTweet) that cannot automatically be cast to the expected type.
Since you want to return a List(Of SimpleTweet) you need to call ToList to create a new list from the IEnumerable(Of SimpleTweet):
Return sortedresult.ToList()
ToList forces an immediate query evaluation.

Searching objects in a list

I have a list of objects, and I want to search it to see if myobject.articleID matches a given articleID. From what I've gather using .Find(Of T) is the best way to go about this, however I am having some difficulty implementing it. Here's some code I have so far:
<WebMethod()> _
Public Function SetTagOnFavorite(ByVal articleID As Integer, ByVal tagtext As String, ByVal mobileGUID As String) As AddTagResult
Dim result As New AddTagResult
Dim userID As Long = GetUserIDByMobileGUID(mobileGUID)
If userID > 0 Then
Dim pageNum As Integer = 1
Dim pageLen As Integer = 500 'arbitrarily large number
Dim savedArticleList As New List(Of SimpleArticle)
savedArticleList = GetSavedArticles(mobileGUID, pageNum, pageLen)
If savedArticleList.Find(Function( m As SimpleArticle) m.articleID = articleID)
Dim lq As New lqDFDataContext
Dim var = lq.web_AddTagToArticle(userID, articleID, tagtext).ToList()
If var.Any() Then
Dim vRes = var.First()
result.articletagID = vRes.articletagID
result.newarticletag = vRes.newarticletag
result.newusertag = vRes.newusertag
result.usertagID = vRes.usertagID
result.resultinfo = "Success."
End If
End If
Else
result.resultinfo = STR_NoUserIDMostLikelyTheSessionTimedOut
End If
Return result
End Function
The error I get is, "value of type SimpleArticle cannot be converted to Boolean".
Because Find(Of returns the found object, you need to change this line:
If savedArticleList.Find(Function( m As SimpleArticle) m.articleID = articleID)
to
If savedArticleList.Find(Function( m As SimpleArticle) m.articleID = articleID) IsNot Nothing
or if you need the found item, store the result of Find in a local variable.
You could optimize #competent_tech's answer further as:
If savedArticleList.Any(Function(m) m.articleID = articleID))