I have the following Linq to SQL query.
var users = rdc.Users.Where(u => u.EmailAddress.Equals(emailaddress) && password.Equals(hash));
But it always translates to:
SELECT [t0].[Id], [t0].[Guid], [t0].[RoleId], [t0].[EmailAddress], [t0].[Password], [t0].[FirstName], [t0].[LastName], [t0].[Created], [t0].[Activated], [t0].[LastAction]
FROM [dbo].[Users] AS [t0]
WHERE 0 = 1
I just re-imported the tables into my DBML file to insure that the latest schema is reflected, but it still removes my clause and adds WHERE 0 = 1
I can use ExecuteQuery<T>(string, params[]) but I want to find the root cause of this.
Are hash and password defined above this line? It looks like you might have forgetten to add the u. in your query. If password was already defined, then you wouldn't see an error, but it would never equal hash.
Did you mean to write:
var users = rdc.Users.Where(u => u.EmailAddress == emailaddress && u.Password == hash);
^^^
Also, #Mark pointed out that using the == operator will show errors that the .Equals operator might ignore.
For those, who also looking for solution, EF can set query filter on WHERE 0 = 1 in case if your subquery always returns empty result. Maybe this is some kind of optimisation.
So, look closely on your subquery. Some expression there always turns it to empty result.
Example:
return clientIds == null ? result : result.Where(r => ...);
Here, in subquery method return, if clientIds is List<T>, then expression will filter all results because list is always not null, even if it has no elements.
The correct way is like:
return clientIds?.Count < 1 ? result : result.Where(r => ...);
Related
I"m working on a WinfForms/C# software for automotive key management that's has a SQL query thats searchs in the table like that:
DataAdapter = SetAdapter($"SELECT * FROM keylist WHERE MANUFACTOR LIKE #manufactor AND KEYTYPE LIKE #type AND SERVICETYPE LIKE #service AND USER_ID = #_user");
So in the begginig I used to use the query directly in the search function but as the project grew, it ended up leaving it without performance, because the query was called directly on the remote server. So I decided to move everything to a list in C # and do the search with lambdas functions.
This is the function with lambda expression:
public List<Key> SearchFilter(string manufactor, string type, string service)
{
return _keys.Where(key => key.Manufactor == manufactor
&& key.Type == type
&& key.ServiceType == service).ToList();
}
The problem is:
In the SQL syntax, when you leave one or more fields, it automatically ignores and checks for the other, but when I use Where <> in the LINQ for example, it ends up returning null or items that do not satisfy conditions and returning other objects.
When I leave one or two of the parameters null, it returns no value. By the way, if I use || instead of && it returns undesirable values.
Is there a way to check if the condition is null and skip to the next clause and return only the values that were passed?
if I understand correctly, I think I should make several "Where" conditions, one for each condition, that is:
return _keys.Where(key => manufactor != string.Empty ? key.Manufactor == manufactor ? key.Manufactor != string.Empty)
.Where(key => key.Type == type)
.Where(key => key.ServiceType == service)
.ToList();
You can also "exclude" or "include" filters if there is value to filter as I did with "key.Manufactor".
I'm trying to select from CRM entity with "contains" key.
I tryed this:
var results = crm.new_supplycontractSet
.Where(x => x.new_city != null &&
x.new_city.Name.Contains("myChars"))
.ToList();
but it give me this error:
Invalid 'where' condition. An entity member is invoking an invalid property or method.
and this:
var result = (
from c in crm.new_supplycontractSet
from a in crm.new_comuneSet
where a.new_name.Contains(comune)
where c.new_city.Id == a.Id
select c)
.ToList();
But i can't figure out how to do it. The second try gives me this error:
A 'SelectMany' operation must be preceeded by a 'Where' operation that filters by an entity ID.
How can I select by a contains filter? "x.new_city" is an entity ref from crm.new_comuneSet.
PS:
I've just read something about the inaccessibility of the "entity.entityRef.Name.Contains()" because the "Name" property is not ground level and so it's not available for the ".contains" check.
At the end i got it. instead of contains clause, I had to install SqlClient and use the following:
results = (from x in crm.new_supplycontractSet
where x.new_city != null
where x.new_address != null
where SqlMethods.Like(x.new_city.Name, "city")
where SqlMethods.Like(x.new_address.Name, "street")
select ....).ToList();
hope this will help someone else :)
you can try converting your field and your filter to lower or upper case.
var results = crm.new_supplycontractSet
.Where(x => x.new_city != null &&
x.new_city.Name.ToLower().Contains(("myChars").ToLower()))
.ToList();
I think is better if you use StartsWith instead (and if is possible).
Take this:
int? item1 = null;
int? item2 = null;
someObjectList.Where(x => x.SomeItem1 == (item1 ?? x.SomeItem1)
&& x.SomeItem2 == (item2 ?? x.SomeItem2)
);
Where someObjectList is not empty and SomeItem1 and SomeItem2 is null in all the objects in the list.
Why is it returning nothing?
EDIT:
My Code:
public void GetPlacementsByMaterial(long clientMaterialID)
{
ClientMaterial clientMaterial = ((ApplicationEntityModel)NavigationItem.ObjectContext).ClientMaterial.FirstOrDefault(x => x.ClientMaterialID == clientMaterialID);
var list = GetPlacementList(supplier, mediaSpace);
PlacementsList = list.Where(x => x.MediaCategoryFormatID == (clientMaterial.MediaCategoryFormatID ?? x.MediaCategoryFormatID)
&& x.MediaCategorySizeID == (clientMaterial.MediaCategorySizeID ?? x.MediaCategorySizeID)
);
}
All ID's are Nullable<long>.
EDIT:
SQL Profiler:
SELECT *
FROM [dbo].[CampaignSchedulePlacements] AS [Extent5]
WHERE ([Extent5].[MediaCategoryFormatID] = [Extent5].[MediaCategoryFormatID]) AND ([Extent5].[MediaCategorySizeID] = [Extent5].[MediaCategorySizeID])
Note: cleaned up the `SQL.
In SQL, NULL is not equal to NULL.
You can interpret NULL as meaning: "there is value, but I don't know what it is". So if you're comparing two NULL values, you're really asking "is the first unknown value equal to the second unknown value?" Of course, there is no reason to assume they are, so SQL will say "no".
I am assuming that this is causing your problem. You can verify that by looking at the actual SQL produced. If it's using the SQL = operator, this is indeed the problem. You can verify that by running the SQL in a database tool, such as SQL Management Studio in case you're using SQL Server.
UPDATE:
The condition
([Extent5].[MediaCategoryFormatID] = [Extent5].[MediaCategoryFormatID])
will indeed return false when [Extent5].[MediaCategoryFormatID] is NULL.
That answers the question "Why is it returning nothing?"
However, another question come to mind: why would the entity framework generate that SQL from this linq query?
I'm afraid that linq to entities is not exactly known for the quality of its SQL generation, and this case seems to confirm that. You might consider Linq to SQL. Even if that seems to be a dead-end track in the long run, the current implementation if a lot better than linq to entities.
In either case, have you tried something like
someObjectList.Where(x =>
!item1.hasValue ||
x.SomeItem1.HasValue && x.SomeItem1.Value == item1.Value)
Make sure to verify that under the profiler as well though, linq to entities might mess it up too.
I want to query my item in table Items, where the last update of each item must be less than 91 days old (from last update till now) and the quantity > 0.
This is my code in the Model:
public IList<Item> GetAllProducts()
{
var ien_item = from i in this.DataContext.Items
orderby i.LastUpdated descending
select i;
return ien_item.ToList().Where(
s =>
HelperClasses.HelperClass.IsLastUpdate(s.LastUpdated.Value) == true
&&
(s => s.Quantity) > 0
)
.ToList();
}
Anyone can solve it? Thanks.
We don't really know what's not working here. EDIT: Merlyn spotted it; your lambda syntax is messed up. There's more to do here though.
However, I'd have thought you'd want this:
public IList<Item> GetAllProducts()
{
var lastUpdateLimit = DateTime.UtcNow.Date.AddDays(-91);
var query = from item in DataContext.Items
where item.Quantity > 0 && item.LastUpdated >= lastUpdateLimit
orderby item.LastUpdated descending
select item;
return query.ToList();
}
Note that this is able to do all the querying at the database side instead of fetching all the items and filtering at the client side. It does assume that HelperClasses.HelperClass.IsLastUpdate is simple though, and basically equivalent to the filter I've got above.
(One additional point to note is that by evaluating UtcNow.Date once, the result will be consistent for all items - whereas if your code evaluates "today" on every call to IsLastUpdate, some values in the query may end up being filtered against a different date to other values, due to time progressing while the query is evaluating.)
EDIT: If you really need to use HelperClasses.HelperClass.IsLastUpdate then I'd suggest:
public IList<Item> GetAllProducts()
{
var query = from item in DataContext.Items
where item.Quantity > 0
orderby item.LastUpdated descending
select item;
return query.AsEnumerable()
.Where(s => HelperClass.IsLastUpdate(s.LastUpdated.Value))
.ToList();
}
... then at least the quantity filter is performed at the database side, and you're not creating a complete buffered list before you need to (note the single call to ToList).
The problem is your lambda syntax. You're trying to define a second lambda while in the middle of defining a first lambda. While this is possible to do, and useful in some contexts, it is sort of an advanced scenario, and probably won't be useful to you until you know you need it.
Right now, you don't need it. Unless you know you need it, you don't need it :)
So -
Instead of what you've written:
.Where(
s =>
HelperClasses.HelperClass.IsLastUpdate(s.LastUpdated.Value) == true
&& (s => s.Quantity) > 0
)
Write this instead:
.Where(
s =>
HelperClasses.HelperClass.IsLastUpdate(s.LastUpdated.Value) == true
&& s.Quantity > 0 // Notice I got rid of the extra lambda here
)
If you're morbidly curious:
The compile error you got is because you didn't define your second lambda correctly. It redefined a variable you'd already used (s), and you were trying to check if a lambda was greater than zero. That makes no sense. You can only compare the result of a lambda to some value. It's like calling a function. You don't compare functions to numbers - you compare the result you get when calling a function to a number.
Easy ...
public IList<Item> GetAllProducts()
{
var ien_item =
from i in DataContext.Items
where
HelperClasses.HelperClass.IsLastUpdate(i.LastUpdated.Value)
&& s.Quantity > 0
orderby i.LastUpdated descending
select i;
return ien_item.ToList();
}
Linq to SQL: Methods are not allowed (linq is not magic and can not convert C# methods to TSQL)
http://msdn.microsoft.com/en-us/library/bb425822.aspx
Linq to Object: while looking the same, it is much more powerful than linq to SQL... but can not query SQL databases :)
http://msdn.microsoft.com/en-us/library/bb397919.aspx
Linq to XML: same as linq to Object, with xml object
http://msdn.microsoft.com/en-us/library/bb387098.aspx
Linq to Dataset: not the same as Linq to SQL !
http://msdn.microsoft.com/en-us/library/bb386977.aspx
Other linq providers:
http://en.wikipedia.org/wiki/Language_Integrated_Query
The LINQ-to-SQL query in Visual Studio generates an SQL query with errors. In LINQPad, the same LINQ query using the same database (or DataContext) runs just fine.
LINQ Query
var accesDomaines = from t in db.Access
where t.IdUser == access.IdUtilisateur
where t.IdDomain != null
where t.IdRole == access.IdRole
where t.IdPlace == access.IdPlace
select t;
Here's a small part of generated SQL where the error occurs:
WHERE (...) AND ([t3].[IdRole] = ) AND (...)
After the equals in where clause, there's literally nothing ! In the SQL query of LINQPad we see the good where clause:
WHERE (...) AND ([t3].[IdRole] IS NULL) AND (...)
When I compare the two generated SQL queries from VS and LINQPad, line by line, this is the same thing. Except LINQPad is using params and also the missing right part of equal in where clause of Visual Studio, as shown before.
Note 1
In the LINQ query, I tried with this syntax in where clauses:
where t.IdRole.Equals(acces.IdRole.Value)
But also generates a bad result. I even tried something like this before the LINQ query:
if (!acces.IdRole.HasValue) { acces.IdRole = null; }
Note 2
Properties are nullable integers. I do want null in query if property is null. Obviously, I want the value of property if there's a value.
Note 3
I have tried the proposition made in this question: Linq where column == (null reference) not the same as column == null
...with no success.
Any explanation of two similar LINQ queries, but generating a good and a bad SQL query? Any suggestion to solve this problem?
Thank you!
try this:
where object.Equals(t.IdRole, access.IdRole)
Use
object.Equals()
.Net would take care of generating correct sql for null condition.
Example:
Say you have a street table with columns like Suffix and Prefix. Then following linq query doesn't work:
string suffix = "ST";
string prefix = null;
var map = from s in Streets
where s.Suffix==suffix || s.Prefix==prefix
select s;
It would generate following sql:
SELECT [t0].[StreetId], [t0].[Prefix], [t0].[Suffix]
FROM [Street] AS [t0]
WHERE ([t0].[Suffix] = #p0) AND ([t0].[Prefix] = #p1)
we can clearly see it will not return any result.
Using object.Equals():
string suffix = "ST";
string prefix = null;
var map = from s in Streets
where object.Equals(s.Suffix, suffix) && object.Equals(s.Prefix,prefix)
select s;
would generate sql:
SELECT [t0].[StreetId], [t0].[Prefix], [t0].[Suffix]
FROM [Street] AS [t0]
WHERE ([t0].[Suffix] IS NOT NULL) AND ([t0].[Suffix] = #p0)
AND ([t0].[Prefix] IS NULL)
Which is correct one.
(Little late, but wanted to expand the answer for the benefit of others)
Have you tried verifying whether your properties had values with the HasValues property provided by the Nullables?
where t.IdRole == access.IdRole.HasValues ? access.IdRole.Value : null
Perhaps this could work. I haven't used LINQ-to-SQL really.
This example worked for me:
var aff3 = from a in context.Affiliates
where ((name == null && a.CompanyName == null) || (a.CompanyName == name))
select a.ID;