Home > Blockchain >  C# Automapper "Unsupported Mapping" with List<dynamic> result of LinQ query
C# Automapper "Unsupported Mapping" with List<dynamic> result of LinQ query

Time:03-24

Given the next working LinQ query:

var catalogues = (from cat in db.CATALOGUES

                      join doc in db.DOCUMENTS_CATALOGS on
                      new { a = cat.PFK_ENTERPRISE, b = cat.FK_DOCUMENT_VIDEO }
                      equals
                      new { a = doc.PFK_ENTERPRISE, b = (int?)doc.PK_DOCUMENT }

                      join pos in db.DOCUMENTS_CATALOGS on
                      new { a = cat.PFK_ENTERPRISE, b = cat.FK_DOCUMENT }
                      equals
                      new { a = pos.PFK_ENTERPRISE, b = (int?)pos.PK_DOCUMENT }

                      where (cat.PFK_ENTERPRISE == enterpriseId && cat.PK_CATALOGUE == catalogueId)
                      orderby cat.DESC_CATALOGUE ascending
                      select new
                      {
                          cat.PK_CATALOGUE,
                          cat.FK_DOCUMENT_VIDEO,
                          cat.DESC_CATALOGUE,
                          doc.REAL_NAME,
                          doc.SERVER_NAME_ORIGINAL_FILE,
                          POSTER = pos.SERVER_NAME_ORIGINAL_FILE
                      });

Which produces a result with a List Anonymous with something like this (1 record un my case):

{ 
    PK_CATALOGUE = 212, 
    FK_DOCUMENT_VIDEO = 212, 
    DESC_CATALOGUE = "xxx", 
    REAL_NAME = "7_Category_Image_c3ab57e3-ec7e-4a80-aaa1-c6cc10a1b917.jpg", 
    SERVER_NAME_ORIGINAL_FILE = "7_Category_Image_c3ab57e3-ec7e-4a80-aaa1-c6cc10a1b917.jpg", 
    POSTER = "7_IMG_CATALOGUE_5d8e24eb-8a40-4e4d-9d86-a3f610d5b65e.jpg" 
}

I'm trying to map it to the next object:

public class VideoGalleryVM
{
    public int PK_CATALOGUE { get; set; }
    public int? FK_DOCUMENT_VIDEO { get; set; }
    public string DESC_CATALOGUE { get; set; }
    public string REAL_NAME { get; set; }
    public string SERVER_NAME_ORIGINAL_FILE { get; set; }
    public string POSTER { get; set; }
}

The following way:

var config = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<object, VideoTrainingVM>().ReverseMap();
});

IMapper mapper = config.CreateMapper();

List<VideoGalleryVM> vgVM = mapper.Map<List<VideoGalleryVM>>(videoGallery);

But I whatever I try I get an exception of type "Invalid mapping".

I don't mind using Automapper or not, just need to cast the return of the LinQ query (that is List dynamic) to a View Model object, and:

var test1 = catalogues.ToList().Cast<VideoGalleryVM1>().ToList();

ends with an invalid cast Exception and

var test2 = catalogues.OfType<VideoGalleryVM1>().ToList();

ends with a list of 0 elements.

CodePudding user response:

You do not need Automapper for everything, it was created for simple scenarios - mapping similar KNOWN objects to another and better if mapping is simple. If you make projection via Select - you can map all that you need in one place without using "magic" of Automapper.

So just project your result into desired objet type:

var catalogues = 
    from cat in db.CATALOGUES

    join doc in db.DOCUMENTS_CATALOGS on
    new { a = cat.PFK_ENTERPRISE, b = cat.FK_DOCUMENT_VIDEO }
    equals
    new { a = doc.PFK_ENTERPRISE, b = (int?)doc.PK_DOCUMENT }

    join pos in db.DOCUMENTS_CATALOGS on
    new { a = cat.PFK_ENTERPRISE, b = cat.FK_DOCUMENT }
    equals
    new { a = pos.PFK_ENTERPRISE, b = (int?)pos.PK_DOCUMENT }

    where (cat.PFK_ENTERPRISE == enterpriseId && cat.PK_CATALOGUE == catalogueId)
    orderby cat.DESC_CATALOGUE ascending
    select new VideoGalleryVM
    {
        PK_CATALOGUE = cat.PK_CATALOGUE,
        FK_DOCUMENT_VIDEO = cat.FK_DOCUMENT_VIDEO,
        DESC_CATALOGUE = cat.DESC_CATALOGUE,
        REAL_NAME = doc.REAL_NAME,
        SERVER_NAME_ORIGINAL_FILE = doc.SERVER_NAME_ORIGINAL_FILE,
        POSTER = pos.SERVER_NAME_ORIGINAL_FILE
    };

Highly recommend to read article from Automapperr's creator when to use or not his library. Article was created to stop using library for cases when it is a pain to support mapping later: AutoMapper Usage Guidelines

CodePudding user response:

Ok, after struggling my head for hours, the only solution I've found to cast my List of dynamic (result of LinQ query) to a View Model object was:

var targetList = catalogues.Select(cat => new VideoGalleryVM() 
                { 
                    PK_CATALOGUE = cat.PK_CATALOGUE,
                    FK_DOCUMENT_VIDEO = cat.FK_DOCUMENT_VIDEO,
                    DESC_CATALOGUE = cat.DESC_CATALOGUE,
                    REAL_NAME = cat.REAL_NAME,
                    SERVER_NAME_ORIGINAL_FILE = cat.SERVER_NAME_ORIGINAL_FILE,
                    POSTER = cat.SERVER_NAME_ORIGINAL_FILE
                }).ToList();

I don't think is the best option, not even understand why Automapper (or other type of casts) won't work, but this just works.

In my case we are talking of a class with not so many properties, but image a long class... this is what Automapper is supposet to.

I hope this will help anyone else.

  • Related