LinqToDB.LinqToDBException Expressionis not an association - c#

Hi All I am trying to do below ,I want to load an attribute value like this .
var date = db.GetTable<bbb>().Where(x => idList.Contains(x.MID))
.Select(x => x.ModifiedDate).FirstOrDefault;
var test = db.GetTable<nnn>().Where(x => xguy.Distinct().Contains(x.SID))
.LoadWith(x => x.Modified == lastPostDate);
exception:-
LinqToDB.LinqToDBException: 'Expression '(x.Modified == value(vv.x+<>c__DisplayClass25_1).lastPostDate)' is not an association.'
How can I do this?
I used the FirstOrDefault option to get one value, but I do not understand about Expression is not an association.

Your use of the "LoadWith" method is suspicious here.
LoadWith is a specialized function to load additional table data that is linked (e.g. via foreign key) to the current table row.
Based on your usage, it looks like you're just trying to set up another "Where" clause, so instead of
.LoadWith(x => x.Modified == lastPostDate);
you wanted
.Where(x => x.Modified == lastPostDate);
or alternatively, combine this with your prior Where statement to simplify things:
var test = db.GetTable<nnn>().Where(x => x.Modified == lastPostDate &&
xguy.Distinct().Contains(x.SID));
Let me know if this isn't what you intended. If this is the case, perhaps you have an SQL statement or similar that you are now trying to translate to C# LINQ, or can otherwise explain in plain English what this statement was meant to accomplish?

Related

LINQ/lambda: How can I query a DB table based on information from another table? (many to many relationship)

I have a database scheme with 3 tables. One for requisitions, one for hospitals, and one joining the two (many-to-many relationship).
I'd like to list all requisitions in the database that are linked to a selected hospital.
This is what I have so far:
var valgtSykehus = Db.Sykehus.Where(n => n.Navn == sykehus).Single(); //this gives me a variable with my current hospital. I want to list all requistions that contains this.
var Rekvisisjoner = Db.Rekvisisjoner
.Where(r => r.Arkivert == true) //get only archived requsitions
.Include(p1 => p1.Sykehus) //include hospitals
.ToList() //this generates a list of -all- requisitions with the hospitals they are attached to.
.Where(x => x.Created > DateTime.Now.AddYears(-3)) /only go 3 years back
.Where(x => x.Sykehus.Contains(valgtSykehus)); //here is the problem. I want to discard all requisitions that does NOT contain the hospital in the valgtSykehus variable
Anyway, this gives me zero requistions, but if I skip the last line, I get all archived requistions.
x.Sykehus.Contains(valgtSykehus) executes in LINQ to Objects context (due to the intermediate ToList call) and most likely uses reference equality, which normally should work as soon as you use tracking queries.
Still, it's safer and also more efficient to do the whole thing with a single db query using Any condition with primitive key. Something like this:
var Rekvisisjoner = Db.Rekvisisjoner
.Include(r => r.Sykehus) //include hospitals
.Where(r => r.Arkivert == true) //get only archived requsitions the hospitals they are attached to.
.Where(r => r.Created > DateTime.Now.AddYears(-3)) /only go 3 years back
.Where(r => r.Sykehus.Any(s => s.Navn == sykehus));
If there is an issues with using DateTime.Now.AddYears(-3) inside the query, just put into variable outside of the query and use it inside.
var minDate = DateTime.Now.AddYears(-3);
var Rekvisisjoner =
// ...
.Where(r => r.Created > minDate)
//...
The issue may lie in the implementation of Contains. Contains has to check equality somehow. Anyway, if your valgtSykehus object is logically contained in x.Sykehus (i.e. has the same data), but not exactly the same object (i.e. the same reference), it's possible that Contains fails to find it, due to the default implementation of == in reference types (== is true, if the objects are exactly the same reference, false otherwise, even though all the data is the same).
You could try the following:
var Rekvisisjoner = Db.Rekvisisjoner
.Where(r => r.Arkivert == true)
.Include(p1 => p1.Sykehus)
.ToList()
.Where(x => x.Created > DateTime.Now.AddYears(-3))
.Where(x => x.Sykehus.Any(sh => sh.Id == valgtSykehus.Id));
If Id (or whatever your ID property is named) is a value field (most likely) this will return true whenever the ID of an Sykehus matches the ID of valgtSykehus.
Oh my.
I just realised that none of the archived requisitions contains any connections to the hospitals, as they apparently are removed one-by-one when the requisition is processed in the program.
I figured this out while trying to reverse the query, so thanks for that tip.

Filter in linq with ID's in a List<int>

I need do a filter that request data with a parameter included in a list.
if (filter.Sc.Count > 0)
socios.Where(s => filter.Sc.Contains(s.ScID));
I try on this way but this not work, I tried also...
socios.Where( s => filter.Sc.All(f => f == s.ScID));
How I can do a filter like this?
socios.Where(s => filter.Sc.Contains(s.ScID));
returns a filtered query. It does not modify the query. You are ignoring the returned value. You need something like:
socios = socios.Where(s => filter.Sc.Contains(s.ScID));
but depending on the type of socios the exact syntax may be different.
In addition to needing to use the return value of your LINQ .Where(), you have a potential logic error in your second statement. The equivalent logic for a .Contains() is checking if Any of the elements pass the match criteria. In your case, the second statement would be
var filteredSocios = socios.Where( s => filter.Sc.Any(f => f == s.ScID));
Of course if you can compare object-to-object directly, the .Contains() is still adequate as long as you remember to use the return value.

How to get a single column with Entity Framework?

I have code to retrieve all columns from a entity class against a search criteria. But I want a specific column value instead of complete column values.
My code is -
Main main;
main = repo.Find<Main>(m => m.Code == criteria.code);
where Main is entity class, repo is repository and criteria is search criteria class. Now I want to get a specific column name, say id. How can I achieve this?
Assuming that Find is returning an IQueryable<T>, then you can use a projection:
repo.Find<Main>(m => m.Code == criteria.code).Select(m => m.Column);
var column =
from m in repo
where m.Code == criteria.code
select m.SomeColumn;
You do a query projection with the Select method:
repo.Mains.Where(m => m.Code == criteria.code).Select(m => m.Id);
On a related note, you should read Getting Started with Entity Framework. It'll give you a good idea of the query operators.

Linq to sql expression tree execution zone issue

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());

Navigate through entities in where clause

Im having some trouble writting a linq expression using entity framework. I have two related entities. Pago (payments) and Cuota(shares). In Cuota, I have the id_prestamo (loan id).
What I need is to get all the Pago(payments) for one Prestamo(loan). But as i have the Pago related only to Cuota, i have to get the id_prestamo from Cuota. The problem is that I cant navigate throw Cuota like this:
Lista_pagos = db.Pago.Where(x => x.Cuota.Prestamo.id_prestamo == prestamo.id_prestamo).ToList();
I tried also this expression but it doesnt work either:
Lista_pagos = db.Pago.Where(x => x.Cuota.Where(y => y.Prestamo.id_prestamo == prestamo.id_prestamo)).ToList();
When I say it doesn´t work is because I cannot compile the application. There must be an error in this place x.Cuota.Where(y => but don´t know how to use the where sentence right. I get this:
"The delegate does not take 1 argument"
Does anybody know how can i write this expression right?
I attach the entity relationship below.
Thanks!
You have a syntax error in your query.
db.Pago.Where()
...takes a predicate -- a function which returns bool.
x.Cuota.Where()
...returns IQueryable<Cuota>
So:
db.Pago.Where(x => x.Cuota.Where( ... ))
...is invalid code, because IQueryable<Cuota> is not bool.
I think what you actually want is:
Lista_pagos = db.Pago.Where(
x => x.Cuota.Any(y => y.Prestamo.id_prestamo == prestamo.id_prestamo)
).ToList();
(Note Any instead of Where.)
You have Cuotas for your Prestamos (by the way, Cuota is Installment, not Share, share is Acción) and you want all the Pagos for a given Prestamo:
Lista_Pagos = (from p in Pagos
join c in Cuotas
on p.Cuota.Cuota_Id equals c.Cuota_Id
where c.Prestamo.Prestamo_Id == prestamo.Prestamo_Id
select p).ToList<Pago>();

Categories

Resources