Problems getting System.Linq.Dynamic to work. - linq

I have included the System.Linq.Dynamic library in my project via Nuget. The following is my linq query which works fine if I use typed fields to be returned in the select. But using System.Linq.Dynamic I should be able to use a string value for the select. I've followed the examples that I found but all I get back from the select is the string itself.
What am I missing?
var predicate = PredicateBuilder.False<Name>();
predicate = predicate.And(d => d.ID == "100053");
var results = from n in Names
.AsExpandable()
.Where(n=> n.ID=="100053")
join d in InstitutionDemographics on n.ID equals d.ID
join m in MemberAdhocIds on n.ID equals m.ID
join a in NameAddresses on n.BillingAddressNumber equals a.AddressNumber
join mas in MemberAdhocServices on n.ID equals mas.InstitutionID
select("new(n.ID,n.Company,n.MemberStatus,n.Email,n.MemberType,n.USCongress,n.FAX,n.County,d.NumberYearsAMember,d.Population,d.FederalReserveDistrict,d.FDICCertificateNumber,d.FRSID,d.ICBADistrictCode,d.UD_Minority_Type,d.MSA,d.NumberOfBranches,d.PubliclyTraded,d.SRAMemberships,d.Assets,d.RSU,d.FutureDues,d.InstitutionType,d.AgLoanPercentageTotal,m.CCRP,a.City,a.State,a.Address1,a.ZIP)");
results.Dump();

If you're telling the select statement to select a string, it's not going to return the values for those strings. What happens if you try without the quotes?
I'm not fluent in C#, being a VB fiend, but you could try something like:
Select New With {.Id = n.ID, .Company = n.Company, ...etc}
Does that make sense? Apologies if I've misunderstood your question.

My mistake. I didn't realize how the extension worked. I was expecting the extension to work in query syntax when in reality it would only work in method syntax.
i.e.
.Select("new (ID,Name)");
(this works)
-vs-
select(new(ID,Name)");
(this doesn't work)

Related

What tools are there that help build expression trees for dynamic LINQ queries?

My project needs to let users build their own dynamic queries. From what I've read, Expression Trees are the way to go. However the syntax is rather complicated.
I envision having a GUI where users would be able to check tables, select columns, specify parameters,etc and then build a string such as:
var myQuery =
from P in context.Projects
join UA in context.UserAttributes on P.ProjectID equals UA.ProjectID
join UBA in context.UserBooleanAttributes on UA.UserAttributeID equals UBA.UserAttributeID
join U in context.Users on UBA.UserID equals U.UserID
where P.ProjectID == 1
where UBA.Value == true
where (UA.UserAttributeID == 1 || UA.UserAttributeID == 2)
select new { uba = U };
And store that in a queries table. To process the query, I was hoping there is some library out there that will magically do something like:
var result = magic(str);
foreach(var user in result)
Foo(user.Email);
In this example I know that all my queries would return Users, but for other queries I would probably have to use reflection or in another column specify the expected type in results.
I found one project called LinqTextQueryBuilder which looks interesting, but I wanted to see if there are other alternatives.

converting sql to linq woes

At my job our main application was written long ago before n-tier was really a thing, ergo - it has tons and tons of business logic begin handled in stored procs and such.
So we have finally decided to bite the bullet and make it not suck so bad. I have been tasked with converting a 900+ line sql script to a .NET exe, which I am doing in C#/Linq. Problem is...for the last 5-6 years at another job, I had been doing Linq exclusively, so my SQL has gotten somewhat rusty, and some of thing I am converting I have never tried to do before in Linq, so I'm hitting some roadblocks.
Anyway, enough whining.
I'm having trouble with the following sql statement, I think due to the fact that he is joining on a temp table and a derived table. Here's the SQL:
insert into #processedBatchesPurgeList
select d.pricebatchdetailid
from pricebatchheader h (nolock)
join pricebatchstatus pbs (nolock) on h.pricebatchstatusid = pbs.pricebatchstatusid
join pricebatchdetail d (nolock) on h.pricebatchheaderid = d.pricebatchheaderid
join
( -- Grab most recent REG.
select
item_key
,store_no
,pricebatchdetailid = max(pricebatchdetailid)
from pricebatchdetail _pbd (nolock)
join pricechgtype pct (nolock) on _pbd.pricechgtypeid = pct.pricechgtypeid
where
lower(rtrim(ltrim(pct.pricechgtypedesc))) = 'reg'
and expired = 0
group by item_key, store_no
) dreg
on d.item_key = dreg.item_key
and d.store_no = dreg.store_no
where
d.pricebatchdetailid < dreg.pricebatchdetailid -- Make sure PBD is not most recent REG.
and h.processeddate < #processedBatchesPurgeDateLimit
and lower(rtrim(ltrim(pbs.pricebatchstatusdesc))) = 'processed' -- Pushed/processed batches only.
So that's raising an overall question first: how to handle temp tables in Linq? This script uses about 10 of them. I currently have them as List. The problem is, if I try to .Join() on one in a query, I get the "Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator." error.
I was able to get the join to the derived table to work using 2 queries, just so a single one wouldn't get nightmarishly long:
var dreg = (from _pbd in db.PriceBatchDetails.Where(pbd => pbd.Expired == false && pbd.PriceChgType.PriceChgTypeDesc.ToLower().Trim() == "reg")
group _pbd by new { _pbd.Item_Key, _pbd.Store_No } into _pbds
select new
{
Item_Key = _pbds.Key.Item_Key,
Store_No = _pbds.Key.Store_No,
PriceBatchDetailID = _pbds.Max(pbdet => pbdet.PriceBatchDetailID)
});
var query = (from h in db.PriceBatchHeaders.Where(pbh => pbh.ProcessedDate < processedBatchesPurgeDateLimit)
join pbs in db.PriceBatchStatus on h.PriceBatchStatusID equals pbs.PriceBatchStatusID
join d in db.PriceBatchDetails on h.PriceBatchHeaderID equals d.PriceBatchHeaderID
join dr in dreg on new { d.Item_Key, d.Store_No } equals new { dr.Item_Key, dr.Store_No }
where d.PriceBatchDetailID < dr.PriceBatchDetailID
&& pbs.PriceBatchStatusDesc.ToLower().Trim() == "processed"
select d.PriceBatchDetailID);
So that query gives the expected results, which I am holding in a List, but then I need to join the results of that query to another one selected from the database, which is leading me back to the aforementioned "Local sequence cannot be used..." error.
That query is this:
insert into #pbhArchiveFullListSaved
select h.pricebatchheaderid
from pricebatchheader h (nolock)
join pricebatchdetail d (nolock)
on h.pricebatchheaderid = d.pricebatchheaderid
join #processedBatchesPurgeList dlist
on d.pricebatchdetailid = dlist.pricebatchdetailid -- PBH list is restricted to PBD purge list rows that have PBH references.
group by h.pricebatchheaderid
The join there on #processedBatchesPurgeList is the problem I am running into.
So uh...help? I have never written SQL like this, and certainly never tried to convert it to Linq.
As pointed out by the comments above, this is no longer being rewritten as Linq.
Was hoping to get a performance improvement along with achieving better SOX compliance, which was the whole reason for the rewrite in the first place.
I'm happy with just satisfying the SOX compliance issues.
Thanks, everyone.

LINQ .Count() not defined for int

I have the below LINQ statement, and get the error " 'int' does not contain a definition for 'Count' and no extension method 'Count' accepting a first argument of type 'int' could be found ( are you missing a using directive or assembly reference?) "
var queryFuture = from pqv in context.OrderPrintQueue_View
join od in context.Order_Details on pqv.confirmId equals od.ConfirmId
join pp in context.Product_Price on od.priceId equals pp.priceId
join p in context.Products on pp.productId equals p.ProductID
select new { p.stationId, inProc = 0, OrderLinesCount = od.recId.Count() };
od.recId.Count() is the portion that is returning an error. I'm very new to LINQ (have been using it for about 2 days) and am a novice programmer. The answers I have found all say to include the system.core assembly reference, and of course, the System.Linq using. I have all of those so I'm not sure what the deal is. I am using WPF with .NET 4, EF, and RIA services and the MVVM pattern.
recID is of type int, not IEnumerable<?>. Count() is only defined on IEnumerable<?>. You will ned a group by statement:
var queryFuture = from pqv in context.OrderPrintQueue_View
join od in context.Order_Details on pqv.confirmId equals od.ConfirmId
join pp in context.Product_Price on od.priceId equals pp.priceId
join p in context.Products on pp.productId equals p.ProductID
group od by od.recId into orders
select new { p.stationId, inProc = 0, OrderLinesCount = orders.Count() };
Note: I'm not sure of this combination of group by and join will work out, as I usually only use the method chains. You might have to adjust on the operators, however you'll need a group by in any case.
Why would you want to get the count for an integer? You are probably getting a single value back, not a collection, which it seems is what you are expecting.

linq where clause problem on multiple join tables

var studentDetails = from aspUser in db.aspnet_Users
join aspMembership in db.aspnet_Memberships on
aspUser.UserId equals aspMembership.UserId
join expUser in db.explore_users on
aspUser.UserId equals expUser.aspnetUserId
where expUser.Id.Equals(studID)
select new { expUser.DOB,
aspMembership.Email,
aspUser.UserName,
aspUser.LoweredUserName,
expUser.Id };
gv1.DataSource = studentDetails;
gv1.DataBind();
I have no idea why this did not work. When i remove where clause everything is running.
I have try to put where expUser.Id == studID is also did not work
if anyone can help me pls
Shouldn't that be where expUser.aspnetUserId.Equals(studID)?
If ID is the correct column then (as already commented) of what type are expUser.ID and the variable studID? Are they of the same type? If so then does the studID value exist in db.explore_users?

FirstOrDefault behavior directly in LINQ statement

Seems like I may have missed something simple in the syntax, but I'd like to get the results of FirstOrDefault from a linq statement directly without having to store the IEnumerable in a temporary variable first. Something like this:
var bestCar = from c in cars
orderby c.Price
select first c
I know the first keyword doesn't actually exist but illustrates what I'd like to do. I also know I can wrap the from...select statement in parenthesis and call FirstOrDefault directly but I think the above syntax is cleaner and easier to read.
Enumerable.FirstOrDefault is one of the extension methods in the Enumerable class which does not have a corresponding LINQ syntax element. The only way to bind to this method is via method call syntax.
You can avoid the temporary by doing the follownig
var bestCar = (from c in cars
orderby c.Price
select c).FirstOrDefault();
There isn't a way to do that. LINQ is used for defining a query. Doing that doesn't actually cause an evaluation, whereas executing FirstOrDefault (or enumerating over it) executes the query.
var bestCar = (from c in cars
orderby c.Price
select c).FirstOrDefault()
OR
var bestCar = cars.OrderBy(c => c.Price).FirstOrDefault()
var bestCar = (from c in cars
orderby c.Price
select c).FirstOrDefault();
Sorry I didn't read your question entirely, it seems that this may be exactly what you don't want to do.
In VB you can use 'Aggregate':
Dim BestCar = Aggregate c In cars
Order By c.Price
Into FirstOrDefault

Resources