Casting substrings with linq into a list of object and than sorting it base on property in vb.net - vb.net

This have to be in vb.net linq, i'm pretty sure I could do it in c#, but I cant find any good enough translator to help me ... even the answers I find here in SO seems to only be written in linq, hence the question which might be a duplicate of a c# one.
That being said, considering these 2 classes :
Public class User
Public Property Name() As String
Public Property Teams As TeamList
Public sub New(d as string, results as TeamList)
me.name = d
me.Teams = results
end sub
end class
Public Class TeamList
Public Property TeamName() As String
Public Property fullscore() As list(of object)
Public sub New(name as string, value as list(of string))
me.TeamName = name
me.fullscore = value
me.fullscore = getFullScore(value) (return a list of object)
end sub
End Class
I'm struggling in the final steps of my linq -to - object : (you can copy /paste this in linqpad)
Sub Main
dim Definition as new Dictionary(of String, object)
definition.add("user1_redTeam-02", new object)
definition.add("user1_redTeam-01", new object)
definition.add("user1_blueTeam-03", new object)
definition.add("user2_redTeam-01", new object)
definition.add("user1_redTeam-03", new object)
definition.add("user1_blueTeam-01",new object)
definition.add("user2_blueTeam-01", new object)
definition.add("user1_blueTeam-02", new object)
definition.add("user2_redTeam-02", new object)
Dim q3 = (From userlists In Definition.Keys.GroupBy(Function(s) s.Split("_")(0)) _
Select New With _
{.UserName = userlists.Key, _
.animationList = (From scList In userlists.GroupBy(Of String)(Function(s) s.Split("-")(0)) _
Select New With {.Team = scList.Key, _
.Score = scList.ToList()})})
q3.dump()
End Sub
this is the result :
now, all I want is to sort the .score attribute (just a simple .sort(), and instead of returning an anonymous q3 object, which I,m cluless to transform, I'd like the q3 to be a list(of User)
it think it should looks like this ... but I cant make it works, i always gets some linq conversion errors :
Unable to cast object of type 'WhereSelectEnumerableIterator2[System.Linq.IGrouping2[System.String,System.String],UserQuery+User]' to type 'System.Collections.Generic.List`1[UserQuery+User]'.
Dim q3 as List(of User)= (From userlists In Definition.Keys.GroupBy(Function(s) s.Split("_")(0)) _
Select New User(userlists.Key, (From scList In userlists.GroupBy(Of String)(Function(s) s.Split("-")(0)) _
Select New TeamList(scList.Key, scList.ToList()))))

Your code examples seem to be incorrect - for example, it seems like User.Teams should be a list of some type, not a TeamList object, which isn't really a list. Anyway, with a little modification, this is what I came up with - maybe it's close to what you were looking for (a list of users with the scores sorted). You can paste into LINQPad to run it.
Sub Main
Dim Definition As New Dictionary(of String, Object)
definition.add("user1_redTeam-02", New Object)
definition.add("user1_redTeam-01", New Object)
definition.add("user1_blueTeam-03", New Object)
definition.add("user2_redTeam-01", New Object)
definition.add("user1_redTeam-03", New Object)
definition.add("user1_blueTeam-01",New Object)
definition.add("user2_blueTeam-01", New Object)
definition.add("user1_blueTeam-02", New Object)
definition.add("user2_redTeam-02", New Object)
Dim q3 = (
From userlists In Definition.Keys.GroupBy(Function(s) s.Split("_"c)(0))
Select New User(
userlists.Key,
(From scList In userlists.GroupBy(Function(s) s.Split("-"c)(0))
Select New Team(scList.Key.Split("_"c)(1), scList.OrderBy(Function(s) s).ToList())).ToList()
)
).ToList()
q3.dump()
End Sub
' Define other methods and classes here
Public class User
Public Property Name() As String
Public Property Teams() As List(Of Team)
Public Sub New(d As String, results As List(Of Team))
Me.Name = d
Me.Teams = results
End Sub
End Class
Public Class Team
Public Property TeamName() As String
Public Property FullScore() As List(Of String)
Public Sub New(name As String, value As List(Of String))
Me.TeamName = name
Me.FullScore = value
End Sub
End Class

Related

How to access object in multidimensional array in Visual Basic

In Visual Basic, I am using a List to store an array of objects. However, I haven't figured out how to access a particular object once I have added it to my list.
I am using Microsoft Visual Studio
Private Results As New List(Of Object)
Dim Results As Object()
Dim CaseStatus as String = "Closed"
...
Results.Add(New Object() {CaseStatus, FlagsStr, OBTotal, OBPaid})
MessageBox.Show(Result(0).ToString)
Displays: System.Object[]
I have also tried MessageBox.Show(Results(0,0).ToString), but don't get the expected results.
When you can .ToString on an object you get the fully qualified name of the object unless the class overrides .ToString. Creating a class and a List (Of T) gives you easy access to any of the properties of the class.
Public Class ProjectCase
Public Property CaseStatus As String
Public Property FlagsString As String
Public Property OBTotal As Decimal
Public Property OBPaid As Decimal
Public Sub New()
'include a default constructor
End Sub
Public Sub New(cs As String, fs As String, total As Decimal, paid As Decimal)
CaseStatus = cs
FlagsString = fs
OBTotal = total
OBPaid = paid
End Sub
Public Overrides Function ToString() As String
Return $"{CaseStatus}, {FlagsString}, Total = {OBTotal}, Paid = {OBPaid}"
End Function
End Class
Private Results As New List(Of ProjectCase)
Private Sub OPCode()
Results.Add(New ProjectCase("Closed", "Some string", 74.36D, 22D))
MessageBox.Show(Results(0).ToString)
MessageBox.Show(Results(0).CaseStatus) 'or any property of your class
End Sub

Create Custom Class Dynamically

I am working on a project where I need to create a multitude of custom classes to interact properly with an API (While I know there might be questions on why, and such, but the short is it has to be this way).
Is there a way to create a complete custom class dynamically on the fly? So instead of
class person
Private _Height
Property Height As Integer
Get
Return _Height
End Get
Set(value As Integer)
_Height = value
End Set
End Property
'Continue for all properties of person
I would like to be able to create a new object and through other input create this dynamically.
dim NewClass as object
dim NewProperty as property
NewProperty.name="Height"
NewProperty.datatype=string
NewClass.AddProperty(NewProperty)
Is this possible? It would save me a lot of time if it is.
I don't like late binding but there are options (I like my option strict on). Like using the DynamicObject or the ExpandoObject class. Your question is vague so I have no idea if it can work.
Sub Main()
Dim test As Object = New SampleDynamicClass()
test.SomeProperty = "123"
Console.WriteLine(test.SomeProperty)
Console.ReadLine()
End Sub
Public Class SampleDynamicClass
Inherits DynamicObject
Private _values As New Dictionary(Of String, String)
Public Sub New()
End Sub
Public Function GetPropertyValue(ByVal propertyName As String) As String
Return _values(propertyName)
End Function
Public Function SetPropertyValue(ByVal propertyName As String, ByVal value As Object) As Boolean
If _values.ContainsKey(propertyName) Then
_values(propertyName) = value.ToString()
Else
_values.Add(propertyName, value.ToString())
End If
Return True
End Function
Public Overrides Function TryGetMember(ByVal binder As GetMemberBinder,
ByRef result As Object) As Boolean
result = GetPropertyValue(binder.Name)
Return If(result Is Nothing, False, True)
End Function
Public Overrides Function TryInvokeMember(ByVal binder As InvokeMemberBinder,
ByVal args() As Object,
ByRef result As Object) As Boolean
result = GetPropertyValue(binder.Name)
Return If(result Is Nothing, False, True)
End Function
Public Overrides Function TrySetMember(binder As SetMemberBinder, value As Object) As Boolean
Return SetPropertyValue(binder.Name, value)
End Function
Dim person = New With {Key .Height = 12}
Dim personTypes = New With {Key .Happy = 1, .Sad = 2}
Dim personsAndTypes = New With {Key .Person = person, .Type = personTypes}
The question is kind of vague, but if you have no need for other fields and methods, or reuse Anonymous Types

Bind a detail report to a class model with properties stored in a Dictionary (VB.NET, Devexpress)

I'm trying the example from Devexpress
Dim binding As New XRBinding("Text", dsProducts1, "Products.UnitPrice")
But my models does not have their properties explicitly written in their class. It would take a method GetProperty("column_name_here") to get it's data. I'm wondering if the 3rd parameter of XRBinding can be a method? Like:
Dim binding As New XRBinding("Text", dsProducts1, product.GetProperty("name"))
Additional Info:
All of my model classes extends this Dao class which is responsible in getting data in the database. The Dao class have a protected variable as a Dictionary(Of String, Object) to store the values (key = column name, value = column row value) from the database.
Now when I want to get something in the database, I only call
Dim user As New User // this class extends the Dao class
Dim userId = user.GetProperty("id") // Method to get the value from Dictionary, first parameter is the Dictionary key or column name from the DB
I made this so that I wont have to create every model class and set the properties of that class, as it is kinda cumbersome.
It seems that there are no way to bind to some method. I suggest you to take a look at ExpandoObject dynamic class. The members of this class can be added at runtime. This class implements IDictionary(Of String, Object) interface which you can use to generate properties from your Dictionary(Of String, Object).
Here is example:
Example of base Dao class implementation with protected Dictionary(Of String, Object) property:
Public Class Dao
Private _values As Dictionary(Of String, Object)
Public Sub New()
_values = New Dictionary(Of String, Object)
End Sub
Public Overridable Sub Fill(index As Integer)
_values.Clear()
_values.Add("ID", index)
_values.Add("Product", "Banana " & index)
_values.Add("Price", 123.45 + index)
End Sub
Protected ReadOnly Property Values As Dictionary(Of String, Object)
Get
Return _values
End Get
End Property
End Class
Example of Dao class descendant with DynamicValues property which returns ExpandoObject based on Dictionary(Of String, Object) (you must omit the type of property):
Public Class DynamicDao
Inherits Dao
Private _dynamicValues As ExpandoObject
Public Overrides Sub Fill(index As Integer)
MyBase.Fill(index)
_dynamicValues = New ExpandoObject()
Dim keyValues = DirectCast(_dynamicValues, IDictionary(Of String, Object))
For Each pair In Values
keyValues.Add(New KeyValuePair(Of String, Object)(pair.Key, pair.Value))
Next
End Sub
Public ReadOnly Property DynamicValues ' <= There is no type. In hint is displayed «As Object».
Get
Return _dynamicValues
End Get
End Property
End Class
Usage of DynamicDao class in XtraReport:
Dim list = New List(Of DynamicDao)
For index% = 0 To 9
Dim dao = New DynamicDao()
dao.Fill(index%)
list.Add(dao)
Next
Dim labelID = New XRLabel()
labelID.DataBindings.Add(New XRBinding("Text", Nothing, "DynamicValues.ID"))
Dim labelProduct = New XRLabel()
labelProduct.DataBindings.Add(New XRBinding("Text", Nothing, "DynamicValues.Product"))
labelProduct.LeftF = 50
Dim labelPrice = New XRLabel()
labelPrice.DataBindings.Add(New XRBinding("Text", Nothing, "DynamicValues.Price"))
labelPrice.LeftF = 150
Dim detail = New DetailBand()
detail.Controls.Add(labelID)
detail.Controls.Add(labelProduct)
detail.Controls.Add(labelPrice)
Dim report = New XtraReport()
report.Bands.Add(detail)
report.DataSource = list
report.ShowRibbonPreview()

Duplicate Settings In Reference DLL

I have a DLL with several properties and a function that generates runs a SSRS report in the background and saves it to a PDF file.
I have a DataTable with all the reports that need to be generated and where they need to be saved.
I want to make each instance of the DLL run in a separate thread. I took a stab at it found the 2nd row in the DataTable overrode the first row.
Here is the Class/DLL Code
Public Class SSRSFunctions
Private Shared _Formated_Parameters As String
Private Shared _Report_Parameters As Dictionary(Of String, String)
Public Property FORMATED_PARAMETERS() As String
Get
Return _Formated_Parameters
End Get
Set(ByVal value As String)
_Formated_Parameters = value
End Set
End Property
Public Sub New()
_Report_Parameters = New Dictionary(Of String, String)
End Sub
Public Function RenderReportToFile() As String
'RenderReportHere
End Function
Public Sub AddParameter(ByVal Name As String, ByVal Value As String)
If _Report_Parameters.ContainsKey(Name) Then
_Report_Parameters.Remove(Name)
_Report_Parameters.Add(Name, Value)
Else
_Report_Parameters.Add(Name, Value)
End If
End Sub
End Class
Here is the calling Code
Private Sub CheckForNewRequests()
'Filter DataTable for Reports to Run
For Each dr As DataRow in DateTable.Rows
Dim rpt As New SSRSFunctions
Dim t1 As New Threading.Thread(AddressOf StartNewThread)
rpt.FORMATED_PARAMETERS = (dr("REPORT_PARAMS"))
t1.Start(rpt)
Next
End Sub
Private Function StartNewThread(ByVal report As SSRSFunctions) As String
Return report.RenderReportToFile()
End Function
I am trying to figure out why the "Dim rpt As New SSRSFunctions" is not creating a new instance of the DLL and so the second row of the dataTable has a new instance to store it's parameters.
The second row is overriding the first.
Help?
Thanks
jlimited
Dont make the private properties shared, remove the Shared keyword from the declarations.
change
Private Shared _Formated_Parameters As String
Private Shared _Report_Parameters As Dictionary(Of String, String)
to
Private _Formated_Parameters As String
Private _Report_Parameters As Dictionary(Of String, String)
By sharing them you are saying that no matter how many instances of the class is created always use (share) the same instance of the shared internal variable.

Data Access Layer returns DataTable

Please have a look at the following question, which i asked some time ago: Breaking BLL (Business Logic Layer) to BLL and DAL (Data Access Layer)
This approach (Data Transfer Object) seems to work well if I am returning one record from the data access layer i.e. getNameByID returns one record.
What happens if you have a Data Access Layer function called getName(), which returns many records e.g. thousands or millions to be processed in the Business Logic Layer? (it is a scheduled task). When this is required I am currently returning a DataTable (because data readers cannot outlive a connection in VB.NET 2008). However, this question and answer seems to negate this approach: Is returning DataTable or DataSet from DAL is wrong approach. Is this a poor approach?
I realise there are ORM tools like NHibernate, which I plan to use more for future projects. However, the data access code in my current project is already written by someone else but I want to refactor it as I go along.
Update
Here is some code (as suggested by Stephen Doggart):
Imports Microsoft.VisualBasic
Public Class PersonBLL
Private Name As String
Private Age As Integer
Dim objPersonDAL As New PersonDAL
Dim personList As List(Of Person)
'Option 2
Public Function getPersonByID() As List(Of Person)
personList = objPersonDAL.getPersonByID()
Return personList
End Function
Public Function ShowMessageBox(ByVal listPersonBLL As List(Of Person))
For Each p As Person In listPersonBLL
Me.Age = p.Age
Me.Name = p.Name
MsgBox(Me.Age)
MsgBox(Me.Name)
Next
End Function
End Class
Public Class PersonDAL
Private Name As String
Private Age As Integer
Public Function getPersonByID() As List(Of Person)
'Connect to database and get Person. Return a person object
Dim personList As List(Of Person) = New List(Of Person)
Dim p1 As New Person
p1.Name = "Ian"
p1.Age = 30
personList.Add(p1)
Dim p2 As New Person
p2.Name = "Steven"
p2.Age = 28
personList.Add(p2)
Dim p3 As New Person
p3.Name = "Sharon"
p3.Age = 29
personList.Add(p3)
Return (personList)
End Function
End Class
Public Class Person
Private _Name As String
Private _Age As Integer
Public Property Name() As String
Get
Return _Name
End Get
Set(ByVal value As String)
_Name = value
End Set
End Property
Public Property Age() As Integer
Get
Return _Age
End Get
Set(ByVal value As Integer)
_Age = value
End Set
End Property
End Class
Public Class Form1
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'If Environment.GetCommandLineArgs(0) = "Test" Then
'MsgBox("Test")
'End If
Dim p1 As PersonBLL = New PersonBLL
Dim p2 As List(Of Person) = p1.getPersonByID()
Dim p3 As PersonBLL = New PersonBLL
p3.ShowMessageBox(p2)
End Sub
End Class
Returning a DataTable isn't completely terrible--there's certainly worse ways of doing it--it's only partly terrible. But, who wants to eat partly terrible food unless they have no other option?
So, unless there's some reason why you need to use a DataTable, I would recommend sticking with custom DTO classes and just have your DAL return a list of those objects. For instance:
Public Function GetNames() As List(Of NameDto)
'...
End Function