0

I have created an automapper

CreateMap<Records_Log, Records_LogDto>()
                .ForMember(dest => dest.UserName, opt =>
                {
                    opt.ResolveUsing(d => d.User.UserName);
                });

Records_Log

public class Records_Log
    {
        public int Id { get; set; }
        public string Table_name { get; set; }



        [ForeignKey("Records")]
        public int RecordsId { get; set; }
        public Records Records { get; set; }
        public  int RecordId { get; set;  }
        public string OldValue { get; set; }
        public string NewValue { get; set; }

        [ForeignKey("User")]
        public string UserId { get; set; }
        public ApplicationUser User { get; set; }

        public DateTime ChangeDate { get; set; }

        public string Action { get; set; }


    }

Records_LogDto

public class Records_LogDto
    {

        public int Id { get; set; }
        public string Table_name { get; set; }

        public int RecordsId { get; set; }
        public Records Records { get; set; }

        public int RecordId { get; set; }
        public string OldValue { get; set; }
        public string NewValue { get; set; }

        public string UserId { get; set; }

        public string UserName { get; set; }

        public string Action { get; set; }

        public DateTime ChangeDate { get; set; }
    }

Records:

public class Records
    {
        public int Id { get; set; }

        public string SerialName { get; set; }

        public string RecordsName { get; set; }

        public string Url { get; set; }
        public string AttachmentPath { get; set; }
        public string ImagePath { get; set; }

        public string RecordsNameModified { get; set; }

        public bool isDeleted { get; set; }

        public bool isRead { get; set; }

        public bool IsHidden { get; set; }
        public bool MarkAsImportant { get; set; }
        public string ImportantComments { get; set; }

        public int subTypeID { get; set; }


        public virtual ICollection<Records_Rate> Records_Rate { get; set; }

    }

My query

var query = (from st in db.Records_State
                         join sl in db.Records_Log
                         on st.Records.Id equals sl.RecordsId
                         where st.Records.isDeleted
                         && sl.Table_name == nameof(Records)
                         && sl.Action == "Deleted"
                         && sl.NewValue == "Top"
                         && (string.IsNullOrEmpty(recordsName) || sl.Records.RecordsName.Contains(recordsName)
                            || sl.Records.RecordsNameModified.Contains(recordsName))
                         && (fromDate == null || sl.ChangeDate >= fromDate)
                         && (toDate == null || sl.ChangeDate <= toDate)
                         orderby sl.ChangeDate descending
                         select new Records_Log { 
                             Records= st.Records, 
                             ChangeDate= sl.ChangeDate 
                         })
                         .AsQueryable();

   



query = from p in query
                group p by p.Records.Id
                into pGroup
                orderby pGroup.Key
                select pGroup.FirstOrDefault();

        var result = query.Skip((pageNumber - 1) * pageSize)
          .Take(pageSize)
          .OrderByDescending(st => st.Id);

        var dto = Mapper.Map<List<Records_LogDto>>(result);

now in the last line var dto = Mapper.Map<List<Records_LogDto>>(result); it throws exception:

Error mapping types.\r\n\r\nMapping types:\r\nDbQuery1 -> List1\r\nSystem.Data.Entity.Infrastructure.DbQuery1[[PortalBackEndAPI.Models.Records_Log, PortalBackEndAPI.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] -> System.Collections.Generic.List1[[PortalBackEndAPI.Dto.Records_LogDto, PortalBackEndAPI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"}

and

The entity or complex type 'PortalBackEndAPI.Models.Records_Log' cannot be constructed in a LINQ to Entities query

Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
testy
  • 37
  • 5
  • 2
    That's an EF error, not an AM error. – Lucian Bargaoanu Aug 31 '22 at 09:53
  • ok but what's the solution @LucianBargaoanu? – testy Aug 31 '22 at 10:58
  • 2
    I believe what @LucianBargaoanu wanted to point out is, that you are only getting the error on the line of automapper, because that is the first time you are enumerating the `result` instance. So, if you where to exchange the line of the automapper with a simple `foreach (var item in result) { }` you would get the same exception. And your issue is on this line `select new Records_Log { ` I can't tell you why Entity Framework doesn't want to create this class, but that should be the issue at hand. – Rand Random Aug 31 '22 at 11:34
  • @RandRandom yeah that's true, i tried before that line and same error but cannot figure out why – testy Aug 31 '22 at 11:35
  • 2
    Have you consider defining a new class and use this? eg. `class Foo { public Records Records { get; set; } public DateTime ChangeDate { get; set; } }` maybe EF doesn't like it when you are using a class that is mapped to the database as it could be treated specially? and the Foo class would be outside the scope of EF? or use an `anonymous type` https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/types/anonymous-types – Rand Random Aug 31 '22 at 11:38
  • @RandRandom hi, i tried that as well. Didn't work. – testy Sep 01 '22 at 04:32
  • 1
    See the duplicate. Project to `Records_LogDto` directly without first projecting to `Records_LogDto`. – Gert Arnold Sep 01 '22 at 06:47
  • 1
    @GertArnold - your sentence seems wrong to me since you are stating the same class, but maybe its just me – Rand Random Sep 01 '22 at 07:39
  • 2
    Ah yeah, without first projecting to `Records_Log`. – Gert Arnold Sep 01 '22 at 08:03

1 Answers1

1

The object you pass into the map method is still of Type DBQuery which Automapper has no configured mapping for. The error code hints at this! The reason why the object you are passing is not of the type Records_Log is because you didn't let it resolve yet.

Check if you can call a ToList or ToListAsync method on the DBQuery like in the following example.

var dto = Mapper.Map<List<Records_LogDto>>(result.ToList());
// Or
var dto = Mapper.Map<List<Records_LogDto>>(await result.ToListAsync());

One of those methods (There are others) will force the DBQuery to be resolved and loaded into a List.

  • hi, same error The entity or complex type 'PortalBackEndAPI.Models.Records_Log' cannot be constructed in a LINQ to Entities query."} – testy Aug 31 '22 at 10:57
  • 1
    @testy - with the same `Error mapping types.` ? if yes, you are doing something wrong the error mapping types shouldn't contain `System.Data.Entity.Infrastructure.DbQuery1` after you called `ToList()` on the query. – Rand Random Aug 31 '22 at 11:24
  • @RandRandom NO, no dbQuery error but only this error The entity or complex type 'PortalBackEndAPI.Models.Records_Log' cannot be constructed in a LINQ to Entities query – testy Aug 31 '22 at 11:28
  • Only this now The entity or complex type 'PortalBackEndAPI.Models.Records_Log' cannot be constructed in a LINQ to Entities query – testy Aug 31 '22 at 11:29
  • Can you update the question and or just provide the new error code you are getting. It is hard to help you with infos like this. Send the whole exceptions with maybe also checking if there is any inner exception. If you want to check it more clearly provide both types in the map function like the following: `var dto = Mapper.Map, List> (result)` the intellisense should then provide you the info you need. – Benny Schärer Aug 31 '22 at 13:02
  • It's only an EF6 limitation. Nothing to do with AutoMapper. `select new Records_Log` is the culprit. EF6 doesn't allow creating entity types in a projection. – Gert Arnold Aug 31 '22 at 21:10
  • @GertArnold yeah that could be becauswe nothing worked. put this in the answers so i can accept – testy Sep 01 '22 at 04:32