LİNQ SQL Creating a New List Using Join VB.NET - vb.net

I'd like to get item_order and item_id from ITEM_DEF and from ITEM_SYT p4 colums. Also item_ids will be the same. And then sort it in a list order by Ascending.
So the new List will include 3 colums as item_id, item_order and p4.
EDIT: I just need to see how I should declare the List.
Here I have an example which performs well:
Dim ItemSytList As List(Of VLibrary.LINQ.ITEM_SYT) = New List(Of VLibrary.LINQ.ITEM_SYT)
ItemSytList = (From itemSyt As VLibrary.LINQ.ITEM_SYT In Context.ITEM_SYTs _
Join itemDef As VLibrary.LINQ.ITEM_DEF In Context.ITEM_DEFs On itemSyt.item_id Equals itemDef.item_id _
Where itemSyt.p1.ToUpper = "BDDK".ToUpper And itemSyt.p2.ToUpper = TableName.ToUpper _
And itemDef.template_id = TemplateId And If(itemDef.item_close_date.HasValue, itemDef.item_close_date, StartDate) >= StartDate _
And If(itemDef.item_open_date.HasValue, itemDef.item_open_date, EndDate) <= EndDate Select itemSyt).ToList
This code provides to keep ITEM_SYT's colums as it's children.

What you need to do is use an anonymous type. (Use implicit typing with LINQ whenever possible)
Dim ItemSytList =
From itemSyt As VLibrary.LINQ.ITEM_SYT In context.ITEM_SYTs
Join itemDef As VLibrary.LINQ.ITEM_DEF In context.ITEM_DEFs On itemSyt.item_id Equals itemDef.item_id
Where itemSyt.p1.ToUpper = "BDDK".ToUpper And itemSyt.p2.ToUpper = TableName.ToUpper _
And itemDef.template_id = TemplateId And If(itemDef.item_close_date.HasValue, itemDef.item_close_date, StartDate) >= StartDate _
And If(itemDef.item_open_date.HasValue, itemDef.item_open_date, EndDate) <= EndDate
Select New With {
.item_order = itemDef.item_order,
.item_id = itemDef.item_id,
.p4 = itemSyt.p4}
You can access the results like this
Dim firstP4 = ItemSytList.OrderBy(Function(i) i.item_order).First().p4

Related

Using Linq for select row from DataTableA where id not in DataTableB

I have two dataTables ,and i want select all rows from DataTable1 where id is not in DataTable2.below what i have tried :
Sql = "select *,N°Reçu as NumRecu from V_Sit_J_Vente,V_Bien where V_Sit_J_Vente.Code_bien=V_Bien.Code_bien and date_situation <= '" + dt2 + "' and date_situation >= '" + dt1 + "'"
Dim GlobalDataVente As DataTable = utilitaire.getDataSet(Sql).Tables(0)
Sql = "select * from V_Reserv_Annule"
Dim GlobalDataAnnule As DataTable = utilitaire.getDataSet(Sql).Tables(0)
Dim query = (From order In GlobalDataVente.AsEnumerable() _
Where order!code_projet = tab.Rows(i).Item("code_projet")).ToList
Dim bannedCCList = From c In GlobalDataAnnule.AsEnumerable() _
Where c!type.Equals("Transfert acompte") = False And c!date_annule <= dt2
Dim exceptBanned = From c In query Group Join b In bannedCCList On c.Field(Of String)("N°Reçu") Equals b.Field(Of String)("num_reserv_remplace")
Into j() From x In j.DefaultIfEmpty() Where x Is Nothing Select c
What i want that "exceptBanned " containt all rows of "query" except row exist in "bannedCCList "
Thanks in advance
You can use Contains for this:
Dim query = (From order In GlobalDataVente.AsEnumerable() _
Where order!code_projet = tab.Rows(i).Item("code_projet")).ToList
Dim bannedCCList = From c In GlobalDataAnnule.AsEnumerable() _
Where c.type.Equals("Transfert acompte") = False And c.date_annule <= dt2
Select c.Field(Of String)("num_reserv_remplace")
Dim exceptBanned = From c In query
Where Not bannedCCList.Contains(c.Field(Of String)("N°Reçu"))
Select c
bannedCCList defines a query that produces the Id values you want to exclude; exceptBanned combines query with this list of Ids into a query that only runs once to return the final results. It works this way because bannedCCList is an IEnumerable. It isn't executed when it's defined, only when it's actually used.

VB.Net Linq with datatables - select from one table what does not exist in the other

I have two data on which I have applied the linq to select some lines :
csql = "select * from V_Vente where code_projet=" & ComProjet.GetColumnValue("code_projet") & " "
Dim tabVnt as Datatable = utilitaire.getDatatable(csql)
Dim query1 = tabVnt.AsEnumerable().Where(Function(r) DirectCast(r("date"), Date) >= dtDu And DirectCast(r("date"), Date) <= dtAu)
Dim tabAnnule As DataTable = utilitaire.getDatatable("select * from V_Reserv_Annule")
Dim query2 = From cust In tabAnnule.AsEnumerable() Where (cust.type = "définitif" Or cust.type = "Transfert") And cust.date_annule <= dtAu
now what i want is to select rows from "query1" where "Num_R" not exist in "query2".
The column "Num_r" exist in both datatable "tabVnt" and "tabAnnule"
I've tried this code but he doesn't work,please help me to find the error :
dim rows = from t1 in query1 .AsEnumerable() join t2 in query2.AsEnumerable() on t1.Field(Of String)("Num_r") equals t2.Field(Of String)("Num_r") Into tg
From tcheck In tg.DefaultIfEmpty()
Where tcheck = null
Select t1()
If I have understood your code right, you can check if second table's Num_rs does not contain the table one Num_r:
Dim rows = t1.Where(x=> !t2.Select(y=> y.Num_r).Contains(x.Num_r));
I have find the solution for my issus ,and i'd like to share it here with you :
Dim csql = "select * from V_Vente where code_projet=" & ComProjet.GetColumnValue("code_projet") & " "
Dim tabVnt As DataTable = utilitaire.getDatatable(csql)
Dim query1 = tabVnt.AsEnumerable().Where(Function(r) DirectCast(r("date"), Date) >= dt1 And DirectCast(r("date"), Date) <= dt2).ToList
Dim tabAnnule As DataTable = utilitaire.getDatatable("select * from V_Reserv_Annule")
bannedCCList = From c In tabAnnule.AsEnumerable() _
Where (c!type.Equals("définitif") = True Or c!type.Equals("Transfert") = True) And c!date_annule <= dt2
Select c.Field(Of String)("num_recu")
Dim exceptData = (From c In query1.AsEnumerable() _
Where Not bannedCCList.Contains(c.Field(Of String)("num_recu")) _
).ToList

how to perform groupby in linq on DataTable inside vb code?

How do I perform group in LINQ inside vb code (dot.net v4.0) with DataTable and sum on the group?
In the sample below I need to add group by GroupName, ProductName and perform sum on QTY. The columns, order and where should remain as in sample, I just need to add the group and sum. The format should remain the same (getting row using e("FieldName")).
Dim ordersTable As DataTable = _dsProd.Tables("tblProductSummary")
Dim query =
(From e In ordersTable
Where (e("Type").ToString() = "1" Or IsDBNull(e("Type")))
Order By e("GroupSortOrder") Ascending, e("ProductName")
Select
GroupName = e("GroupName"),
ProductName = e("ProductName"),
QTY = e("QTY"),
Type= e("Type")
)
Dim query =
(From e In ordersTable
Where (e("Type").ToString() = "1" Or IsDBNull(e("Type")))
Order By e("GroupSortOrder") Ascending, e("ProductName")
Group e By Key = New With {
.ProductName = e("ProductName"),
.GroupName = e("GroupName")
} Into Group
Select New With {
.ProductName = Key.ProductName,
.GroupName = Key.GroupName,
.Sum = Group.Sum(Function(x) x("QTY"))
})

How can I preserve Null (DBNull) in Sum in LINQ queries

I am trying to perform this query on two DataTables in a DataSet
SELECT Totals.accCategory, Totals.ID, Totals.Account, Sum(Totals.Jan) AS Jan FROM (SELECT * FROM Allocated UNION SELECT * FROM Spent) AS Totals GROUP BY Totals.accCategory, Totals.ID, Totals.Account
As they are generated in code (in memory) into the DataSet I need to use LINQ thus:
Dim t = (From totals In (allocated.AsEnumerable.Union(spent.AsEnumerable)) _
Group totals By accCategory = totals.Item("accCategory"), ID = totals.Item("ID"), Account = totals.Item("Account") _
Into g = Group _
Select New With {Key .accCategory = accCategory, Key .ID = ID, Key .Account = Account, Key .Jan = g.Sum(Function(totals) Totals.Item("Jan"))}).ToList
Which fails as there are some instances where there are no records to sum. The Access query returns an empty cell - which is what I want. I can make the LINQ statement work by using If(IsDbNull(totals.Item("Jan")),0,totals.Item("Jan")) but then I get 0.00 if the total is zero (which is correct) but also if there are no items to sum (which I don't want)
I have tried Select New With {Key .accCategory = accCategory, Key .ID = ID, Key .Account = Account, Key .Jan = g.Sum(Function(totals) DirectCast(totals.Item("Jan"), Nullable(Of Decimal)))}).ToList which doesn't work either.
How can I make .Jan a Nullable(Of Decimal) and accept DBNull as a value??
Thanks
Andy
Got it!
Dim t = (From totals In (allocated.AsEnumerable.Union(spent.AsEnumerable)) _
Group totals By accCategory = totals.Item("accCategory"), ID = totals.Item("ID"), Account = totals.Item("Account") _
Into g = Group _
Select New With {Key .accCategory = accCategory, Key .ID = ID, Key .Account = Account, Key .Jan = If(g.AsQueryable.Any(Function(totals) totals.Field(Of Nullable(Of Decimal))("Jan").HasValue), g.AsQueryable.Sum(Function(totals) totals.Field(Of Nullable(Of Decimal))("Jan")), Nothing)}).ToList

Linq: Group by Time Interval

I've the following Datatable:
[Date];[Time];[ProcessID];[ID]
24.09.2012;08:18:00;4000;1
24.09.2012;08:18:00;4000;2
24.09.2012;08:19:00;4001;3
24.09.2012;08:23:00;4002;4
24.09.2012;08:32:00;4003;5
...
As result I would like to have a grouping by a 15-minute Time-Interval to count the ProcessID´s:
[Interval];[ProcessID Count]
8:15:00 - 8:29:00;3
8:30:00 - 8:45:00;1
How to achieve this goal?
Here's the solution against Linq-to-SQL (on SQL Server) with the DateTime being in a single field (a LINQpad query):
Const BaseDate As Date = #9/24/2012#
Const PeriodMinutes As Integer = 15
Dim p = From t In TestData _
Group By q=CInt(Math.Floor((t.SomeDate - BaseDate).TotalMinutes/PeriodMinutes)) Into Group _
Select s=BaseDate.AddMinutes(q*PeriodMinutes), _
e=BaseDate.AddMinutes((q+1)*PeriodMinutes), _
ids=Aggregate g In Group Select g.ProcessID Distinct Into Count()
p.Dump
Using different types and other "little" adjustments could produce simpler SQL backend code.
For your actual database, you need to adjust the Group By, although it now depends upon what your Time column is converted to through Linq-to-SQL and/or your database's driver.
As it is a TimeSpan the Group By becomes something like:
Group By d=t.[Date], q=CInt(Math.Floor(t.[Time].TotalMinutes/PeriodMinutes)) Into Group _
Select s=d.AddMinutes(q*PeriodMinutes), _
e=d.AddMinutes((q+1)*PeriodMinutes), _
ids=Aggregate g In Group Select g.ProcessID Distinct Into Count()
This should work (however, not tested):
Dim groupedByQuarter =
From r In table
Let day = r.Field(Of Date)("Date").Date
Let time = r.Field(Of TimeSpan)("Time")
Let quarter = time.Add(TimeSpan.FromMinutes((-1) * time.Minutes Mod 15))
Group r By Key = New With {Key .day = day, Key .quarter = quarter} Into TimeGroup = Group
Select New With {
.Interval = String.Format("{0} - {1}",
Key.quarter,
Key.quarter.Add(TimeSpan.FromMinutes(14))),
.ProcessCount = TimeGroup.Select(Function(r) r.Field(Of Int32)("ProcessID")).Distinct().Count()
}