vb.net LINQ select Distinct to a List - c#

I have a datatable with a column that has some duplicate values, I want to add those values to a listbox but without duplicates
I tried the following
Dim a = From row In table.AsEnumerable.Distinct.ToList Select row.Field(Of String)("name")
but it gives me duplicate values, How can it be done without duplicates?

I believe there are some more column(s) which are unique in each row that's why the distinct doesn't return the result as expected. Instead you should need to select the columns first than apply the distinct to it.
So try this instead :
Dim a = (From row In table.AsEnumerable()
Select row.Field(Of String)("name")).Distinct().ToList()
Hope this will help !!

You can pass an IEqualityComparer to the distinct function. See this answer Distinct() with lambda?

I had the same problem. I found that on anonymous type distinct works. So I first do the distinct and then copy into a list.
Dim _ret = New List(Of Marcas)()
For Each m In lista.Select(Function(s) New With {Key .id = s.BrandNo, .nombre = s.BrandName}).Distinct()
_ret.Add(New Marcas With {.id = m.id, .nombre = m.nombre})
Next

Related

LIKE query on DataTable using LINQ

Ive just started learning Linq. Ive just created a sample test like this.
Dim dt As New DataTable
Dim dc As New DataColumn
dc.ColumnName = "Test"
dt.Columns.Add(dc)
dt.Rows.Add("Test")
dt.Rows.Add("One test")
dt.Rows.Add("Second test")
Dim results = From myRow In dt.AsEnumerable
Where myRow("Test") = "Test"
Select myRow
For Each Row In results
Console.WriteLine(Row.Item(0).ToString())
Next
This returns the first row in the iteration.
But what if i want to use a LIKE operator using %? I cant get it to work.
Ive tried
Where myRow("Test") LIKE "Test%"
Sounds to me like you want to use StartsWith i.e.
Dim results = From myRow In dt.AsEnumerable
Where myRow("Test").StartsWith("Test")
Select myRow
Contains will match anywhere in the string where as StartsWith will only match if it's at the beginning of the string (same logic as Test%).
You migh be looking for contains.
Take a look at this:
var query = from mem in context.Member
where mem.LastName.Contains("xxx")
orderby mem.LastName, mem.FirstName
select new
{
FirstName = mem.FirstName,
LastName = mem.LastName,
};
You can also use .StartsWith() or .EndsWith().
You can use the contains method:
Dim results = From myRow In dt.AsEnumerable
Where myRow("Test").Contains("Test")
Select myRow

C# DataTable Linq select distinct values where column equals 'x'

I have a Datatable (Groups) designed like so
ColumnA|ColumnB
X|Apple
Y|Purple
X|Apple
X|Mango
I basically want to select from columna where it's X and get the disinct from ColumnB
This is what I have
var names = (from DataRow dr in Groups.Rows
orderby (string)dr["ColumnB"]
select (string)dr["ColumnB"]).Distinct();
This will give me distinct but it gives me Purple, and i dont want purple.
Thanks!
var names = (from DataRow dr in Groups.Rows
where dr["ColumnA"] == "X"
orderby (string)dr["ColumnB"]
select (string)dr["ColumnB"]).Distinct();
DataTable dt2 = dt1.Select("ColumnA = 'X'").CopyToDataTable().DefaultView.ToTable(true, "ColumnB");
So here we are selecting only the rows of data that you want, only rows where columnA is X. Then we choose only to see columnB, but with unique values only. Doing it in this order, you'll receive another datatable to play with. It'll only contain 1 column, columnB, and it'll only have unique/distinct values.
Enjoy.
If your return has more than one value and you want to Distinct the whole set by just one of the values you should use a custom IEqualityComparer.
var names = (from DataRow dr in Groups.Rows
where (string)dr["ColumnA"] == "X"
orderby (string)dr["ColumnB"]
select new {
ColumnA = (string)dr["ColumnA"],
ColumnB = (string)dr["ColumnB"]
}).Distinct(new MyCustomEqualityComparer());
edit: to include where clause
edit2: changed to custom IEqualityComparer

DataGridView binding to two tables

I have two tables. Most of the data is coming from the first table but there is a second table which has a column which I want to present in my UI
Here is my SQL Query
String sqlQuery = "SELECT u.CallerName, t.* FROM users u INNER JOIN tickets t ON u.id = t.user WHERE u.CallerName = 'tim.smith'";
I am using WinForms
If your query result is DataTable, then you can use Merge function to merge two table.
DataTable table1 = GetTable1Data(...);
DataTable table2 = GetTable2Data(...);
table1.Merge(table2, true);
Or if your query result is List, then you can use same approach as in DataTable case, using AddRange function:
List<YourClassType> list1 = GetList1Data(...);
List<YourClassType> list2 = GetList2Data(...);
list1.AddRange(list2, true);
It looks like you are doing just fine.
When binding with the DataGridView you can use:
Eval("CallerName")
to access the other column, but that column should work like all of the others.

How to select a field with linq on datarow

I have this linq query :
string title = from DataRow r in (OleDB.DataItems.Tables[0]).Rows
select r.Title;
and I'd like to extract the field Title (from Database) on the row (rows will be 1, not more, so that's I put on a string and not in a string[].
How can I do it?
VStudio says that DataRow doesnt contain the definition of Title, but the field Title exist on the database.
I making confusion :)
As Frédéric Hamidi said, you don't need LINQ.
However, if you still want to do it that way (overkill) and you know that there is always a single table with a single row, do:
DataSet data = new DataSet();
var table = (from a in data.Tables.Cast<DataTable>() select a).Single();
var row = (from a in table.Rows.Cast<DataRow>() select a).Single();
String title = row.Field<String>("Title");
or
DataSet data = new DataSet();
var table = (from a in data.Tables.Cast<DataTable>() select a).SingleOrDefault();
var row = (from a in table.Rows.Cast<DataRow>() select a).SingleOrDefault();
String title = row.Field<String>("Title");
I used a DataSet because I don't know how your object is structured.
You don't need LINQ since you only want to fetch the Title field of the first row in the collection:
string title = OleDB.DataItems.Tables[0].Rows[0]["Title"];
try
string title = (from DataRow r in (OleDB.DataItems.Tables[0]).Rows
select r.Title).First();
Linq returns an enumerable collection as it doesn't know there will be only one item. Calling the First method will return the first item from the query.
Edit: Hang on, I have blatantly missed the problem you originally mentioned (but you'll still need the above)!
A data row contains fields, not properties as such. What you'll need to do is
select r.Field<string>("Title")
So your entire query will be
string title = (from DataRow r in (OleDB.DataItems.Tables[0]).Rows
select r.Field<string>("Title")).First();
It's better to use FirstOrDefault, in case there are no rows:
string title = (from DataRow r in (OleDB.DataItems.Tables[0]).Rows
select r.Title).FirstOrDefault();
Usually, if you need to perform such an action, you would cast the DataRow object to your strongly typed object corresponding with the table in your database.
I assume there is a class "Book" which contains the field "Title":
Book selectedBook = (Book) from DataRow r in (OleDB.DataItems.Tables[0]).Rows[0]
string sTitle = selectedBook.Title;
Hope this helps.

Sorting DataTable string column, but with null/empty at the bottom

I need to sort a DataTable or DataGridView by a column that is a string value, but with null/empty values at the BOTTOM when sorting ASCENDING.
The DataTable is NOT populated by a SQL statement, so no order by.
If I do
DataGridView1.Sort(New RowComparer(System.ComponentModel.ListSortDirection.Ascending))
then it throws an exception, saying that the DataGridView is DataBound, which is correct, but doesn't help me, and I want to keep it databound.
It's .NET 2.0, which means no LINQ available!
in some cases you could do this if you have another extra column in your table:
SELECT completed, completed IS NULL AS isnull
FROM TABLE
ORDER BY isnull DESC, completed DESC
Edit:
Like this in VB.NET
For Each srSearchResult In srcSearchResultCollection
Try
dr = dt.NewRow()
dr("cn") = srSearchResult.GetDirectoryEntry().Properties("cn").Value
dr("Account") = srSearchResult.GetDirectoryEntry().Properties("sAMAccountName").Value
dr("Nachname") = srSearchResult.GetDirectoryEntry().Properties("sn").Value
dr("Vorname") = srSearchResult.GetDirectoryEntry().Properties("givenname").Value
dr("Mail") = srSearchResult.GetDirectoryEntry().Properties("mail").Value
dr("HomeDirectory") = srSearchResult.GetDirectoryEntry().Properties("homedirectory").Value
dr("LogonScript") = srSearchResult.GetDirectoryEntry().Properties("scriptPath").Value
dr("IsNull") = String.IsNullOrEmpty(dr("Nachname").ToString())
dt.Rows.Add(dr)
Catch ex As Exception
End Try
Next srSearchResult
dt.DefaultView.Sort = "IsNull ASC, Nachname ASC"
Davide Piras has a good solution, however there is another simplest solution I have
Add a new column and do it in just one line
// just, add a new column
ActualDataTable.Columns.Add("NullEmptyCheck", typeof(int), "ColumnNameToSort is Null OR ColumnNameToSort = ''");
// apply sort expression
ActualDataTable.DefaultView.Sort = "NullEmptyCheck asc, ColumnNameToSort asc";
// pass datasource to grid
MyGridView.DataSource = ActualDataTable.DefaultView;
MyGridView.DataBind();
even if the DataTable you bind to the user interface control DataGridView is not populated via SQL, you can still sort it using a DataView, you can do something like this:
DataView myView = myDataTable.DefaultView;
myView,Sort = "yourColumnName ASC";
then you do your binding.
how does it work? Are the null values in the top or in the bottom?
For those who are looking for a way to achieve this in .NET 4+, here is a example :
DataTable orderedDataTable = sourceDataTable.AsEnumerable()
.OrderByDescending(row => !string.IsNullOrWhiteSpace(row.Field<string>("COLUMN_NAME")))
.ThenBy(row => row.Field<string>("COLUMN_NAME"))
.CopyToDataTable();
This will place null values at the end of the table (note that both empty and white spaces strings will have the same rank) and then order the requested column in ascending order.

Categories

Resources