0

I have 2 service models and 2 DAL models. While creating new Author, I want to save its books to Book table. So, I send payload as json. However, If I try to adapt model to Book model, its values are null.So I can solve this problem. I also tried model.Adapt<IEnumerable<Book>>(), this also comes null.

public async Task<AuthorRequest> CreateAsync(AuthorRequest model)
{
    var authorEntity= model.Adapt<Author>(); // works fine
    var bookEntity =model.Adapt<Book>();//null
}

Service.Models

public class AuthorRequest :Identifiable<string>
{
    public string override Id{get;set;}

    [Attr("name")]
    public string Name { get; set; }

    [Attr("surname")]
    public string Surname { get; set; }

    public  ICollection<BookRequest> Books{get; set; }
}

public class BookRequest :Identifiable<string>
{
    public string override Id{get;set;}
    public string Title { get; set; }
}

DAL.Model

public class Author : AuditableEntity
{
    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("surname")]
    public string Surname { get; set; }

    [JsonProperty("books")]
    public Relationship<IList<Book>> Books;
}

public class Book :AuditableEntity
{
    [JsonProperty("Title")]
    public string Title { get; set; }

    [JsonProperty("Author")]
    public Relationship<IList<Author>> Author;
}

Mappings with mapster

TypeAdapterConfig<DAL.Models.Author, Service.Models.AuthorRequest>.NewConfig();
TypeAdapterConfig<DAL.Models.Book, Service.Models.AuthorRequest>.NewConfig();
TypeAdapterConfig<DAL.Models.Book, Service.Models.BookRequest>.NewConfig();

TypeAdapterConfig<Service.Models.AuthorRequest, DAL.Models.Author>.NewConfig();
TypeAdapterConfig<Service.Models.AuthorRequest, DAL.Models.Book>.NewConfig();
TypeAdapterConfig<Service.Models.BookRequest, DAL.Models.Book>.NewConfig();

AuthorRequest.JSON

{
    "name": "William",
    "surname": "Shakespeare",
    "books": [{
        "title": "Macheth"
    }]
}
beetlejuice
  • 115
  • 1
  • 10
  • I don’t know Mapster, but why do you expect `model.Adapt()` to work here? If `model.Adapt()` maps to the author, then that works because the model looks like an `Author` object. But it only *contains* (possibly multiple) books, it *is* not a book, so it’s not surprising that it won’t map. Maybe you need to do something like `model.Books.Adapt()` here? – poke May 01 '18 at 12:13

1 Answers1

1

Why do you expect model.Adapt<Book>() to yield any result here? Mapping entities usually works by copying over similar properties. This works for AuthorRequest and Author because they both contain the same properties. So when you map the model, which is an AuthorRequest, you properly get a filled Author object back.

However, when you try to map the same AuthorRequest to a (single) Book then that won’t work since they are just too different: AuthorRequest has the properties Name, Surname, and Books, while Book has the properties Title and Author. There is simply no match there.

What you can do is map the books that are within the AuthorRequest object, doing this:

var bookEntities = model.Books.Adapt<Book[]>();

This will not map the collection of BookRequest objects that are within the model to a Book array. This should work as expected.

Note though that Mapster is already smart enough to map nested types on its own. If you look at the authorEntity object, you will see that the nested book entities were also properly mapped. So if you want to map the AuthorRequest (which contains BookRequests) to an Author entity containing Book entities, then your first line should already be enough:

var r = new AuthorRequest
{
    Name = "William",
    Surname = "Shakespeare",
    Books = new BookRequest[] {
        new BookRequest { Title = "Macbeth" },
        new BookRequest { Title = "Romeo and Juliet" },
    },
};
r.Adapt<Author>().Dump();

Result of the previous code in LINQPad

poke
  • 369,085
  • 72
  • 557
  • 602
  • The reason to use model.Adapt is that I do not want to use foreach loop and do not want to create new instance of Book entity. `model.Books.Adapt();` also does not work for me. – beetlejuice May 01 '18 at 13:24
  • @beetlejuice Did you check that `model` actually contains your values? Did you look at the `authorEntity` object to see whether it already contains the book entities? Try my example and see if that works for you. Also check whether your `Relationship` type causes any problem there (I did it without that because I don’t know what it is); you might have to configure Mapster to recognize that. – poke May 01 '18 at 13:39
  • Yes I check my `authorEntity` and it contains Books' values. I have already done as you have shown in your example when the adapt method fails. I agree with you. It is related with mapster configuration. – beetlejuice May 01 '18 at 14:00