delMo is a list of DateTime. I have it populated with 3/1/2014 and 4/1/2014. The results I get back is 2 records (what I expected) but the p.dt values for both records show 3/1/2014. I would expect 1 record to be 3/1/2014 and the other to be 4/1/2014.
My understanding of using Any() in this way is like using an in() statement in SQL. However, the results I get back don't seem to reflect this. Any ideas on what I did wrong here?
var result = (from p in db.Table1
where (from dt in delMo
where p.dt == dt).Any()
&&
(from s in db.Stores
where p.storeID == s.ID).Any()
select p).ToList();
[EDIT]
I broke the problem down further and am getting very strange results. I hardcoded the store ID to 5 and it still gives me the problem. I even loop through delMo and pass in the 1 value to p.dt and on the first pass of 3/1/2014 I get the expected result. The second pass uses 4/1/2014 and it returns 3/1/2014!! If I only have 4/1/2014 in delMo then it works. It's like it's keeping the first 3/1/2014 record for some reason. It makes no sense.
Any returns a bool indicating whether or not any elements in the collection satisfy a given condition. When used without a predicate, it indicates whether or not the collection contains elements. I'm not sure if that's what you meant by saying
in this way is like using in an in() statement
but that's what it does. See this link for more details.
As to your question in the comments, I believe something like this should do it. I'm not a huge fan of using linq over the IEnumerable extensions, so bear with me.
var result = db.Table1.Where( p =>
delMo.Contains( p.dt ) &&
db.Stores.Where( s=> s.ID == p.storeId ) );
This will return the values from db.Table1 where p.dt is in delMo and p.storeId is in db.Stores. Hope this helps!
This should help. I wonder if P has a Stores collection, if it has, then it is more straightforward, but I'm not making assumptions.
(from p in db.Table1
where delMo.Contains(p.dt)
&& db.Stores.Any(x=>x.ID==p.storeID)
select p).ToList();
Note: Date should be exact match(including time) for this to work.
Related
Sorry for title, but i didn't know how to write it better. I will try in post.
When I am trying to get values from database using linq with orderby something strange happens. Let's look on 4 queries:
//1
var badAsc = new ConcurrentBag<int>((from x in se.produkts orderby x.numerProduktu select x.numerProduktu));
//2
var bagDesc = new ConcurrentBag<int>((from x in se.produkts orderby x.numerProduktu descending select x.numerProduktu));
//3
var listAsc = (from x in se.produkts orderby x.numerProduktu select x.numerProduktu).ToList();
//4
var listdesc = (from x in se.produkts orderby x.numerProduktu descending select x.numerProduktu).ToList();
We got 2 ConcurrentBags<int> and 2 List<int>. What I was expecting from this is that 1 and 3 will be the same and also 2 and 4 will be the same. Check what values i got:
Ascending sort for ConcurrentBag<int> is in fact descending. On Microsoft site we can read, that ConcurrentBag is good when sorting does not matters, but as we can see in bagDesc, sorting is kept. To show, that I don't have any strange things in database I also make two List<int> where sorting is kept as it should be.
Executing select * from produkt in my database gives me values sorted like listAsc and bagDesc.
Database is mssql 2014 and numerProduktu is primary key in this table.
Do anybody know what happened there?
See here.
The ConcurrentBag appears to be implemented as a stack rather than a
queue. That is, the last item added is the first item removed. I
wouldn't count on that, though.
So they are getting added in reverse order. However, order is not meant to be reliably consistent in ConcurrentBag, so it's not guaranteed to always behave that way, especially if accessed by multiple threads.
If you care about maintaining the original order of entry, then you probably want a ConcurrentQueue.
I have the following query:
var vendors = (from pp in this.ProductPricings
join pic in this.ProductItemCompanies
on pp.CompanyId equals pic.CompanyId into left
from pic in left.DefaultIfEmpty()
orderby pp.EffectiveDate descending
group pp by new { pp.Company, SortOrder = (pic != null) ? pic.SortOrder : short.MinValue } into v
select v).OrderBy(z => z.Key.SortOrder);
Does anyone know how the last OrderBy() is applied? Does that become part of the SQL query, or are all the results loaded in to memory and then passed to OrderBy()?
And if it's the second case, is there any way to make it all one query? I only need the first item and it would be very inefficent to return all the results.
Well it will try to apply the OrderBy to the original query since you are still using an IQueryable - meaning it hasn't been converted to an IEnumerable or hydrated to a collection using ToList or an equivalent.
Whether it can or not depends on the complexity of the resulting query. You'd have to try it to find out. My guess is it will turn the main query into a subquery and layer on a "SELECT * FROM (...) ORDER BY SortOrder" outer query.
Given your specific example the order by in this situation most, likely be appliead as part of the expression tree when it getting build, there for it will be applied to sql generated by the LINQ query, if you would convert it to Enumarable like ToList as mentioned in another answer then Order by would be applied as an extension to Enumerable.
Might use readable code, because as you write it is not understandable.
You will have a problem in the future with the linq statement. The problem is that if your statement does not return any value the value will be null and whenever you make cause a exception.
You must be careful.
I recommend you to do everything separately to understand the code friend.
I'm working on a Linq query to join data from two tables (using Linq to SQL), with the logic as follows:
Banners contains a field which has comma separated values in it. I want to split this column and have a list of IDs (for example 1,2,3,4)
References contains a list of these mappings with 1:1 mapping between the ID in banners and the ID in the reference table
Once the tables are merged I want to return the description from the reference table, which is the text representation of the ID.
I've been fiddling with this for a while and have hit a brick wall. Below is the code I am using (in LinqPad):
var results = (from b in Banners
where b.BannerCode == "1234"
from a in b.VesselBoatAreaY.Split (',').AsEnumerable()
join r in References on a equals r.ReferenceCode
where r.Context == "TestContext"
select r.Description).ToList();
I have confirmed that the first part of the query works, i.e. that banner code exists and returns 4 separate values. When I run the query as a whole however I get the following:
NotSupportedException
Comparison operators not supported for type 'System.String[]'.
I have also tried the following:
var results = (from b in Banners
where b.BannerCode == "1234"
from a in b.VesselBoatAreaY.Split (',').AsEnumerable()
from r in References
where r.Context == "TestContext" &&
a.Contains(r.ReferenceCode)
select r.Description).ToList();
When I run this I get the following:
ArgumentException
The argument 'value' was the wrong type. Expected 'System.String'. Actual 'System.String[]'.
Any help appreciated!
Thanks for everyones help. I've solved the problem and it was actually very easy. As the table I am reading from is quite small I can apply AsEnumerable to the Banners table and it works fine. I realise this means it will get processed in memory, so it's not good for bigger tables, but its fine for what I need.
For reference the code is now:
var results = (from b in Banners.AsEnumerable()
where b.BannerCode == "1234"
from a in b.VesselBoatAreaY.Split (',')
from r in References.AsEnumerable()
where r.Context == "TestContext" &&
a.Contains(r.ReferenceCode)
select r.Description).ToList();
Ok, I must be doing something dumb, but shouldn't this work? I have following three lists:
var commonViews = (from v in context.TPM_VIEWS where v.VIEWID < 0 select v); // IQueryable<TPM_VIEWS>
var ownedViews = (from v in context.TPM_VIEWS where v.OWNERID == userId && v.VIEWID > 0 select v); // IQueryable<TPM_VIEWS>
var sharedViews = (from v in context.TPM_USER.Include("TPM_VIEWS2") where v.USERID == userId select v).First().TPM_VIEWS2; // EntityCollection<TPM_VIEWS>
Each list has the proper values and count. I can return any one of these lists:
return commonViews.ToList();
And I can return a any two of these lists:
return commonViews.Concat(ownedViews).ToList();
However, when I try to return all three:
return commonViews.Concat(ownedViews).Concat(sharedViews).ToList();
I get the exception:
Unable to create a constant value of type 'Entity.TPM_VIEWS'. Only
primitive types or enumeration types are supported in this context.
What am I doing wrong? All three values are indeed enumerable. Mostly, I'm asking this question because it's the best possible way to guarantee I'll notice the problem 30 seconds after posting.
UPDATE:
I'm 93% sure the problem is here:
var sharedViews = (from v in context.TPM_USER.Include("TPM_VIEWS2") where v.USERID == userId select v).First().TPM_VIEWS2;
This looks like an enumerable list of TPM_VIEWS object, and I can call ToList() on it and get the correct data, but it doesn't play well with the other lists.
UPDATE 2:
This actually works. Points to the person who can tell me why!
commonViews.ToList().Concat(ownedViews.ToList()).Concat(sharedViews.ToList()).ToList();
The problem is that Concat() on an EF IQueryable<T> will turn the entire concatenation into a single query.
When you call .Concat(sharedViews), you're passing a scalar (pre-loaded) collection of your nested entity class.
EF doesn't know how to convert that into a query, so it complains.
You can make it faster by calling AsEnumerable() instead of ToList().
This actually works. Points to the person who can tell me why!
commonViews.ToList().Concat(ownedViews.ToList()).Concat(sharedViews.ToList()).ToList();
That's because each of the original queries is executed separately; you're only concatenating the results in memory. There seems to be a bug in the Entity Framework query translator when you combine the 3 queries, but when you call ToList on each of them, they're no longer EF queries, they're just lists, so they're concatenated using Linq to Objects.
Does anyone knows what am I doing wrong, while getting a data from db.
I have the following code
var a = from p in db.test3s
where p.ID == '1'
select p.PostID;
ViewData["a"] = a;
And in the .aspx file the ViewData["a"] shows me this:
SELECT [t0].[PostID] FROM [dbo].[test3] AS [t0] WHERE [t0].[ID] = #p0
...instead of an (some) integer number.
I don't know, what ViewData is, but you need to be aware, that Linq to SQL queries are not executed immediately after you assign them to some variable. It's called lazy loading, and what it means is that you will have your data when you will try to operate on it (e.g. when you will try to iterate over results or sth).
What you want is:
var a = (from p in db.test3s
where p.ID == '1'
select p.PostID).First();
This will get you first result. If you want to get set of results you can call ToList(), ToArray() or something like that.
Try
if(a.Any())
ViewData["a"] = a.First();
You need to iterate over the result before the values become available. Linq2Sql does not know that your query will only return one row (although you may know that). So you could do this instead:
ViewData["a"] = db.test3s.First(t => t.Id == 1).PostID;
Which will make sure that there is only one result, and that the value of PostID is assigned to your view data.
In your example a is of type IQueryable<Int32>. It's like a list of items (but with delayed execution). You should retrieve concrete item using some of selectors: First(), FirstOrDefault(), Single(), SingleOrDefault() and so on (depends what you need in concrete situation)