In my project, I need to return a list of car data that does not match the model Id' provided in the array. I'm unsure on how I would go in getting my query to work. So far i have the following below:
var IdList = new List<int> { 60,61,62, 63, 64, 65 };
var query = Context.ManufacturersTable.Where(m => m.Date == date && m.CountryToship = country && m.ExportOnly == false);
if(query.Count() > 0)
query = query.Where(x => x.CarMoreInfoTable.CarModelTable.Where(f => IdList.Contains(f.ModelId))) //Cannot convert lambda expression to intended delegate type error here
return query
As you can see in the above query I have 3 tables all linked to each other. But please could some direct me on how I would query all data that does not contain the Id's in the given array?
Thank you
You have an error because second 'Where' is the issue here, first Where expects to delegate method return bool instead of IEnumerable. (Comment edit) And I think you have to negate:
IdList.Contains(f.ModelId)
Edit
If you need Car Data (I will assume that it is inside CarModel class) then you need change first Where to SelectMany (we would like to merge many collections into one) and negate the inner expression (with contains).
var result = query
.SelectMany(x => x.CarMoreInfoTable.CarModelTable
.Where(f => !IdList.Contains(f.ModelId))).ToList();
Related
I'm testing a simple LINQ select query and want to get two DateTime values from the table, but I'm doing something wrong here and need to know what I'm doing/thinking wrong?
My query:
var test = from x in db.Projects where x.ID == 1 select x;
Then I try to get on of the values like this:
DateTime Date = test. ?????
Here I thought I should get a suggestion from the Intellisense after the dot to pick the value from the column StartDate the table, but this isn't working.
If you need multiple matches...
Are you sure that you have multiple Project objects that have the same ID of 1 which your query currently suggests? If that is the case, then your query should return all of the records that meet that constraint via the Where() method :
// Get your Projects that meet your criteria
var test = db.Projects.Where(p => p.ID == 1);
If you need to access properties from these elements, you could either loop through them explicitly :
// Iterate through each match that was found
foreach(var t in test)
{
// Access your properties here
DateTime dt = t.YourDateProperty;
}
Or you could accomplish this using a Select() statement to only pull the properties that you need :
// This will return a collection of Dates mapped from each element in your collection
var testDates = db.Projects.Where(p => p.ID == 1)
.Select(x => x.YourDateProperty);
If you only need a single match...
If you only need to match a single element within your collection, you might consider using the First(), Single() or their equivalent FirstOrDefault() and SingleOrDefault() methods, which will return a single entity that you can use as expected :
// This will return the first Project with an ID of 1
var test = db.Project.FirstOrDefault(p => p.ID == 1);
// If it was successful
if(test != null)
{
// Then you can safely access it here
DateTime dt = test.YourDateProperty;
}
The only difference between the methods mentioned (normal vs OrDefault()) is that the OrDefault() methods will return null if no matching elements are found, so they generally require a null check as seen above.
test is going to be an enumeration (IEnumerable<>, IQueryable<>, etc... many are applicable) of your Project type. So if, for example, you want the first record, you might do this:
DateTime Date = test.First().SomeDateProperty;
All of the data returned from your query is in test. It could be zero records, one record, many records, etc.
In test you will have a collection which matches the condition x.ID == 1. You should iterate through that collection and take your needed properties.
Edit
I suggest you to use the syntax:
var result = db.Projects.FirstOrDefault(x => x.ID ==1);
this is such as:
var date = test.FirstOrDefault();
DateTime? Date = date != null ? date.StartDate : null;
Trying to work out this lambda query without doing a foreach etc. I currently have a database table with a column which contains a comma separated list of strings. It's basically a filter (it could for example be 'pants,tops,t-shirts,gloves'). In the function that queries the database is basically has a parameter that accepts a similar string.
I don't know if I'm just too tired at the moment and can't work it out but struggling. I know it will be Intersect but can't figure out the syntax.
Currently I have...
public static List<ItemListItem> GetItems(string filter = "")
{
var db = new dbConnection();
var results = (from i in db.Items
select i);
if (!string.IsNullOrEmpty (filter))
results = results.Where(x => x.Filters.Split(',').Intersect(filter.Split(',')) )
}
You need Enumerable.Any at the end of your Intersect like:
x.Filters.Split(',').Intersect(filter.Split(',')).Any()
So your query would be:
results = results.Where(x => x.Filters.Split(',')
.Intersect(filter.Split(','))
.Any());
Enumerable.Where would require an expression returning bool. Intersect would return an IEnumerable<T> and Enumerable.Where would not accept it. Adding Enumerable.Any would means return those rows where intersection resulted in Any row.
Is it possible within Linq in C#, to convert a string field in a database, to a long type - and use it in the query?
Here, tme is a unix time (long) - but the field in the database, targetdate - is a string.
I've tried:
var qbt = db.Calls
.Where(x => x.team == id && long.Parse(x.targetdate) <= tme);
However I get the message: LINQ to Entities does not recognize the method 'Int64 Parse(System.String)' method, and this method cannot be translated into a store expression.
I know you can convert before the linq query, but is there any way of using it WITHIN the linq query?
Thanks for any help,
Mark
try
var qbt = db.Calls.ToList()
.Where(x => x.team == id && long.Parse(x.targetdate) <= tme);
if you have many records you can limit them by team first and then call ToList like below
var qbt = db.Calls.Where(x => x.team == id).ToList()
.Where(i=>long.Parse(i.targetdate) <= tme);
Or You can use AsEnumerable
var qbt = db.Calls.AsEnumerable()
.Where(x => x.team == id && long.Parse(x.targetdate) <= tme);
This is to do with the way the Linq is translated into the backing query language, it might be easier to do a string comparison in this case, using tme.ToString(). If you pull the full collection down first, you could query like this but that means what it says: pulling down the full unfiltered (or at least less filtered) set.
You have to either change the database table to not store a string (you could create a computed column that converts it to a long or create a view if you cannot modify the existing table) or compare the value as string. The reason is that Entity Framework LINQ provider does not understand long.Parse and there is no method in SqlFunctions class for this purpose.
var stringTme = tme.ToString(CultureInfo.InvariantCulture);
var qbt = db.Calls
.Where(x => x.team == id && ((x.targetdate.Length < stringTme.Length)
|| (x.targetdate.Length == stringTme.Length && x.targetdate <= stringTme)));
You have to either change the database table to not store a string or compare the value as string. The reason is that Entity Framework LINQ provider does not understand long.Parse and there is no method in SqlFunctions class for this purpose.please use long.Parse()
I have got a bit of an issue and was wondering if there is a way to have my cake and eat it.
Currently I have a Repository and Query style pattern for how I am using Linq2Sql, however I have got one issue and I cannot see a nice way to solve it. Here is an example of the problem:
var someDataMapper = new SomeDataMapper();
var someDataQuery = new GetSomeDataQuery();
var results = SomeRepository.HybridQuery(someDataQuery)
.Where(x => x.SomeColumn == 1 || x.SomeColumn == 2)
.OrderByDescending(x => x.SomeOtherColumn)
.Select(x => someDataMapper.Map(x));
return results.Where(x => x.SomeMappedColumn == "SomeType");
The main bits to pay attention to here are Mapper, Query, Repository and then the final where clause. I am doing this as part of a larger refactor, and we found that there were ALOT of similar queries which were getting slightly different result sets back but then mapping them the same way to a domain specific model. So take for example getting back a tbl_car and then mapping it to a Car object. So a mapper basically takes one type and spits out another, so exactly the same as what would normally happen in the select:
// Non mapped version
select(x => new Car
{
Id = x.Id,
Name = x.Name,
Owner = x.FirstName + x.Surname
});
// Mapped version
select(x => carMapper.Map(x));
So the car mapper is more re-usable on all areas which do similar queries returning same end results but doing different bits along the way. However I keep getting the error saying that Map is not able to be converted to SQL, which is fine as I dont want it to be, however I understand that as it is in an expression tree it would try to convert it.
{"Method 'SomeData Map(SomeTable)' has no supported translation to SQL."}
Finally the object that is returned and mapped is passed further up the stack for other objects to use, which make use of Linq to SQL's composition abilities to add additional criteria to the query then finally ToList() or itterate on the data returned, however they filter based on the mapped model, not the original table model, which I believe is perfectly fine as answered in a previous question:
Linq2Sql point of retrieving data
So to sum it up, can I use my mapping pattern as shown without it trying to convert that single part to SQL?
Yes, you can. Put AsEnumerable() before the last Select:
var results = SomeRepository.HybridQuery(someDataQuery)
.Where(x => x.SomeColumn == 1 || x.SomeColumn == 2)
.OrderByDescending(x => x.SomeOtherColumn)
.AsEnumerable()
.Select(x => someDataMapper.Map(x));
Please note, however, that the second Where - the one that operates on SomeMappedColumn - will now be executed in memory and not by the database. If this last where clause significantly reduces the result set this could be a problem.
An alternate approach would be to create a method that returns the expression tree of that mapping. Something like the following should work, as long as everything happening in the mapping is convertible to SQL.
Expression<Func<EntityType, Car>> GetCarMappingExpression()
{
return new Expression<Func<EntityType, Car>>(x => new Car
{
Id = x.Id,
Name = x.Name,
Owner = x.FirstName + x.Surname
});
}
Usage would be like this:
var results = SomeRepository.HybridQuery(someDataQuery)
.Where(x => x.SomeColumn == 1 || x.SomeColumn == 2)
.OrderByDescending(x => x.SomeOtherColumn)
.Select(GetCarMappingExpression());
Consider this line of code:
List<SIDB_TransactionInformation> transaction = SIDB.SIDB_TransactionInformations
.Where(k => k.iscurrent == true & k.objectid == SIDB.func_GetObjectID("dbo.SIDB_Module")).ToList();
List<SIDB_Module> module = SIDB.SIDB_Modules
.Where(k => k.moduleid == transaction
.Where(j => j.transactionid == k.moduleid)
.SingleOrDefault().transactionid).ToList();
I do have 2 invocation of where method in different collection. First i distinct my list via iscurrent and objectid after that I do have other invocation of where method (for SIDB_Modules) to distinct the list via moduleid where in the the values refer to the transactionid of my previous list. Now i have an error message like this Local sequence cannot be used in LINQ to SQL implementation of query operators except the Contains() operator.
sorry i'm new in lambda expression. need help badly
I think this is what you're looking for
List<SIDB_Module> module = SIDB
.SIDB_Modules
.Where(k => transaction.Any(j => j.transactionid == k.moduleid))
.ToList();
Make a list of SIDB_Modules where there is a transaction whose transactionid is equal to the moduleid. LINQ to Sql might have an issue with Any, I don't remember, if it does you can rewrite it with an extra step like this
var transactionIds = transaction.Select(j => j.transactionid);
List<SIDB_Module> module = SIDB
.SIDB_Modules
.Where(k => transactionIds.Contains(k.moduleid))
.ToList();
If performance is an issue you might consider going with the second method and putting transactionIds into something that implements ISet<T> and has a constant time lookup.
Well, it looks like you're trying to do a join between SIDB_TransactionInformations and SIDB.SIDB_Modules. If so, try
var objectID = SIDB.func_GetObjectID("dbo.SIDB_Module");
List<SIDB_Module> modules = (from module in SIDB.SIDB_Modules
join transaction in SIDB.SIDB_TransactionInformations on module.moduleid equals transaction.transactionid
where transaction.iscurrent && transaction.objectid == objectID
select module).ToList();