I have a following query
return _context.Table1
.Where(x => x.ContactId == contactKey.Id)
.Include(x => x.Table2)
.Include(x => x.Table3.Table4)
.Select(a =>
new MyReadModel
{
PriorityAssignment = true,
LastContactedDate = (a.Table3.Table4 != null && a.Table3.Table4.FirstOrDefault(h =>
h.Id == a.Table2.FkId
) != null ?
a.Table3.Table4.FirstOrDefault(h => && h.Id == a.Table2.FkId
).LastContactedDatetime : default
)
}
)
.ToListAsync();
What i wants is to simplify LastContactedDate assignment with in select. I think we can assign
a.Table3.Table4.FirstOrDefault(h =>
h.Id == a.Table2.FkId
)
to some variable but can't able to do it
can someone identify what is needed
With EF Core you don't have to check for null, LINQ Translator do not execute your code, but uses it for translation to the SQL. Also Includes is not needed if you do not retrieve whole objects.
return await _context.Table1
.Where(x => x.ContactId == contactKey.Id)
.Select(a => new MyReadModel
{
PriorityAssignment = true,
LastContactedDate = (DateTime?)a.Table3.Table4.Where(h => h.Id == a.Table2.FkId)
.OrderByDescending(h => LastContactedDatetime)
.Select(h => LastContactedDatetime)
.FirstOrDefault()
}).ToListAsync();
you can use it like this example
List<string> someList= new List<string>();
someList= someList.Select(x =>
{
var newVariable= "newVariable";
return newVariable;
}).ToList();
in your case
return _context.Table1
.Where(x => x.ContactId == contactKey.Id)
.Include(x => x.Table2)
.Include(x => x.Table3.Table4)
.Select(a => {
Table4 newVariable = null;
if(a.Table3.Table4 != null)
newVariable = a.Table3.Table4.FirstOrDefault(h => h.Id == a.Table2.FkId;
var result = new MyReadModel
{
PriorityAssignment = true,
LastContactedDate = (newVariable != null ? newVariable.LastContactedDatetime : default
)
};
}
) .ToListAsync();
I am getting this error for the query below
Unable to create a constant value of type API.Models.PersonProtocol. Only primitive types or enumeration types are supported in this context
ppCombined below is an IEnumerable object of PersonProtocolType, which is constructed by concat of 2 PersonProtocol lists.
Why is this failing? Can't we use LINQ JOIN clause inside of SELECT of a JOIN?
var persons = db.Favorites
.Where(x => x.userId == userId)
.Join(db.Person, x => x.personId, y => y.personId, (x, y) =>
new PersonDTO
{
personId = y.personId,
addressId = y.addressId,
favoriteId = x.favoriteId,
personProtocol = (ICollection<PersonProtocol>) ppCombined
.Where(a => a.personId == x.personId)
.Select( b => new PersonProtocol()
{
personProtocolId = b.personProtocolId,
activateDt = b.activateDt,
personId = b.personId
})
});
This cannot work because ppCombined is a collection of objects in memory and you cannot join a set of data in the database with another set of data that is in memory. You can try instead to extract the filtered items personProtocol of the ppCombined collection in memory after you have retrieved the other properties from the database:
var persons = db.Favorites
.Where(f => f.userId == userId)
.Join(db.Person, f => f.personId, p => p.personId, (f, p) =>
new // anonymous object
{
personId = p.personId,
addressId = p.addressId,
favoriteId = f.favoriteId,
})
.AsEnumerable() // database query ends here, the rest is a query in memory
.Select(x =>
new PersonDTO
{
personId = x.personId,
addressId = x.addressId,
favoriteId = x.favoriteId,
personProtocol = ppCombined
.Where(p => p.personId == x.personId)
.Select(p => new PersonProtocol
{
personProtocolId = p.personProtocolId,
activateDt = p.activateDt,
personId = p.personId
})
.ToList()
});
In my case, I was able to resolve the issue by doing the following:
I changed my code from this:
var r2 = db.Instances.Where(x => x.Player1 == inputViewModel.InstanceList.FirstOrDefault().Player2 && x.Player2 == inputViewModel.InstanceList.FirstOrDefault().Player1).ToList();
To this:
var p1 = inputViewModel.InstanceList.FirstOrDefault().Player1;
var p2 = inputViewModel.InstanceList.FirstOrDefault().Player2;
var r1 = db.Instances.Where(x => x.Player1 == p1 && x.Player2 == p2).ToList();
Don't know if anyone searches for this.
I had the same problem. A select on the query and then doing the where (or join) and using the select variable solved the problem for me.
(problem was in the collection "Reintegraties" for me)
query.Select(zv => new
{
zv,
rId = zv.this.Reintegraties.FirstOrDefault().Id
})
.Where(x => !db.Taken.Any(t => t.HoortBijEntiteitId == x.rId
&& t.HoortBijEntiteitType == EntiteitType.Reintegratie
&& t.Type == TaakType))
.Select(x => x.zv);
hope this helps anyone.
I had this issue and what I did and solved the problem was that I used AsEnumerable() just before my Join clause.
here is my query:
List<AccountViewModel> selectedAccounts;
using (ctx = SmallContext.GetInstance()) {
var data = ctx.Transactions.
Include(x => x.Source).
Include(x => x.Relation).
AsEnumerable().
Join(selectedAccounts, x => x.Source.Id, y => y.Id, (x, y) => x).
GroupBy(x => new { Id = x.Relation.Id, Name = x.Relation.Name }).
ToList();
}
I was wondering why this issue happens, and now I think It is because after you make a query via LINQ, the result will be in memory and not loaded into objects, I don't know what that state is but they are in in some transitional state I think. Then when you use AsEnumerable() or ToList(), etc, you are placing them into physical memory objects and the issue is resolving.
It's worth adding, since the OP's code sample doesn't provide enough context to prove otherwise, but I received this error as well on the following code:
public RetailSale GetByRefersToRetailSaleId(Int32 refersToRetailSaleId)
{
return GetQueryable()
.FirstOrDefault(x => x.RefersToRetailSaleId.Equals(refersToRetailSaleId));
}
Apparently, I cannot use Int32.Equals in this context to compare an Int32 with a primitive int; I had to (safely) change to this:
public RetailSale GetByRefersToRetailSaleId(Int32 refersToRetailSaleId)
{
return GetQueryable()
.FirstOrDefault(x => x.RefersToRetailSaleId == refersToRetailSaleId);
}
Just add AsEnumerable() andToList() , so it looks like this
db.Favorites
.Where(x => x.userId == userId)
.Join(db.Person, x => x.personId, y => y.personId, (x, y).ToList().AsEnumerable()
ToList().AsEnumerable()
I want to translate this into lambda syntax and can't seem to get it to work:
Grouping by two columns, select max on a different column, return list of complete complex object.
I am writing more text here to get past the validation on this form. How much text is needed until I am allowed to post this?
_clientpolicies = (from policy in
_reply.CommercialInsuredGroupWithPolicyTerm.InsuredWithPolicyTerm.SelectMany(x => x.PolicyTerm)
.Where(x => !(string.IsNullOrWhiteSpace(x.PolicyNumber) && string.IsNullOrWhiteSpace(x.ControlNumber)))
.Where(x => x.Insured.DNBAccountNumber == _client.LookupID)
group policy by
new
{
PolicyReference = GetPolicyReference(policy),
PolicyType = policy.ProductInformation.PolicyTypeCode
}
into g
let maxPolicyInception = g.Max(p => p.InceptionDate)
from policyGroup in g
where policyGroup.InceptionDate == maxPolicyInception
select policyGroup).ToList();
I dont think there's a way of doing it in one line. So there's my try :
policyGroups=
_reply.CommercialInsuredGroupWithPolicyTerm.InsuredWithPolicyTerm
.SelectMany(x => x.PolicyTerm)
.Where(x => !(string.IsNullOrWhiteSpace(x.PolicyNumber) && string.IsNullOrWhiteSpace(x.ControlNumber)))
.Where(x => x.Insured.DNBAccountNumber == _client.LookupID)
.GroupBy(x => GetPolicyReference(x))
.ThenBy(x => x.ProductInformation.PolicyTypeCode)
.ToList();
var maxPolicyInception = policyGroups.Max(p => p.InceptionDate);
_clientpolicies = policyGroups
.Where(g => g.InceptionDate == maxPolicyInception)
.ToList();
_clientpolicies =
_reply.CommercialInsuredGroupWithPolicyTerm.InsuredWithPolicyTerm.SelectMany(x => x.PolicyTerm)
.Where(x => !(string.IsNullOrWhiteSpace(x.PolicyNumber) && string.IsNullOrWhiteSpace(x.ControlNumber)))
.Where(x => x.Insured.DNBAccountNumber == _client.LookupID)
.GroupBy(x =>
new
{
PolicyReference = GetPolicyReference(x),
PolicyType = x.ProductInformation.PolicyTypeCode
},
(key, g) => g.OrderByDescending(gx => gx.InceptionDate).First()
This question already has answers here:
LINQ equal instead of Contains
(3 answers)
Closed 5 years ago.
I need to use Equals method or something similar instead of using Contains method because i want to search in database for the exact values in selectedDeviceTypeIDs array not any of it.
IEnumerable<Guid> selectedDeviceTypeIDs = DeviceTypeIDs
.Split(',')
.Select( Guid.Parse )
.AsEnumerable();
query = query
.Where( j =>
j.HospitalDepartments.Any( jj =>
jj.Units.Any( m =>
m.Devices.Any( w =>
selectedDeviceTypeIDs.Contains( w.DeviceTypeID )
)
)
)
);
Here is my full code
public HttpResponseMessage GetAvailableHospitalsByAjax(System.Guid? DirectorateOfHealthID = null, System.Guid? UnitTypeID = null, string DeviceTypeIDs = null)
{
Context db = new Context();
var query = db.Hospitals.AsQueryable();
if (DeviceTypeIDs != null)
{
IEnumerable<Guid> selectedDeviceTypeIDs = DeviceTypeIDs.Split(',').Select(Guid.Parse).AsEnumerable();
query = query.Where(j => j.HospitalDepartments.Any(jj => jj.Units.Any(m => m.Devices.Any(w => selectedDeviceTypeIDs.Contains(w.DeviceTypeID)))));
}
if (UnitTypeID != null)
{
query = query.Where(j => j.HospitalDepartments.Any(www => www.Units.Any(u => u.UnitTypeID == UnitTypeID)));
}
if (DirectorateOfHealthID != null)
{
query = query.Where(h => h.DirectorateHealthID == DirectorateOfHealthID);
}
query = query.Where(j => j.HospitalDepartments.Any(u => u.Units.Any(d => d.Devices.Any(s => s.Status == Enums.DeviceStatus.Free)))
&& j.HospitalDepartments.Any(hd => hd.Units.Any(u => u.Beds.Any(b => b.Status == Enums.BedStatus.Free))));
var list = query.ToList();
return Request.CreateResponse(HttpStatusCode.OK, list);
}
Your problem is not Contains() but with the Any() method used in your query which will return true immediately after it finds a device whose DeviceTypeID is in the provided selectedDeviceTypeIDs list.
If you need to check if all the devices of a unit match all the items in the list, you could use:
query = query
.Where(j =>
j.HospitalDepartments.Any(jj =>
jj.Units.Any(m =>
m.Devices.All(
w => selectedDeviceTypeIDs.Contains(w.DeviceTypeID))
&&
selectedDeviceTypeIDs.All(
g => m.Devices.Select(d => d.DeviceTypeID).Contains(g))
)
)
);
Note that if you have duplicate items in the selectedDeviceTypeIDs but not in the Devices of the Unit, it will still return true.
I've currently got a working multi level predicate shown below...
var predicate = PredicateBuilder.New<Patient>();
foreach (var code in codeArray) // ect..["AB12", "W231", "Q213"]
{
string localCode = code;
predicate.Or(p => p.Requests.Any(
u => u.Records.Any(
t => t.OutgoingRecords.Any(
s => s.Code == localCode)
)
)
);
}
res = query.AsExpandable().Where(predicate);
// Query is built up from an outside source and is eventually turned into a list via .ToListAsync()
Which is fine except as far as I'm aware it is producing a query in the form of...
query = p => p.PatientEpisodes.Any(u => u.EpisodeGroupings.Any(t => t.EpisodeDiagnoses.Any(s => s.Code == 'AB12'))) ||
p.PatientEpisodes.Any(u => u.EpisodeGroupings.Any(t => t.EpisodeDiagnoses.Any(s => s.Code == 'W231'))) ||
p.PatientEpisodes.Any(u => u.EpisodeGroupings.Any(t => t.EpisodeDiagnoses.Any(s => s.Code == 'Q213')))
Which is just overkill (and somewhat wrong) when all I really should be producing is...
query = p => p.PatientEpisodes.Any(u => u.EpisodeGroupings.Any(t => t.EpisodeDiagnoses.Any(s => s.Code == 'AB12' || s.Code == 'W312' || s.Code == 'Q213')))
Is there a way to insert the predicate at a sub level of a query such as below? My current attempts to do so have failed so far.
var predicate = PredicateBuilder.New<RecordCode>();
foreach (var code in codeArray)
{
string localCode = code;
predicate.Or(p => p.Code == localCode);
}
query = query.AsExpandable().Where(
s => s.Requests.Any(
c => c.Records.Any(
d => d.OutgoingRecords.Any(predicate))));
Many thanks in advance.