Open Closed

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


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)
  • 0
    maliming created
    Support Team

    hi

    Can you share the full code?

  • 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;
            }
            
            ```
    
  • 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.

  • 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?
    
  • 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
                             })
    
  • 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>?

  • 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.
    
  • 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.

  • 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.

  • 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&lt;List&lt;Quote_Policy_TravelTraveller&gt;>(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.

  • 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

  • 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.

  • 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.
    
  • 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 ?

  • 0
    thinkn.tech created

    Without toList() , it will error

  • 0
    ismcagdas created
    Support Team

    Hi,

    Is it possible to share youır project via email with info@aspnetzero.com ? We can run your project and fix the query for you.

    Thanks,

  • 0
    thinkn.tech created

    HI,

    I have shared my project. Please check your email.

    Many thank and appreciate.

  • 0
    ismcagdas created
    Support Team

    Hi,

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

    Thanks,