I've been trying to solve this for the entire day.. :-(
I'm Using C# with MSSQL and querying via LINQ
I have a collection stored in studWithTuiDisc variable, It contains the following data (shown in the link below)
(source: secompeusc.com)
When using this variable as reference for other LINQ Statements the results are very off, prior to this post I performed experiments to check if it really wasn't my fault that incorrect results were returned:
(1) I tried to iterate through studWithTuiDisc and then checking the relationship only in the select clause since I'm sure that this will return the desired output (see below)
Code:
var xxx = (from a in studWithTuiDisc
select new
{
please = a.StudentId,
help = _conn.EEnrolledSubjects
.Where(m => m.StudentId == a.StudentId)
.Select(m => m.StudentId)
.FirstOrDefault()
}).Distinct();
Output:
(source: secompeusc.com)
As we can see the studWithTuiDisc values are the only values contained in xxx
(2) Now I tried the approach that gave me a lot of headaches (see below)
Code:
var zzz = (from a in studWithTuiDisc
join b in _conn.EEnrolledSubjects on a.StudentId equals b.StudentId
select new { please = a.StudentId, help = b.StudentId }).Distinct();
or
var zzz = (from a in studWithTuiDisc
from b in _conn.EEnrolledSubjects
where a.StudentId == b.StudentId
select new { please = a.StudentId, help = b.StudentId }).Distinct();
Output:
(source: secompeusc.com)
Given that we already know the values in studWithTuiDisc and since we used it as filter for _conn.EEnrolledSubjects we should be expecting results that are in studWithTuiDisc but looking at the screen shots, LINQ is not returning the proper results.
What am I doing wrong?
Has anyone experienced something like this before?
Does anyone know why this is happening?
Check what is generated/sent to SQL Server by using DataContext.Log, or SQL Profiler. I think that your queries will be different.
Related
My error is:
Could not find an implementation of the query pattern for source type
'System.Data.Entity.Database'. 'Select' not found.
My relevent code is:
DatabaseEntities db = new DatabaseEntities();
var whichUi = from UiType in db.Database
select AdvancedUi;
I am using the linq import (common answer on other threads).
I think your error is that you try to select something from .Database directly, not from the table. Instead of this code:
from UiType in db.Database
try out something like this:
from UiType in db.UiTypes
select UiType.AdvancedUi;
This should work as the table UiTypes will implemet the IEnumerable interface.
You should put your table name after the in keyword.
UiType is just a placeholder, and can be anything you want. Please, pay attention to the select clause - you must use the placeholder there, not the table name.
In my case, I resolved the error by changing:
var results = db.MyStoredProc().Select(x => x);
Or,
var results = from x in db.MyStoredProc()
select x;
To,
var results = db.MyStoredProc();
HTH.
The whole logic behind the query syntax/fluent syntax is to select an object as a whole or to select a property of an object.
Look at this following query:
var result = (from s in _ctx.ScannedDatas.AsQueryable()
where s.Data == scanData
select s.Id).FirstOrDefault();
Please note that after the where clause I am selecting only the Id property of the ScannedData object.
So to answer your question, if AdvancedUi is a property of UiTypes class then your query should be more like:
var result = from UiType in db.UiTypes
select UiType.AdvancedUi;
Alternatively if you want to return all data from a table say ScannedDatas, then your query will be:
var listResult = (from d in _ctx.ScannedDatas
select d).ToList();
Hope this answers your question my friend.
I have the following query
var listOfFollowers = (from a in db.UserLinks
where a.TargetUserID == TargetUserID && a.LinkStatusTypeID == 2
join b in db.UserNotifications on (int)a.OriginUserID equals b.TargetUserID
select b);
then I want to update once column on each row ( or object) returned
foreach (var a in listOfFollowers)
{
a.UserNotifications += HappeningID.ToString() + "|";
}
db.SubmitChanges();
The query seems to work , and when I put the generated SQL into SSMS it works fine , but when I run the entire code I get exception for trying to cast to int, don't make too much sense.
Is this ok , to do a query using a join , but only returning one table , change one property, then submitchanges?
The reason you are getting can't cast exception is that in the LINQ statement it is invalid to do cast. Other things which we can't do is to use regular method calls such as toString()
(int)a.OriginUserID is not allowed in
var listOfFollowers = (from a in db.UserLinks
where a.TargetUserID == TargetUserID && a.LinkStatusTypeID == 2
join b in db.UserNotifications on (int)a.OriginUserID equals b.TargetUserID
select b);
This problem will occur because parser tries to convert it into a equivalent SQL but doesn't find any equivalent. Other such cases are when you try to invoke toString(). Several Good responses here:
linq-to-entities-does-not-recognize-the-method
For your current scenario, I believe you have to
1. get the results from first query
2. cast the value
3. Make the second LINQ query
Hope this helps!
Most likely, problem occures in this piece of code (int)a.OriginUserID.
Try remove casting or use SqlFunctions.StringConvert() to compare strings.
I have a query which is fully translatable to SQL. For unknown reasons LINQ decides the last Select() to execute in .NET (not in the database), which causes to run a lot of additional SQL queries (per each item) against database.
Actually, I found a 'strange' way to force the full translation to SQL:
I have a query (this is a really simplified version, which still does not work as expected):
MainCategories.Select(e => new
{
PlacementId = e.CatalogPlacementId,
Translation = Translations.Select(t => new
{
Name = t.Name,
// ...
}).FirstOrDefault()
})
It will generates a lot of SQL queries:
SELECT [t0].[CatalogPlacementId] AS [PlacementId]
FROM [dbo].[MainCategories] AS [t0]
SELECT TOP (1) [t0].[Name]
FROM [dbo].[Translations] AS [t0]
SELECT TOP (1) [t0].[Name]
FROM [dbo].[Translations] AS [t0]
...
However, if I append another Select() which just copies all members:
.Select(e => new
{
PlacementId = e.PlacementId,
Translation = new
{
Name = e.Translation.Name,
// ...
}
})
It will compile it into a single SQL statement:
SELECT [t0].[CatalogPlacementId] AS [PlacementId], (
SELECT [t2].[Name]
FROM (
SELECT TOP (1) [t1].[Name]
FROM [dbo].[Translations] AS [t1]
) AS [t2]
) AS [Name]
FROM [dbo].[MainCategories] AS [t0]
Any clues why? How to force the LINQ to SQL to generate a single query more generically (without the second copying Select())?
NOTE: I've updated to query to make it really simple.
PS: Only, idea I get is to post-process/transform queries with similar patterns (to add the another Select()).
When you call SingleOrDefault in MyQuery, you are executing the query at that point which is loading the results into the client.
SingleOrDefault returns IEnumerable<T> which is no longer an IQueryable<T>. You have coerced it at this point which will do all further processing on the client - it can no longer perform SQL composition.
Not entirely sure what is going on, but I find the way you wrote this query pretty 'strange'. I would write it like this, and suspect this will work:
var q = from e in MainCategories
let t = Translations.Where(t => t.Name == "MainCategory"
&& t.RowKey == e.Id
&& t.Language.Code == "en-US").SingleOrDefault()
select new TranslatedEntity<Category>
{
Entity = e,
Translation = new TranslationDef
{
Language = t.Language.Code,
Name = t.Name,
Xml = t.Xml
}
};
I always try to separate the from part (selection of the datasources) from the select part (projection to your target type. I find it also easier to read/understand, and it generally also works better with most linq providers.
You can write the query as follows to get the desired result:
MainCategories.Select(e => new
{
PlacementId = e.CatalogPlacementId,
TranslationName = Translations.FirstOrDefault().Name,
})
As far as i'm aware, it's due to how LINQ projects the query. I think when it see's the nested Select, it will not project that into multiple sub-queries, as essentially that would be what would be needed, as IIRC you cannot use multiple return columns from a sub-query in SQL, so LINQ changes this to a query-per-row. FirstOrDefault with a column accessor seems to be a direct translation to what would happen in SQL and therefore LINQ-SQL knows it can write a sub-query.
The second Select must project the query similar to how I have written it above. It would be hard to confirm without digging into a reflector. Generally, if I need to select many columns, I would use a let statement like below:
from e in MainCategories
let translation = Translations.FirstOrDefault()
select new
{
PlacementId = e.CatalogPlacementId,
Translation = new {
translation.Name,
}
})
i want to select from 2 different objects in Linq in order to compare them. This is what i tried,
var myItem = (from abc in firstList.Value
from cds in secondList
where (abc.Key.theKey == cds.secondList.theSecondKey
select cds).SingleOrDefault();
although i get an error:
Type inference failed in the call to 'SelectMany'
If that's your exact query, it may just be because you've got unmatched brackets. Try this:
var myItem = (from abc in firstList.Value
from cds in secondList
where abc.Key.theKey == cds.secondList.theSecondKey
select cds).SingleOrDefault();
Admittedly I would probably rewrite that using a join - in most cases the join will be more efficient.
However, if that's not your exact query, please post a short but complete program which demonstrates the problem. It's not clear why cds would have a secondList property for example. A complete example demonstrating the problem would make this a lot simpler.
You have an opening paranthesis in more:
var myItem = (from abc in firstList.Value
from cds in secondList
where abc.Key.theKey == cds.secondList.theSecondKey
select cds
).SingleOrDefault();
var cityList = from country in
doc.Element("result")
.Element("cities")
.Descendants("city")
select new {
Name = country.Element("name").Value,
Code = country.Element("code").Value,
CountryCode = int.Parse(country
.Element("countrycode")
.Value)
};
foreach(var citee in cityList)
{
City city = new City();
city.CountryID = from cnt in db.Countries
where cnt.DOTWInternalID == citee.CountryCode
select cnt.ID;
}
I'm getting an error on the second query as seen in the title of this post. I tried converting to int to nullable int but nothing worked. Help me, guys.
Thanks
it will return an iQueryable, you will need to do something like using the First
cit.CountryID = db.Countries.First(a=>a.DOTWInternalID == citee.CountryCode).ID
It has elapsed a long time since the last update to the post but i think it's worth improving the solution.
In my opinion the solutions posted for this particular scenario are not the best way in terms of performace to get the ID you need. A better solution is as follows.
db.Countries.Where(a=>a.DOTWInternalID == citee.CountryCode)
.Select(a => a.ID).FirstOrDefault();
The previous statemants basically runs a SQL query similar to the following one:
SELECT TOP (1) ID
FROM [dbo].[Countries]
WHERE DOTWInternalID = 123
The proposed solutions work but basically do a "SELECT *" to create the entity with all the values and then obtain the ID from the object just created.
You can use Linqpad to actually see the generated SQL and tune up LINQ queries or Lambdas.
Hope it helps to some others that get to this post.
Here is the problem and solution
from cnt in db.Countries where cnt.DOTWInternalID == citee.CountryCode select cnt.ID part. If you omit the ID then it returns a Generic IEnumerable with Country(hoping that you have Country class). So what you have to do is first return the select criteria and select the first row then the ID field. Same like shown below.
cit.CountryID = (from cnt in db.Countries where cnt.DOTWInternalID == citee.CountryCode select cnt).First<Country>().ID;
This will solve your problem.
IQueryable is not a single int - but a query that can represent a collection.
As the error message says, your Linq query returns an System.Linq.IQueryable (for all intents and purposes a collection of ints). If you'd like to get one of them, you can either call First or ElementAt(n) to get the n'th element.
cit.CountryID = db.Countries.First(a=>a.DOTWInternalID == citee.CountryCode).ID