I have a linq query that is used to display the list of requests from multiple users.And a Requestor can have multple requests(So the grid can have same Requestor multiple times). Now i am creating a dropdown list with unique Requestor that are displayed on the grid.(issue is i am not getting the distinct list but getting all the Requestor multiple times). Below is the linq query i am unsing.Can anyone suggest with correct linq query.
Dim rqstQry = From x In db.Request_vws _
Order By x.RequestID Descending _
Select x.RequestID,
Descr = x.Descr, _
RequestorName = String.Format("{0} {1}", x.FIRST_NAME, x.LAST_NAME), _
RelatedTask = GetTaskDescr(x.WorkID, x.TaskLabel, x.TaskDescr), _
RequestDescr = GetRequestDescr(x.RequestType), x.SubmitDttm, x.UpdatedDttm, _
x.ChangeDttm, _
x.MigrTimeStr, x.MigrApptTime, _
x.Requestor Ditinct
DataBind:
RequestorCB1.DataSource = rqstQry
RequestorCB1.DataTextField = "Requestor" RequestorCB1.DataValueField = "REquestor"
RequestorCB1.DataBind()
Need distinct user in the dropdownlist
Put parentheses around the LINQ query and append .Distinct()
Dim rqstQry = (From x In db.Request_vws _
Order By x.user
Select x.user).Distinct()
If you are including Request stuff in the result, then you cannot get distinct users (as Gert Arnold points out in his comment). Only include columns related to users.
If you still need information on requests then you must limit this information to one record per user. You would use a group by and use an aggregate in order to select a request (the first one, the last one etc.).
Got this by using the below query.
Dim rqstQry = (From x In db.Request_vws _
Order By x.RequestID Descending _
Select x.RequestID,
Descr = x.Descr, _
RequestorName = String.Format("{0} {1}", x.FIRST_NAME, x.LAST_NAME), _
RelatedTask = GetTaskDescr(x.WorkID, x.TaskLabel, x.TaskDescr), _
RequestDescr = GetRequestDescr(x.RequestType), x.SubmitDttm, x.UpdatedDttm, _
x.ChangeDttm, _
x.MigrTimeStr, x.MigrApptTime, _
x.Requestor). Distinct()
Dim rqstQry2 = (From y In rqstQry _
Select y.Requestor, y.RequestorName).Distinct()
I am trying to insert/update my table using the values in the grid
Given below is the code I'm using to get the productId in the grid:
Dim prodId = From row As DataRow _
In grdSale.Rows _
Where row.Item(0).ToString <> "" _
Select row.Item(0)
I am getting productid correctly. Given below is the code to get the value in QTY column with respect to the productId:
For Each id As Long In prodId
Dim intpdt As Long
intpdt = id
intQty = (From row As DataRow In grdSale.Rows Where _
row.Item(0).Equals(intpdt) _
Select row.Item("QTY")).FirstOrDefault()
Next
In intQty I am getting 0 but it should be 10 or 12 as you can see in the QTY column in the grid (Enumeration yielded no results).
Where am wrong?
Try doing this and see if you get the result you expected:
intQty = _
( _
From row As DataRow In grdSale.Rows Where _
CLng(row.Item(0)) = intpdt _
Select CInt(row.Item("QTY")) _
).FirstOrDefault()
Not sure what causes your issue, but you should use the Field extension method since it is strongly typed and supports nullable types. I also don't understand why you need the additional loop and query to find the quantity of each product. This should do both:
Dim prodQTYs = From row In grdSale.Rows.Cast(Of DataRow)()
Let ProductID = row.Field(Of String)("ProductId")
Let Quantity = row.Field(Of Long)("QTY")
Where Not String.IsNullOrWhiteSpace(ProductID)
Select New With {.ProductID = ProductID, .Quantity = Quantity}
Change the types to the appropriate ones.
Output:
For Each prodInfo In prodQTYs
Console.WriteLine("Product:{0} Quantity:{1}", prodInfo.ProductID, prodInfo.Quantity)
Next
I have an application utilising Entity Framework 5 Database First, VB.net, Linq, SQL Server 2008 R2 and a Disconnected Repository Pattern.
I've used the EF5.x dbContext generator to create my POCO's and modified the T4 Template to add various extra bits and bobs, including my INotifiyPropertyChanged Event Raising.
I have various linked tables, and I need to show data in a "Friendly" manner.
As an example, I have the following two tables;
Colours:
Colour_ID | Colour_Name | Created_By | Creation_Date | Modified_By | Modification_Date
----------------------------------------------------------------------------------------------
1 | Blue | 1 | 22-01-13 | 1 | 23-01-13
Users:
User_ID | First_Name | Last_Name |
--------------------------------------
1 | Peter | Gallagher |
In order to show the "Friendly Data" in my DataGrids, I'm pulling in the data, and creating "Friendly Entities" using code such as;
Using CriticalPathDBContext As CriticalPathEntities = ConnectToDatabase()
Dim query = (From Colour In CriticalPathDBContext.Colours _
.Include(Function(x) x.CreationUser) _
.Include(Function(x) x.LastUpdateUser).AsNoTracking.ToList
Select New FriendlyColours With {.CreatedBy = If(Colour.CreationUserCode Is Nothing, "", Colour.CreationUser.First_Name & " " & Colour.CreationUser.Last_Name),
.CreationDate = Colour.CreationDate,
.CreationUserCode = Colour.CreationUserCode,
.LastUpdateDate = Colour.LastUpdateDate,
.LastUpdatedBy = If(Colour.LastUpdateUserCode Is Nothing, "", Colour.LastUpdateUser.First_Name & " " & Colour.LastUpdateUser.Last_Name),
.LastUpdateUserCode = Colour.LastUpdateUserCode,
.Colour_ID = Colour.Colour_ID,
.Colour_Name = Colour.Colour_Name}).OrderBy(Function(x) x.Colour_Name)
Return New ObservableCollection(Of FriendlyColours)(query)
End Using
My problem with the above is, for more complicated connected Entities, this type of query takes a too long.
I've considered using my Buddy Classes to pull in the related data, however in a disconnected pattern, this doesn't work for me.
Obviously, while disconnected, lazy loading isn't an option...
So, my question is... Is there a better way of doing this? For better... Read faster!
Any help would be gratefully received! Maybe I'm missing something obvious!
Edit...To further explain:
I have a query which returns all Products, as well as their
Components and Product Stock Items...
There are 4 different sorts of Component lists which are returned, as
well as a list of Product Stock Items.
I take each set of Components and Product Stock Items, and fill an
associated Grid with the results.
The User is able to add, edit or delete items from the various Components or Product Stock items.
The query is (sorry for the size!);
Dim query = (From ProductList In _DBContext.Products _
.Include(Function(x) x.CreationUser) _
.Include(Function(x) x.LastUpdateUser) _
.Include(Function(x) x.Colour) _
.Include(Function(x) x.License) _
.Include(Function(x) x.Pack_Size) _
.Include(Function(x) x.Customer) _
.Include(Function(x) x.Supplier) _
.Include(Function(x) x.ProductComponents) _
.Include(Function(x) x.ProductComponents.Select(Function(y) y.ApprovalType)) _
.Include(Function(x) x.ProductComponents.Select(Function(y) y.Component)) _
.Include(Function(x) x.ProductComponents.Select(Function(y) y.Component).Select(Function(z) z.ComponentType)) _
.Include(Function(x) x.Product_Stock_Item) _
.Include(Function(x) x.Product_Stock_Item.Select(Function(y) y.Pack_Type)) _
.Include(Function(x) x.Product_Stock_Item.Select(Function(y) y.Product_Sizing)) _
.Include(Function(x) x.Product_Stock_Item.Select(Function(y) y.Units_Of_Measure)) _
.Include(Function(x) x.ProductType) _
.Include(Function(x) x.ProductClassification) _
.Include(Function(x) x.ProductType.ProductDepts) _
.Include(Function(x) x.Season).AsNoTracking().OrderBy(Function(x) x.Product_Code).ToList
Select New FriendlyProducts With {.Colour_ID = ProductList.Colour_ID,
.Colour_Name = If(ProductList.Colour_ID Is Nothing, "", ProductList.Colour.Colour_Name),
.CreatedBy = If(ProductList.CreationUserCode Is Nothing, "", ProductList.CreationUser.First_Name & " " & ProductList.CreationUser.Last_Name),
.CreationDate = ProductList.CreationDate,
.CreationUserCode = ProductList.CreationUserCode,
.FriendlyCreationUser = ProductList.CreationUser,
.Cust_Product_Desc_24 = ProductList.Cust_Product_Desc_24,
.Cust_Product_Desc_48 = ProductList.Cust_Product_Desc_48,
.Customer_Code = ProductList.Customer_Code,
.Customer_Name = If(ProductList.Customer_Code Is Nothing, "", ProductList.Customer.NAME),
.Description = ProductList.Description,
.DesignNo = ProductList.DesignNo,
.Gender_ID = ProductList.Gender_ID,
.Gender_Name = If(ProductList.Gender_ID Is Nothing, "", ProductList.Gender.Gender_Name),
.LicenseCode = ProductList.LicenseCode,
.License_Name = If(ProductList.LicenseCode Is Nothing, "", ProductList.License.NAME),
.Pack_Size_ID = ProductList.Pack_Size_ID,
.Pack_Size_Name = If(ProductList.Pack_Size_ID Is Nothing, "", ProductList.Pack_Size.Pack_Size_Name),
.PackagingNR = ProductList.PackagingNR,
.ProductClassification_ID = ProductList.ProductClassification_ID,
.Product_Classification_Name = If(ProductList.ProductClassification_ID Is Nothing, "", ProductList.ProductClassification.ProductClassification_Name),
.Product_Code = ProductList.Product_Code,
.Product_Picture_Path = ProductList.Product_Picture_Path,
.ProductComponentsNR = ProductList.ProductComponentsNR,
.ProductType_ID = ProductList.ProductType_ID,
.ProductType_Name = If(ProductList.ProductType_ID Is Nothing, "", ProductList.ProductType.NAME),
.ProductDept_ID = If(ProductList.ProductType Is Nothing, Nothing, ProductList.ProductType.ProductDept),
.ProductDept_Name = If(ProductList.ProductType Is Nothing, "", (If(ProductList.ProductType.ProductDepts Is Nothing, "", ProductList.ProductType.ProductDepts.NAME))),
.SageDescription = ProductList.SageDescription,
.SeasonCode = ProductList.SeasonCode,
.Season_Name = If(ProductList.SeasonCode Is Nothing, "", ProductList.Season.NAME),
.StrikeOffNR = ProductList.StrikeOffNR,
.Supplier_Code = ProductList.Supplier_Code,
.Supplier_Name = If(ProductList.Supplier_Code Is Nothing, "", ProductList.Supplier.NAME),
.TransfersNR = ProductList.TransfersNR,
.Deleted = ProductList.Deleted,
.LastUpdateDate = ProductList.LastUpdateDate,
.LastUpdatedBy = If(ProductList.LastUpdateUserCode Is Nothing, "", ProductList.LastUpdateUser.First_Name & " " & ProductList.LastUpdateUser.Last_Name),
.LastUpdateUserCode = ProductList.LastUpdateUserCode,
.ProductComponents = If(ProductList.ProductComponents.Count > 0, GetProductComponentsByPrimaryName(ProductList.ProductComponents, "Component"), New ObservableCollection(Of FriendlyProductComponents)),
.ProductPackaging = If(ProductList.ProductComponents.Count > 0, GetProductComponentsByPrimaryName(ProductList.ProductComponents, "Packaging"), New ObservableCollection(Of FriendlyProductComponents)),
.ProductStrikeOffs = If(ProductList.ProductComponents.Count > 0, GetProductComponentsByPrimaryName(ProductList.ProductComponents, "Strike Off"), New ObservableCollection(Of FriendlyProductComponents)),
.ProductTransfers = If(ProductList.ProductComponents.Count > 0, GetProductComponentsByPrimaryName(ProductList.ProductComponents, "Transfers"), New ObservableCollection(Of FriendlyProductComponents)),
.ProductStockItems = If(ProductList.Product_Stock_Item.Count > 0, GetProductStockItems(ProductList.Product_Stock_Item), New ObservableCollection(Of FriendlyProductStockItems))
}).Where(Function(x) x.Deleted = False Or x.Deleted Is Nothing)
Where GetProductComponentsByPrimaryName calls a function which simply filters the Components by their type and returns a Friendly ObservableCollection.
So each related Set of Components and Product Stock Items is returned as an ObservableCollection, which I can interact with...
Sorry about the long post!
EDIT - 08-03-13:
I have not resolved this issue above, but I have managed to persuade the client that they shouldn't be retrieving all the results and then relying on the User to filter afterwards.
This also led me to rejig my Filtering routines so that the Filtering is performed on the database, rather than locally.
Both of these two factors mean the query below now functions at a reasonable speed.
I tried filling my entities manually, but this took far longer than the query which Linq produced for me.
One of these days perhaps I'll revisit this problem to see what I can learn. But for now, I've sidestepped it!
Create a stored procedure that does this same query and return the results as a new entity type or as FriendlyColours if you can swing it. You are right, doing it like this is a hog. Not sure what else I can add.
That Query will result in a massive amount of data over the wire. You should probably start by projecting to entities that only contains the data you need. Maybe that won't help here though depending on you data needs.
SQL is usually blazing fast at running simple queries so you could try to load each collection seperately and then Stich the entities toghether in code. This will grately reduce the amount of data transfared.
To explain why joining like this will kill your performance here is a simple example:
In my test database I have three tables with very little data but you should still see the pattern.
First the individual queries
SELECT * FROM [OPath-dev].[dbo].[Groups] g
1;Hästhovarna;nzb5x50vibb;0;NULL;NULL;0
One single row. 39 characters according to notepad++
SELECT * FROM [OPath-dev].[dbo].[GroupMemberships]
1;1;1
2;1;0
Two rows. 12 characters
SELECT * FROM [OPath-dev].[dbo].[Blogs] where id > 5
3 rows with the fields;
Title;
Intro;
Body;
PublishDate;
Created;
CreatorIP;
Creator;
Edited;
Editor;
EditorIP
at 5907 characters
Joining the two simple tables
SELECT *
FROM [OPath-dev].[dbo].[Groups] g
JOIN [OPath-dev].[dbo].[GroupMemberships] gm on gm.GroupId = g.Id
1;Hästhovarna;nzb5x50vibb;0;NULL;NULL;0;1;1;1
1;Hästhovarna;nzb5x50vibb;0;NULL;NULL;0;2;1;0
The length is now 96 characters. If running these two in separate queries it would be 39 + 12 = 51 (Which probably is faster because the small difference).
Joining all three tables
SELECT *
FROM [OPath-dev].[dbo].[Groups] g
JOIN [OPath-dev].[dbo].[GroupMemberships] gm on gm.GroupId = g.Id
JOIN [OPath-dev].[dbo].[Blogs] b on b.Id > 5
The response is 6 rows with the columns:
Id;
Name;
JoinCode;
IsCompetitionClub;
SourceSystemKey_SystemKey;
SourceSystemKey_EntityId;
SourceSystemKey_HasValue;
UserId;
GroupId;
IsAdministrator
ID;
Title;
Intro;
Body;
PublishDate;
Created;
CreatorIP;
Creator;
Edited;
Editor;
EditorIP
The response now is 11954 characters long and we are suddenly paying quite a toll for the joins. Especially if the database is located on the same machine or on a really fast network.
Now this is even a bad example. I have better datasets that would show even worse growth on my other computer. And remeber that you are joining many more columns which will end up in a massive amount of data transfered. If it's a windows application and you are connecting to the database over a WAN that will be a serious problem but even on the local machine you can see that the transfer is not free if you profile.
I am trying to work out a LINQ query to pull items from a List, the List contains a child-nested List - which I need to query for an item, then use the resulting item in my final sort of all records returned the query.
The parent is List(Of MediaItems) - the class structure as follows:
MediaItems
.ID (int)
.Src (string)
.Advert (bool)
.AdOptions As List(Of AdvertOptions)
.Counter (int)
AdvertOptions class consists of:
.Age (int)
.Gender (int)
.Priority (int)
I want to query for any MediaItems that meet the following criteria:
.Advert = true
.Age = x (paramter in calling function)
.Gender = y (paramter in calling function)
To do this, I am using the following LINQ query: (Age and Gender are the function parameters)
Where(Function(s) s.Advert And s.AdOptions.Any(Function(a) a.Gender = Gender And a.Age = Age))
I now need to sort the results based on two sorting levels:
AdOptions.Priority (in descending order), then sort by Counter in ascending order
This is my failing attempt:
Where(Function(s) s.Advert And s.AdOptions.Any(Function(a) a.Gender = Gender And a.Age = Age)).OrderBy(Function(a) From p1 In a.AdOptions Where p1.Gender = Gender And p1.Age = Age Select p1.Priority).ThenByDescending(Function(s) s.Counter)
My attempt is not working, I am getting the following error:
at least on object must implement IComparable
Can anyone see what needs to be done to achieve my goal?
Ben
On reading your code a bit closer, I spotted that you order by AdOptions
I think this is what you really want
Sub Demo(ByVal gender As Integer, ByVal age As Integer)
Dim items = New List(Of MediaItem)()
Dim matching = Function(a) a.Gender = gender And a.Age = age
Dim ads = items.Where(Function(s) s.Advert And s.AdOptions.Any(matching))
Dim sorted = ads _
.OrderBy(Function(a) a.AdOptions.Where(matching).Max(Function(ao) ao.Priority)) _
.ThenByDescending(Function(s) s.Counter)
' if you really wanted a sorted list of AdOptions, you'd write
Dim optionlist = ads.OrderByDescending(Function(s) s.Counter) _
.SelectMany(Function(a) a.AdOptions.Where(matching).OrderBy(Function(ao) ao.Priority))
' to combine the two previous options
Dim adsWithOptions = ads.OrderByDescending(Function(s) s.Counter) _
.Select(Function(a) New With { _
.Ad = a, _
.Options = a.AdOptions.Where(matching) _
.OrderBy(Function(ao) ao.Priority) _
})
End Sub
I want to filter records dynamically on user choice. The user may choose to show the debit amount greater than credit or credit amount greater than debit. Accordingly I want to put a condition similar to either totDebit>totCredit orTotCredit>totDebit`
Dim query = _
From product In Bills.AsEnumerable() _
Group product By accode = product.Field(Of String)("ACCODE"), _
BILLNO = product.Field(Of String)("BILLNO") Into g = Group _
Let totDebit = g.Sum(Function(proudct) proudct.Field(Of Decimal)("DEBIT")) _
Let totCredit = g.Sum(Function(proudct) proudct.Field(Of Decimal)("CREDIT")) _
Select New With _
{ _
.ACCODE = accode, _
.billno = BILLNO, _
.TOTALDEBIT = totDebit, _
.TOTALCREDIT = totCredit, _
.BALNACE = totDebit - totCredit _
}
How can this be done?
In the code you h ave shownm you've merely built a query; you haven't executed it yet. And, at any point before you excute it, you may continue to build it:
Dim query = _
From product In Bills.AsEnumerable() _
Group product By accode = product.Field(Of String)("ACCODE"), _
' etc as above....
If onlyCredits Then
query = query.Where(Function(proudct) product.TOTALCREDIT > product.TOTALDEBIT)
Elseif onlyDebits Then
query = query.Where(Function(proudct) product.TOTALCREDIT < product.TOTALDEBIT)
Endif
Note, I'm a C# guy, so please forgive minor syntax errors....
I think you're looking for Dynamic Query Library. Not included in Linq but availble for download from Scott Guthrie's blog:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
Both the VB and C# DynamicQuery
samples include a source
implementation of a helper library
that allows you to express LINQ
queries using extension methods that
take string arguments instead of
type-safe language operators.
You can apply strings to filter the exection:
myData.DynamicWhere(string.Format("{0}.Contains(\"{1}\")", filter.field, filter.data.value));