Base solution for your next web application
Open Closed

ObjectMapper.Map error - variable '' of type '' referenced from scope '', but it is not defined #8942


User avatar
0
thinkn.tech created

HI,

We have encounter some issue on objectMapper after we have upgraded to .Net Core 3.1. Is there any workaround / solution?

Below is our code:

Message: variable 'TravellerList' of type 'System.Collections.Generic.IEnumerable`1[ThinknInsurTech.Quote.Quote_Policy_TravelTraveller]' referenced from scope '', but it is not defined

Error Stack: at System.Linq.Expressions.Compiler.VariableBinder.Reference(ParameterExpression node, VariableStorageKind storage) at System.Linq.Expressions.Compiler.VariableBinder.VisitParameter(ParameterExpression node) at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes) at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node) at System.Linq.Expressions.ExpressionVisitor.VisitMemberAssignment(MemberAssignment node) at System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding node) at System.Linq.Expressions.ExpressionVisitor.Visit[T](ReadOnlyCollection1 nodes, Func2 elementVisitor) at System.Linq.Expressions.ExpressionVisitor.VisitMemberInit(MemberInitExpression node) at System.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor visitor) at System.Linq.Expressions.ExpressionVisitor.Visit(ReadOnlyCollection1 nodes) at System.Linq.Expressions.Compiler.VariableBinder.VisitLambda[T](Expression1 node) at System.Linq.Expressions.Compiler.LambdaCompiler.Compile(LambdaExpression lambda) at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.VisitShapedQueryExpression(ShapedQueryExpression shapedQueryExpression) at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.VisitExtension(Expression extensionExpression) at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query) at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass9_01.&lt;Execute&gt;b__0() at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func1 compiler) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query) at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1.GetEnumerator() at System.Collections.Generic.LargeArrayBuilder1.AddRange(IEnumerable1 items) at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable1 source) at System.Linq.SystemCore_EnumerableDebugView`1.get_Items()

If we change "ObjectMapper.Map<List<QuotePolicyTravelTraveller>>(TravellerList.ToList())"

We got following error

Unable to cast object of type 'System.Linq.Expressions.TypedParameterExpression' to type 'Microsoft.EntityFrameworkCore.Query.ShapedQueryExpression'.


18 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team

    hi

    Can you share the full code?

  • User Avatar
    0
    thinkn.tech created
    
    private IQueryable<TravelExceptionListingOutput> TravelExceptionListingQuery(GetTravelExceptionListingInput input)
            {
                List<string> exceptionErrorCode = new List<string>() { "000", "003", "004", "008" };
    
                var query = (from quotepolicy in _quotePolicyRepository.GetAll().Where(p => p.StatusId.Equals(2))
                             join quotepolicytravel in _quotePolicyTravelRepository.GetAll().Where(p => !exceptionErrorCode.Contains(p.ePolicyRespCode)) on quotepolicy.Id equals quotepolicytravel.QuotePolicyId
                             join quotepolicypayment in _quotePolicyPaymentRepository.GetAll().Where(p => p.PaymentStatus == Convert.ToString((byte)PaymentStatus.Success)) on quotepolicy.Id equals quotepolicypayment.QuotePolicyId
                             join quotepolicytraveltraveller in _quotePolicyTravelTravellerRepository.GetAll().Where(x => x.IsPolicyHolder == true) on quotepolicy.Id equals quotepolicytraveltraveller.QuotePolicyId into TravellerList
                             from quotepolicytraveltraveller in TravellerList.DefaultIfEmpty()
                             where ((input.ReferenceNo.IsNullOrWhiteSpace() || quotepolicy.ReferenceNo.Equals(input.ReferenceNo)) &&
                                 ((input.PolicyStartDate.IsNullOrWhiteSpace()
                                  || (quotepolicy.CreationTime.Date >= DateTime.Parse(input.PolicyStartDate).Date && quotepolicy.CreationTime.Date <= DateTime.Parse(input.PolicyEndDate).Date)
                                 )))
    
                             select new TravelExceptionListingOutput
                             {
                                 QuotePolicyId = quotepolicy.Id,
                                 QuotePolicy = ObjectMapper.Map<Dto.QuotePolicy>(quotepolicy),
                                 QuotePolicyTravel = ObjectMapper.Map<QuotePolicyTravel>(quotepolicytravel),
                                 QuotePolicyTravelTraveller = null, //ObjectMapper.Map<List<QuotePolicyTravelTraveller>>(TravellerList.ToList()),
                                 QuotePolicyPayment = ObjectMapper.Map<QuotePolicyPayment>(quotepolicypayment),
                                 ResponseCode = quotepolicytravel.ePolicyRespCode,
                                 ResponseMessage = quotepolicytravel.ePolicyIntMessage + " " + quotepolicytravel.ePolicyRespMessage
                             });
    
                return query;
            }
            
            ```
    
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @thinkn.tech,

    I think this code is generated by AspNet Zero Power Tools. Latest version of Power Tools doesn't create such mapping anymore because of EF Core 3.1 breaking changes. You can create a test entity, see the newly generated code and modify your existing code accordingly.

  • User Avatar
    0
    thinkn.tech created

    Hi @ismcagdas,

    We actually don't use AspNet Zero Power Tools to generate class but I just wonder,

    Below linq statement will returning multiple records ... join quotepolicytraveltraveller in _quotePolicyTravelTravellerRepository.GetAll().Where(x => x.IsPolicyHolder == true) on quotepolicy.Id equals quotepolicytraveltraveller.QuotePolicyId into TravellerList from quotepolicytraveltraveller in TravellerList.DefaultIfEmpty() .... and from the results, we just map as following code

    QuotePolicyTravelTraveller = ObjectMapper.Map<List<QuotePolicyTravelTraveller>>(TravellerList.ToList()),

    QuotePolicyTravelTraveller entity public class QuotePolicyTravelTraveller : EntityDto<long> { public long QuotePolicyId { get; set; } [StringLength(100)] public string FullName { get; set; } [Required] public bool IsPolicyHolder { get; set; } [Required] [StringLength(20)] public string NRIC { get; set; } }

    TravelExceptionListingOutput entity public class TravelExceptionListingOutput { public long QuotePolicyId { get; set; } public QuotePolicy QuotePolicy { get; set; } public QuotePolicyTravel QuotePolicyTravel { get; set; } public List<QuotePolicyTravelTraveller> QuotePolicyTravelTraveller { get; set; } public QuotePolicyPayment QuotePolicyPayment { get; set; } public string ResponseCode { get; set; } public string ResponseMessage { get; set; } }

    is there any other possible solution that you can suggest?
    
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    When I look at your query, I see several parts which can't be converted to SQL by EF Core.

    1. Convert.ToString
    2. DateTime.Parse
    3. ObjectMapper.Map in select statements

    You can basically define variables for Convert.ToString and DateTime.Parse before your LinQ query and use those fields. After that, you can remove ObjectMapper.Map statements in your LinQ select statement and do the mapping after retrieving the result of your query. So, your TravelExceptionListingQuery method shouldn't return an output class but it should return a class which contains Entity classes as parameters instead of DTOs. For example;

    select new MyTravelExceptionListing
                             {
                                 QuotePolicyId = quotepolicy.Id,
                                 QuotePolicy = quotepolicy,
                                 QuotePolicyTravel = quotepolicytravel,
                                 QuotePolicyTravelTraveller = null, //ObjectMapper.Map<List<QuotePolicyTravelTraveller>>(TravellerList.ToList()),
                                 QuotePolicyPayment = quotepolicypayment,
                                 ResponseCode = quotepolicytravel.ePolicyRespCode,
                                 ResponseMessage = quotepolicytravel.ePolicyIntMessage + " " + quotepolicytravel.ePolicyRespMessage
                             })
    
  • User Avatar
    0
    thinkn.tech created

    Hi,

    Your suggestion work half if not list. What if we have One to Many relationship (i.e. 1 Quotation have many traveller on board). How i can do the bind to my DTO if is List<QuotePolicyTravelTraveller>?

  • User Avatar
    0
    thinkn.tech created

    Hi,

    Any update? I have rephrase a simple joining with One to Many relationship as below.

    private IQueryable<TravelExceptionListingOutputTesting> TravelExceptionListingQueryTesting(GetTravelExceptionListingInput input)
            {
              var fristQuery = (from quotepolicy in _quotePolicyRepository.GetAll().Where(p => p.StatusId.Equals(2))
                                  join quotepolicytraveltraveller in _quotePolicyTravelTravellerRepository.GetAll().Where(x => x.IsPolicyHolder == true) on quotepolicy.Id equals quotepolicytraveltraveller.QuotePolicyId into TravellerList
                                  from quotepolicytraveltraveller in TravellerList.DefaultIfEmpty()
                                  select new TravelExceptionListingOutputTesting
                                  {
                                      QuotePolicyId = quotepolicy.Id,
                                      QuotePolicy = quotepolicy,
                                      QuotePolicyTravelTraveller = quotepolicytraveltraveller,
                                      QuotePolicyTravelTravellerList = ObjectMapper.Map<List<Quote_Policy_TravelTraveller>>(TravellerList),
                                  });
    
                return fristQuery;
            }
            
            public class TravelExceptionListingOutputTesting
        {
            public long QuotePolicyId { get; set; }
            public Quote_Policy QuotePolicy { get; set; }
            public Quote_Policy_TravelTraveller QuotePolicyTravelTraveller { get; set; }
            public List<Quote_Policy_TravelTraveller> QuotePolicyTravelTravellerList { get; set; }
        }
    
    but i still received error as following:-
    
    variable 'TravellerList' of type 'System.Collections.Generic.IEnumerable`1[ThinknInsurTech.Quote.Quote_Policy_TravelTraveller]' referenced from scope '', but it is not defined
    
    
    Appreciate that you can provide me solution as we have a lot of method using this way and it hits only when we upgrading .Net Core 3.
    
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    For your final query, you can't use TravellerList, you can only use quotepolicytraveltraveller. You are making one join to Quote_Policy_TravelTraveller table. Does your entity TravelExceptionListingOutputTesting really has those two fields (QuotePolicyTravelTraveller and QuotePolicyTravelTravellerList) ? If so, what is the relation for QuotePolicyTravelTravellerList ? I can only see QuotePolicyId in your entity.

  • User Avatar
    0
    thinkn.tech created

    Hi,

    Is that mean in .Net Core 3.1. We cannot have One to Many?

    1 Quote_Policy has many Quote_Policy_TravelTraveller (1 : M)

    How i can retrieve all Quote_Policy_TravelTraveller that associate to Quote_Policy? If cannot, how i can achieve this requirement?

    Appreaciate and Thank.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Of cours,e you can create One to Many relations. I was talking about the entity you have shared. Anyway, you can just use it like below;

    QuotePolicyTravelTravellerList = TravellerList

    instead of

    QuotePolicyTravelTravellerList = ObjectMapper.Map<List<Quote_Policy_TravelTraveller>>(TravellerList)

    Then, you have to map your result to your Dto. Mapping operation will map nested objects and lists in your result object to your Dto.

  • User Avatar
    0
    thinkn.tech created

    Hi,

    I followed what you have recommended but still not successful.

    if i do QuotePolicyTravelTravellerList = TravellerList

    QuotePolicyTravelTravellerList need to be accept public List<Quote_Policy_TravelTraveller> QuotePolicyTravelTraveller { get; set; }

    If i run query, it prompt me "Unable to cast object of type 'System.Linq.Expressions.TypedParameterExpression' to type 'Microsoft.EntityFrameworkCore.Query.ShapedQueryExpression'."

    You can have a try. Or can show me some workable sample code which involved 1-M Relathipship

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Could you share your entire query ? By the way, this is not related to AspNet Zero but we will try to help you if we can.

  • User Avatar
    0
    thinkn.tech created

    var fristQuery = (from quotepolicy in _quotePolicyRepository.GetAll().Where(p => p.StatusId.Equals(2)) join quotepolicytraveltraveller in _quotePolicyTravelTravellerRepository.GetAll().Where(x => x.IsPolicyHolder == true) on quotepolicy.Id equals quotepolicytraveltraveller.QuotePolicyId into TravellerList from quotepolicytraveltraveller in TravellerList.DefaultIfEmpty() select new TravelExceptionListingOutputTesting { QuotePolicyId = quotepolicy.Id, QuotePolicyTravelTraveller = TravellerList.ToList() });

    public class TravelExceptionListingOutputTesting { public long QuotePolicyId { get; set; } public List<Quote_Policy_TravelTraveller> QuotePolicyTravelTraveller { get; set; } }

    **1 item** of  _quotePolicyRepository and **Many** records in _quotePolicyTravelTravellerRepository
    
    
    Very appreciate for your help.
    
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Your query is correct except using ToList

    var fristQuery = (from quotepolicy in _quotePolicyRepository.GetAll().Where(p => p.StatusId.Equals(2))
    	join quotepolicytraveltraveller in _quotePolicyTravelTravellerRepository.GetAll().Where(x => x.IsPolicyHolder == true) on quotepolicy.Id equals quotepolicytraveltraveller.QuotePolicyId into TravellerList
    	from quotepolicytraveltraveller in TravellerList.DefaultIfEmpty()
    select new TravelExceptionListingOutputTesting
    {
    	QuotePolicyId = quotepolicy.Id,
    	QuotePolicyTravelTraveller = TravellerList
    });
    

    Then, you can map output of your query result to TravelExceptionListingOutputTesting. Does that work for you ?

  • User Avatar
    0
    thinkn.tech created

    Without toList() , it will error

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Is it possible to share youır project via email with [email protected] ? We can run your project and fix the query for you.

    Thanks,

  • User Avatar
    0
    thinkn.tech created

    HI,

    I have shared my project. Please check your email.

    Many thank and appreciate.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Thanks, we got the email and we will reply to you via email.

    Thanks,