0

I use entity framework core 2.0 and mapster as object mapper.

An user can create news in my scenario.

I have this method:

public List<NewsMasterDTO> GetMasterData()
{
      IQueryable<News> news = dbcontext.News;
      IQueryable<ApplicationUser> user = dbcontext.Users;
      return news.Join(inner: user, outerKeySelector: newsDB =>   newsDB.UserId,
          innerKeySelector: applicationUser => applicationUser.Id,
          resultSelector: (newsSelector, applicationUser) =>
                           new
                           {
                            newsSelector.ID,
                            newsSelector.Date,
                            newsSelector.Image,
                            newsSelector.Headline,
                            newsSelector.Text,
                            Author= applicationUser.UserName
                           }).ToList();
}

which works as I want. But instead of writing my selected properties by hand, I want to use mapster. Therefore I have this class:

  public class NewsMasterDTO
  {
    public int ID { get; set; }
    public string Headline{ get; set; }
    public byte[] Image{ get; set; }
    public string Text { get; set; }
    public DateTime Date{ get; set; }
    public string Author{ get; set; }
  }

and tried something like this:

 public List<NewsMasterDTO> GetMasterData()
    {
          IQueryable<News> news = dbcontext.News;
          IQueryable<ApplicationUser> user = dbcontext.Users;
          return news.Join(inner: user, outerKeySelector: newsDB =>   newsDB.UserId,
              innerKeySelector: applicationUser => applicationUser.Id,
              resultSelector: (newsSelector, applicationUser) =>
                               new
                               {
                                newsSelector,
                                Author= applicationUser.UserName
                               })
                               .ProjectToType<NewsMasterDTO>()
                               .ToList();
    }

But it doesn't work. My SQL-Profiler show me this:

SELECT applicationUser.UserName as author
FROM News
INNER JOIN Users ON News.AuthorId = Users.ID;

So it doesn't project the properties from NewsMasterDTO.

If I write it this way:

 public List<NewsMasterDTO> GetMasterData()
    {
          IQueryable<News> news = dbcontext.News;
          IQueryable<ApplicationUser> user = dbcontext.Users;
          return news.Join(inner: user, outerKeySelector: newsDB =>   newsDB.UserId,
              innerKeySelector: applicationUser => applicationUser.Id,
              resultSelector: (newsSelector, applicationUser) => newsSelector)

                               .ProjectToType<NewsMasterDTO>()
                               .ToList();
    }

the property selection works but the join to get the Username doesn't. SQL-Profiler shows something like this:

SELECT id, headline, image, text, date
FROM News
INNER JOIN Users ON News.AuthorId = Users.ID;

But as you can see, the author in the SELECT is missing...

Is there any way to achieve my goal, so that I can describe my selected properties in my NewsMasterDTO class instead of writing it in the resultSelector explicit?

Thank you in advance!

GrayFox
  • 997
  • 1
  • 9
  • 26
  • 1
    Why use mapster when `NewsMasterDTO` has the properties you want? Why don't you write `new NewsMasterDTO{ID=newsSelector` etc? What you ask isn't *mapping*, it's projection. Mapping means you already have one type instance and want to map it to another type. You have no instances here, only a query that needs something to tell it how to project the results it gets into a type – Panagiotis Kanavos Jan 25 '18 at 13:54
  • BTW, EF is an ORM. Relations should be mapped to navigation properties. The `News` class should have a `User` property. It's the ORM's job to map those relations to joins. You could load everything you need with a simple `News.Where(someFilter).ToArray()` or `News.Where(..).Select(news=>new NewsMasterDTO{,,,Author=news.User.UserName})` if you don't want to load all of a User's fields – Panagiotis Kanavos Jan 25 '18 at 13:59
  • If I add a property to my NewsMasterDTO I have to go inside my GetMasterData() method and have to add this in the .Select statement. That's what I want to avoid, I just want to add a new property inside NewMasterDTO class – GrayFox Jan 25 '18 at 14:02
  • then create *proper* entities and relations. If `News` had a `User` property you wouldn't need to map anything. Nothing prevents you from adding another property that isn't mapped to a database field. If `User` contains only the `UserName` property you can use mapster to flatten the parent/child objects into a single one, configuring only the Author=>User.Username mapping. If it contains more fields, eg a photo, you *have* to write the projection anyway, to avoid loading unwanted data – Panagiotis Kanavos Jan 25 '18 at 14:04
  • @Panagiotis Kanavos thanks for your comment. Could you give me an example as answer. News and User have a lot of properties on the database, but for the MasterView I just need some properties from News and only the username from Users. – GrayFox Jan 25 '18 at 14:12

0 Answers0