Where clause in LINQ - C# - c#

I have the following which works in SQL Query Analyzer.
select oh.*
from order_history oh
join orders o on o.order_id = oh.order_id
where oh.order_id = 20119 and oh.date_inserted = (
select max(date_inserted) from order_history where order_id = oh.order_id
group by order_id
)
How would I go about converting to LINQ? From test code, the compiler complained:
Error Operator '&&' cannot be applied to operands of type 'int' and 'System.DateTime'
My LINQ code:
var query = from ch in cdo.order_histories
join c in cdo.orders on ch.order_id equals c.order_id
where (ch.order_id.equals(1234)) &&
(ch.date_inserted == (cdo.order_histories.Max(p => p.date_inserted)))
select new OrderData() { };
Update: I was not using '==' for comparing.
Item remaining is this from my SQL query:
oh.date_inserted = (
select max(date_inserted) from order_history where order_id = oh.order_id
group by order_id)
How do I do this in LINQ?

It look like you are missing an equals sign somewhere when filtering on the order_id field. You probably have:
oh.order_id = 20119 && ...
Whereas you should have:
oh.order_id == 20119 && ...
Note the equality operator vs. the assignment operator. The result of an assignment operator is the value that was assigned, which is why your error says you can't compare operands of int and System.DateTime.
I also assume you have the same problem on the check against the value of date_inserted as well.
For the second part of your question, you are close in the conversion of the correlated sub query.
In SQL you have:
oh.date_inserted = (
select max(date_inserted) from order_history where order_id = oh.order_id
group by order_id)
And in LINQ-to-SQL you have
ch.date_inserted == (cdo.order_histories.Max(p => p.date_inserted))
You just have to add the filter for the order_histories which takes advantage of closures to capture the order_id value on the ch instance like so:
ch.date_inserted == (cdo.order_histories.
Where(ch2 => ch2.order_id == ch.order_id).
Max(p => p.date_inserted))

You could translate the SQL into LINQ... or you could write the LINQ for what you want.
var result = cdo.order_histories
.Where(oh => oh.order_id == 20119)
.OrderByDescending(oh => oh.date_inserted)
.Take(1)
.Select(oh => new {history = oh, order = oh.order}
.Single();

Agreed, some C# code is needed here, but off the top of my head- you're using "==" (evaluation) rather than "=" (assignment), correct? C# makes a distinction here where SQL does not.

Related

comparison operator not supported for type int[] - linq to sql

Here is the problematic line:
var originalSummaryCandidates =
(from a in masterDB.tbl_thirty_second_summaries_multi_variant_associations
join d in masterDB.tbl_thirty_second_summaries_multi_variants on a.ThirtySecSummaryId equals d.ThirtySecondSummaryId_this
where d.DrugId == drugId &&
variantGenotypeIds.Contains(new int[] {a.VariantId, a.GenotypeId})
select d.ThirtySecondSummaryId_this)
.Distinct()
.ToList();
variantGeotpeIds is of type List<int[]>. Both a.VariantId and a.GenotypeId are of type int.
I cannot figure out why it why it will not do the comparison. Is this a deferred execution issue? It doesn't seem like it should be...
Thanks in advance.
List<T>.Contains only takes a single parameter of type T. In your case, T is Int32 but you're passing in a Int32[].
If you want to check that both values are in the list, you have to break the calls apart:
where d.DrugId == drugId &&
variantGenotypeIds.Contains(a.VariantId) &&
variantGenotypeIds.Contains(a.GenotypeId)
EDIT
If variantGenotypeIds is actually a List<Int32[]>, then there's another issue. LINQ to SQL will try to convert your query into its SQL equivalent. In this case, there's no way to translate your query into SQL so LINQ to SQL will throw an Exception.
If you really need to query this way, you'll have to read the records into memory first and then query using LINQ to Objects (which may or may not be a big deal depending on how many rows you are reading):
var query =
from a in masterDB.tbl_thirty_second_summaries_multi_variant_associations
join d in masterDB.tbl_thirty_second_summaries_multi_variants
on a.ThirtySecSummaryId equals d.ThirtySecondSummaryId_this
where d.DrugId == drugId
select new { a, d }
var originalSummaryCandidates =
(from q in query.AsEnumerable()
where variantGenotypeIds.Contains(new [] { q.a.VariantId, q.a.GenotypeId})
select d.ThirtySecondSummaryId_this)
.Distinct()
.ToList();
Array comparison uses reference equality by default. It's possible that linq-to-sql just tries to translate that into SQL that compares the values, but you'd have to look at the generated SQL to be sure. Another option would be to use Any instead:
where d.DrugId == drugId &&
variantGenotypeIds.Any(v => v[0] == a.VariantId && v[1] == a.GenotypeId)
but I'm not sure if Linq-to-Sql will be able to translate that to the correct SQL either. Another option would be to project the List` to a > and then do a string comparison:
variantGenotypeStrings = variantGenotypeIds.Select(v => string.Format("{0}|{1}", v[0],v[1]);
var originalSummaryCandidates =
(from a in masterDB.tbl_thirty_second_summaries_multi_variant_associations
join d in masterDB.tbl_thirty_second_summaries_multi_variants on a.ThirtySecSummaryId equals d.ThirtySecondSummaryId_this
where d.DrugId == drugId &&
variantGenotypeStrings.Contains(string.Format("{0}|{1}", a.VariantId, a.GenotypeId))
select d.ThirtySecondSummaryId_this)
.Distinct()
.ToList();

Writing left join Query in LINQ

select a.stakebuyinid , a.StakeBuyInValue from StakeBuyInByStakeCategories AS b
left join StakeBuyIns AS a on b.stakebuyinid = a.stakebuyinid
where b.GametypeId = 1 and b.StakeCategoryID = 3 and a.Currencyid = 1
above is my Simple SQL query i want to write in LINQ
I am using following LINQ query but Raise Error :- "The cast to value type 'Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type."
var query = (from v in db.StakeBuyInByStakeCategories.Where(x => x.GameTypeId == gametypeid && x.StakeCategoryId == stakecategoryid)
join u in db.StakeBuyIns.Where(y => y.CurrencyId == currencyid)
on v.StakeBuyInId equals u.StakeBuyInId into Temp
from vus in Temp.DefaultIfEmpty()
select new {
vus.StakeBuyInId,
vus.StakeBuyInValue )
Assume
StakeBuyInByStakeCategoriesList as IEnumerable<StakeBuyInByStakeCategories>
and StakeBuyInsList as IEnumerable<StakeBuyIns>
(from b in StakeBuyInByStakeCategoriesList
from a in StakeBuyInsList
.Where(b.stakebuyinid equals a.stakebuyinid)
.DefaultIfEmpty()
.Where( b.GametypeId == 1 and b.StakeCategoryID == 3 and a.Currencyid == 1)
select new {Stakebuyinid=a.stakebuyinid, StakeBuyInValue=a.StakeBuyInValue}
The int in your model should be an int?, since nullable return values are possible.

Converting t-sql query into EF's method syntax

What would be an EF method syntax equivalent for the following TSQL query?
select istb.service_id, ss.service_desc, selected=1
from istb_services istb
inner join setup_services ss on istb.service_id=ss.service_id
where istb.istb_id=3
union
select ss.service_id, ss.service_desc, selected=0
from setup_services ss
where ss.service_id not in (select service_id from istb_services where istb_id=3)
I tried converting the not in part of the query like following:
var _existing = context.istb_services.Where(e => e.istb_id == IstbID);
var _others = context.setup_services.Except(_existing);
but it is generating compile-time error:
The best overloaded method match for 'System.Data.Objects.ObjectQuery.Except(System.Data.Objects.ObjectQuery)' has some invalid arguments
I understand I can't pass different type of ObjectQuery to the .Except method but then what would be the alternative code?
Thanks,
Try the following:
var resultA =
from istb in istb_services
join ss in setup_services on istb.service_id equals ss.service_id
where istb.istb_id == 3
select new { istb.service_id, ss.service_desc, selected = true };
var resultB =
from ss in setup_services
where !istb_services.Any(istb =>
istb.service_id == ss.service_id &&
istb.istb_id == 3)
select new { ss.service_id, ss.service_desc, selected = false };
var result = resultA.Union(resultB);
Anonymous type initializers having identical fields should be compiled to the same anonymous type, making the two sequences compatible for the Union operation.

How to get SQL query into LINQ form in C# code

How can I convert the following SQL queries into LINQ query form in C#, .NET 3.5 code:
1)
select COUNT(distinct Skill_Name)
from Table1
where Department = 'ABC' and Skill_Name is not null
2)
select distinct location, country from Customer where Customer_Code ='1001';
I suspect you want:
var query = from entry in dbContext.Table1
where entry.Department == "ABC" && entry.SkillName != null
select entry.SkillName;
var count = query.Distinct().Count();
Or using extension method syntax, in one go:
var count = dbContext.Table1
.Where(entry => entry.Department == "ABC" &&
entry.SkillName != null)
.Select(entry => entry.SkillName)
.Distinct()
.Count();
As shown by mesiesta, you can combine query expressions with calls not supported within query expressions, but I tend to assign the query expression to an intermediate variable... I personally find it clearer, but use whichever you (and your team) prefer.
Something like this
int count = (from p in Table1
where p.Department == "ABC" && p.Skill_Name != null
select p.Skill_Name).Distinct().Count();
For second query you can use this
var query= (from p in Customer
where p.Customer_Code=="1001"
select new { Location=p.location ,Country=p.country}).Distinct();
you can use linqpad to convert to linq and lambda expressions

"IN" Operator in Linq

I am trying to convert an old raw Sql query in Linq with Entity Framework here.
It was using the IN operator with a collection of items. The query was something like that:
SELECT Members.Name
FROM Members
WHERE Members.ID IN ( SELECT DISTINCT ManufacturerID FROM Products WHERE Active = 1)
ORDER BY Members.Name ASC
Since the return of the subquery is not a single string but a collection of strings I can't use the String.Contains() method.
I thought about doing something like :
var activeProducts = (
from products in db.ProductSet
where product.Active == true
select product.ManufacturerID);
and then
var activeMembers = (
from member in db.ContactSet
where member.ID.ToString().Contains(activeProducts));
but it stops at the contains saying it has invalid arguments ... I can't select activeProducts.ManufacturerID because obviously the proprety is not there since it returns an IQueryable...
Bottom line what I'm trying to do here is to return a list of members who have at least one active product.
Any hint ?
[edit]
Here's the full query code ... I tried with the contains on the second expression, Linq didn't seem to like it :
Server Error in '/' Application.
LINQ to Entities does not recognize the method 'Boolean Contains[String](System.Linq.IQueryable``1[System.String], System.String)' method, and this method cannot be translated into a store expression.
var activeProduct =(from product in Master.DataContext.ProductSet
where product.Active == true
&& product.ShowOnWebSite == true
&& product.AvailableDate <= DateTime.Today
&& ( product.DiscontinuationDate == null || product.DiscontinuationDate >= DateTime.Today )
select product.ManufacturerID.ToString() );
var activeArtists = from artist in Master.DataContext.ContactSet
where activeProduct.Contains(artist.ID.ToString())
select artist;
NumberOfArtists = activeArtists.Count();
artistsRepeater.DataSource = activeArtists;
artistsRepeater.DataBind();
[More details]
ManufacturerID is a nullable GUID apparently...
For some reason the ContactSet class do not contain any reference to the products I guess I will have to do a join query, no clues here.
var activeMembers = (
from member in db.ContactSet
where activeProducts.Select(x=>x.ID).Contains(member.ID));
Try where activeProducts.Contains(member.ID).
EDIT: Did you try it without any ToStrings?
You can do it in one query:
var q = from member in db.ContactSet
where member.Products.Any(p => p.IsActive)
select member;
Try the solution posted by Colin Meek at: http://social.msdn.microsoft.com/forums/en-US/adodotnetentityframework/thread/095745fe-dcf0-4142-b684-b7e4a1ab59f0/. It worked for me.
What about this:
from m in members
where products.FirstOrDefault(prod => prod.IsActive == 1 && prod.Id == m.Id) != null
select m;
you can chain any number of conditions required in the where clause using &&
Ash..
from m in members
where products.Any(p => p.Active && p.ManufacturerID == m.ID)
select m
or
from m in members
join p in products on m.ID equals p.ManufacturerID
where p.Active
select m
Instead of this:
var activeMembers = (
from member in db.ContactSet
where member.ID.ToString().Contains(activeProducts));
Try this:
var activeMembers = (
from member in db.ContactSet
where activeProducts.Contains(member.ID));
What if you swap the statement (untested)?
where activeProducts.Contains(member.ID)
How about this...
var activeProducts = (
from products in db.ProductSet
where product.Active == true
select product.ManufacturerID);
var activeMembers = (
from member in db.ContactSet
where activeProducts.Contains(member.ID.ToString()));
A helper or extension method will work fine when querying against objects in memory. But against an SQL database, your LINQ code will be compiled into an expression tree, analysed and translated into an SQL command. This functionality has no concept of custom-made extension methods or methods of other objects like .Contains(...).
It could be easily implemented into the standard LINQ-To-SQL functionality by Microsoft though. But as long as they don't want, we're helpless as long it's not an open source functionality.
All you can do is create your own QueryProvider that goes against an SQL database. But it will be hard and it would be only for that one in feature alone that you're missing.
However, if you really wanna go that route, have fun: LINQ: BUILDING AN IQUERYABLE PROVIDER SERIES
Finally I managed to code something really ugly, but that actually works! (lol)
var activeProduct =(from product in Master.DataContext.ProductSet
where product.Active == true
&& product.ShowOnWebSite == true
&& product.AvailableDate <= DateTime.Today
&& ( product.DiscontinuationDate == null || product.DiscontinuationDate >= DateTime.Today )
select product.ManufacturerID ).Distinct();
var artists = from artist in Master.DataContext.ContactSet
select artist;
List<Evolution.API.Contact> activeArtists = new List<Evolution.API.Contact>();
foreach (var artist in artists)
{
foreach(var product in activeProduct)
{
if (product.HasValue && product.Value == artist.ID)
activeArtists.Add(artist);
}
}
NumberOfArtists = activeArtists.Count();
artistsRepeater.DataSource = activeArtists;
artistsRepeater.DataBind();
I have already posted about the same at
http://www.codeproject.com/Tips/336253/Filtering-records-from-List-based-similar-to-Sql-I
var q = (from p in db.DOCAuditTrails
where p.ActionUser == "MyUserID"
&& p.ActionTaken == "Not Actioned"
&& p.ActionDate > DateTime.Parse("2011-09-13")
select p.RequisitionId).Distinct();
var DocAuditResults = db.DOCAuditTrails.Where(p
=> q.ToArray().Contains(p.RequisitionId));
Without know the exact mappings it is hard to tell what can be done and what can't. I will assume that there isn't any casting involved. Firstly you have to remember that everything in the Linq Expression tree must have an equivalent in SQL. As some others have noted, you have a object.ToString() in your Linq Statements.
However it seems that what people have neglected to mention is that you have TWO usages of object.ToSting(), both of which must be removed.
I would also make an extra variable to change the closure's capture type to be explicitly of DataContext (since the Linq statement is like a lambda, and delayed evaluated. It will need to take the whole of the Master variable. Earlier I stated that everything in your Linq must have an equivalent in SQL. Given that Master can't possibly exist in SQL, there is no DataContext property/column/mapping for the type of Master).
var context = Master.DataContext;
var activeProduct = from product in context.ProductSet
where product.Active == true
&& product.ShowOnWebSite == true
&& product.AvailableDate <= DateTime.Today
&& ( product.DiscontinuationDate == null || product.DiscontinuationDate >= DateTime.Today )
select product.ManufacturerID;
var activeArtists = from artist in context.ContactSet
where activeProduct.Contains(artist.ID)
select artist;
I hope the above changes work for you.
In many cases issues with Linq to ORMs can be traced back to your Linq Expression capturing a non primative (DateTime, int, string etc) and non ORM based class (DataContext/EntityObject etc). The other major gotcha is usage of functions and operators that aren't exposed by the ORM (it is possible to map user defined functions to .net function through the ORM, but I would not recommend it due to indexing issues).

Categories

Resources