Unhandled exception. System.InvalidOperationException: The LINQ expression error by JsonConvert.Deserialize() - asp.net-core

I get an error from this code:
var b = content.FormMasterLists.Where(x => x.FormMasterStatus == "pending");
var c = b.Where(x => JsonConvert.DeserializeObject<ApprovalCCB>(x.FormMasterApprovalCcb).Group.SelectMany(x => x.Department).SelectMany(x => x.ApprovalCCBLevel).SelectMany(x => x.Approver).Where(x => x.ApproverEmail == "christ").Any());
But this code runs successfully:
var b = content.FormMasterLists.Where(x => x.FormMasterStatus == "pending").ToList();
var c = b.Where(x => JsonConvert.DeserializeObject<ApprovalCCB>(x.FormMasterApprovalCcb).Group.SelectMany(x => x.Department).SelectMany(x => x.ApprovalCCBLevel).SelectMany(x => x.Approver).Where(x => x.ApproverEmail == "christ").Any());
Is there any way to declare .Where without List()?

Is there any way to declare .Where without List()?
No way in such implementation. EF Core cannot convert JsonConvert.DeserializeObject to the SQL and provide needed filtering on the server side.
So you have to materialise objects to IEnumerable and use client side filtering.
Anyway some databases provide filtering based on JSON content but then you have to create appropriate extension function for EF Core.

Related

Elasticsearch Autocomplete Issues

I am trying to create an Autocompletion using Elasticsearch.net, but i keep getting an Invalid response.
But cant figure out why?
My Request looks like this
var descriptor = new SearchDescriptor<EmployeeDocument>()
.Index("employees").Type("employee").From(page - 1).Size(pageSize)
.Suggest(
s => s.Completion(
"my-completion-suggest",
c => c
.Field(f1 => f1.Description)
.Field(f1 => f1.empfirstname)
.Contexts(
queriesDescriptor => queriesDescriptor.Context(
"query-descriptor",
queryDescriptor => queryDescriptor.Prefix(true).Context(query)))));
var response3 = await this.client.SearchAsync<EmployeeDocument>(descriptor);
the error i am getting is
Invalid NEST response built from a unsuccessful low level call on POST: /employees/employee/_search
Audit trail of this API call:
- [1] BadResponse: Node: http://192.168.2.29:9200/ Took: 00:00:00.3543244
ServerError: ServerError: 400Type: search_phase_execution_exception Reason: "all shards failed"
This is how i am calling the method
var results1 = await service.SearchAsync("brenda", page, pageSize);
var results8 = await service.SearchAsync("something else", page, pageSize);
My model is also very straightforward. I left out some properties
[ElasticsearchType(Name = "employee")]
public class EmployeeDocument
{
//[Text(Name = "pkempid")]
public long pkempid { get; set; }
//[Text(Name = "empfirstname")]
public string empfirstname { get; set; }
}
Description and empfirstname need to be mapped as completion field data types. The CompletionField type in NEST can be used for the property type, which will be mapped as a completion data type through automapping.
Additionally, a completion suggester can only specify one field, so chaining multiple calls to .Field() will not work as expected (the last call will be the field used). You can however specify multiple suggesters in one request targeting different fields. It's more usual though, rather than having multiple completion fields in a mapping, to specify multiple input values to a single completion field.
The use case for the completion suggester is to provide fast "search as you type" autocompletion functionality, trading off the power of more complex analysis chains that can be performed with text field data types.
Ok, so I figured out how to do autocomplete, I ended up using Edge NGram Tokenizer First thing I needed to do was setup my indexes with the correct filters.
var response = this.client.CreateIndex(
ElasticConfig.IndexName,
index => index.Mappings(
ms => ms.Map<EmployeeDocument>(
m => m.Properties(
p => p
.Text(t => t.Name(n => n.EmpFirstName).Analyzer("auto-complete").Fields(ff => ff.Keyword(k => k.Name("keyword"))))
.Text(t => t.Name(n => n.pkEmpID).Analyzer("auto-complete-id").Fields(ff => ff.Keyword(k => k.Name("keyword"))))
.Text(t => t.Name(n => n.Description).Analyzer("auto-complete").Fields(ff => ff.Keyword(k => k.Name("keyword")))))))
.Settings(f => f.Analysis(
analysis => analysis
.Analyzers(
analyzers => analyzers
.Custom("auto-complete", a => a.Tokenizer("standard").Filters("lowercase", "auto-complete-filter"))
.Custom("auto-complete-id", a => a.Tokenizer("standard").Filters("lowercase", "auto-complete-id-filter")))
.TokenFilters(tokenFilter => tokenFilter
.EdgeNGram("auto-complete-filter", t => t.MinGram(3).MaxGram(5))
.EdgeNGram("auto-complete-id-filter", t => t.MinGram(1).MaxGram(5))))));
Then for the actual search
var response = await this.client.SearchAsync<EmployeeDocument>(
x => x.Index("default-index").Type("employee").From(page - 1).Size(pageSize)
.Query(q => q
.MultiMatch(m => m
.Query(query)
.Fields(f => f
.Field(_ => _.EmpFirstName)
.Field(_ => _.pkEmpID)
.Field(_ => _.Description))))
.Highlight(
h => h.PreTags("<mark>").PostTags("</mark>").Fields(
f => f.Field(p => p.EmpFirstName),
f => f.Field(p => p.pkEmpID),
f => f.Field(p => p.Description))));

Nhibernate Restrictions.In Error

Finally tracked down my error which is a result of the query. I have an nhibernate query using a Restrictions.In. Problem is once query executes if no results returned query throws error immediately. Is there another restriction that I can use. I know if I was writing a linq query I could use the .Any to return bool value and go from there is there something similar I can do in this instance?
carMake is passed in
myQuery.JoinQueryOver(x => x.Car)
.Where(Restrictions.In("VIN",
Trades.Where(x => x.Car.Make.ToLower() == carMake.ToLower())
.Select(x => x.Car.PrimaryVIN)
.ToList()));
Assuming that Trades is a list of objects you can use .WhereRestrictionOn() instead. Try this (I split the code for better readability):
var vinsWithCarMake = Trades
.Where(x => x.Car.Make.ToLower() == carMake.ToLower())
.Select(x => x.Car.PrimaryVIN)
.ToList<string>();
var carAlias = null;
var result = myQuery.JoinAlias(x => x.Car, () => carAlias)
.WhereRestrictionOn(() => carAlias.VIN).IsInG<string>(vinsWithCarMake)
.List();

NHibernate JoinQueryOver returns all subtype entries

I know there are many similar topics but I couldn't find the answer I am searching for.
I have Message with list of Receivers. I am trying to get all messages with state new and receivers of type A. I get all messages having corresponding receivers but with all of their receivers. I only want to get the receivers I am interested in.
Here is what I am trying to use:
var messages = session.QueryOver<MessageDTO>()
.Where(message => message.State == MessageState.New)
.JoinQueryOver<MessageReceiverDTO>(message => message.MessageReceivers)
.Where(receiver => receiver.Type == ReceiverType.A)
.TransformUsing(Transformers.DistinctRootEntity)
.List();
//.Where(message => message.MessageReceivers.Count > 0)
//.ToList();
Would be great to have help with that. I also tried using Select for getting message and receiver out of the query but that didn't work neither.
Try QueryOver with alias:
MessageDTO messageAlias = null;
MessageReceiverDTO receiverAlias = null;
var query =
session.QueryOver<MessageDTO>(() => messageAlias)
.JoinAlias(() => messageAlias.Receivers, () => receiverAlias)
.Where(() => messageAlias.State == MessageState.New)
.And(() => receiverAlias.Type == ReceiverType.A);
I think Transformers.AliasToEntityMap might be useful here. Basically it transforms each row in your resulting query to an IDictionary with keys corresponding to alias names and values corresponding to entities. For example:
MessageDTO message = null;
MessageReceiverDTO receiver = null;
var messages = session.QueryOver<MessageDTO>(() => messageAlias)
.Where(message => message.State == MessageState.New)
.JoinQueryOver<MessageReceiverDTO>(message => message.MessageReceivers, () => receiver)
.Where(receiver => receiver.Type == ReceiverType.A)
.TransformUsing(Transformers.AliasToEntityMap)
.List<IDictionary>();
MessageDTO firstMessage = (MessageDTO)messages[0]["message"];
MessageReceiverDTO firstReceiver = (MessageReceiverDTO)messages[0]["receiver"];

QueryOver fails with could not resolve property:

I am using NHibernate 3.0 and was comparing Query and QueryOver
var p = _prepo.Query<Party>()
.Where(c => c.Person.LastName == "Bobby")
.FirstOrDefault();
The above works, I get proxy class for p.Person if I view the object graph.
var p = _prepo.QueryOver<Party>()
.Where(c => c.Person.LastName == "Bobby")
.FirstOrDefault();
This one fails with error ==> could not resolve property: Person.LastName of:
Why?
I'm not familiar with the Linq provider but when using QueryOver you have to use a join to do a query like that:
Example 1
IQueryOver<Cat,Kitten> catQuery =
session.QueryOver<Cat>()
.JoinQueryOver(c => c.Kittens)
.Where(k => k.Name == "Tiddles");
Example 2
Cat catAlias = null;
Kitten kittenAlias = null;
IQueryOver<Cat,Cat> catQuery =
session.QueryOver<Cat>(() => catAlias)
.JoinAlias(() => catAlias.Kittens, () => kittenAlias)
.Where(() => catAlias.Age > 5)
.And(() => kittenAlias.Name == "Tiddles");
It works when you use Linq in this case because the filtering is being done on the client, not in the database. So it is actually the IEnumerable version of Where that is running which is not related to NHibernate.
The QueryOver uses Expression<Func<T,object>> which NHibernate tries to translate to SQL but fails. For reasons unknown to me you must explicitly join using JoinQueryOver or JoinAlias.
Some more info on QueryOver here:
http://nhibernate.info/blog/2009/12/17/queryover-in-nh-3-0.html

Nhibernate queryover with multiple join fail

I have a nhibernate queryover like this:
var query = Session.QueryOver<Immobile>()
.WhereRestrictionOn(i => i.Agenzia.CodiceAgenzia).IsLike(codiceAgenzia)
.WhereRestrictionOn(i => i.StatoImmobile.StatoImmobileId).IsLike(statoId)
.And(i => i.Prezzo <= prezzo)
.And(i => i.Mq <= metriquadri);
The code compile but on execute I receive this exception:
could not resolve property: Agenzia.CodiceAgenzia of: Domain.Model.Immobile
What am I doing wrong?
QueryOver syntax doesnt work that way unfortunately on Referenced objects you need to join them first and then add the restriction..
Change the code to as follows:
Azengia azengiaAlias=null; //Azengia here is typeof(Immobile.Azengia) I am assuming it is Azengia
StatoImmobile statoImmobileAlias=null; //similarly StatoImmobile is assumed to be typeof(Immobile.StatoImmobile)
var query=Session.QueryOver<Immobile>()
.Where(i => i.Prezzo <= prezzo && i.Mq <= metriquadri)
.Inner.JoinAlias(x=>x.Agenzia,()=>azengiaAlias)
.Inner.JoinAlias(x=>x.StatoImmobile,()=.statoImmobileAlias)
.WhereRestrictionOn(() => azengiaAlias.CodiceAgenzia).IsLike(codiceAgenzia)
.WhereRestrictionOn(() => statoImmobileAlias.StatoImmobileId).IsLike(statoId);
Hope this helps.