Search code examples
c#.netasp.net-coreentity-framework-coreblazor

While trying to concatenate a string, I am getting expression tree cannot contain value of ref struct or restricted type error


I have a method that pulls data from DB and then assigns it to a Model for use in other places. I am getting address details from the db in different parameters as shown below. While concatenating the string values, I am getting below error.

Please help me with this.

Expression tree cannot contain value of ref struct or restricted type.

An expression tree may not contain an expanded form of non-array params collection parameter.

The code below

 public async Task<InvoiceLocationDTO> GetLocationDetails(int locId)
 {
     try
     {
         InvoiceLocationDTO? locationDetails = await (
             from loc in context.Location.Where(loc => loc.Id == locId)
             .Include(x => x.LocationAddress)             

             select new InvoiceLocationDTO
             {
                 ///Getting error in below line
                 BillToAddress = string.Format(" {0}, {1}, {2}, {3}, {4}",
                                 loc.LocationAddress.Address, loc.LocationAddress.AddressExtraLine, loc.LocationAddress.City, loc.LocationAddress.State.Name, loc.LocationAddress.Zip)
                                 .Replace(" ,", string.Empty).TrimEnd(','),
             }
         ).FirstOrDefaultAsync();
         return locationDetails;
     }
     catch (Exception ex)
     {
         throw ex;
     }
 }

Solution

  • Don't forget that your query will be translated to SQL. Your String.Format can't be translated to SQL. Therefore, return all the required fields in the query and format the string locally using the query result. You can return the fields in an anonymous object:

    public async Task<InvoiceLocationDTO?> GetLocationDetails(int locId)
    {
        // Query the database for the location details
        var a = await (
            (from loc in context.Location
            .Where(loc => loc.Id == locId)
            .Include(x => x.LocationAddress)
                select new {
                    loc.LocationAddress.Address,
                    loc.LocationAddress.AddressExtraLine,
                    loc.LocationAddress.City,
                    StateName = loc.LocationAddress.State.Name,
                    loc.LocationAddress.Zip
                })
        )
        .FirstOrDefaultAsync()
        .ConfigureAwait(false);
    
        if (a is null) return null;
    
        // Format the address. String interpolation simplifies the code.
        return new InvoiceLocationDTO {
            BillToAddress = $" {a.Address}, {a.AddressExtraLine}, {a.City}, {a.StateName}, {a.Zip}"
                .Replace(" ,", string.Empty).TrimEnd(','),
        };
    }
    

    It's not tested, but you get the point.