0

The original question of mine is here. Where I was trying to find a way to restrict the number of columns returned FROM the database using Repository Pattern and Unit of Work. My question found an answer but I have not solved it and decided to post the new problem which arose using that technique as the problem I am going through now is a completely new subject.

In the repository, I have a Get method which takes the following parameters:

public virtual IEnumerable<TEntity> Get(
        Expression<Func<TEntity, bool>> filter = null,
        Func<TEntity, TEntity> selector = null,
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
        string includeProperties = "")

The following works well inside of my controller:

IEnumerable<Models.Authors.Author> authors = unitOfWork.AuthorRepository.Get(filter: x => x.TenantID == 1);

But, I cannot get the 'select' part working:

IEnumerable<Models.Authors.Author> authors = unitOfWork.AuthorRepository.Get(filter: x => x.TenantID == 1, selector: a=> new { FirstName = a.FirstName } );

and similarly, this:

var authors = unitOfWork.AuthorRepository.Get(filter: x => x.TenantID == 1, selector: a=> new { FirstName = a.FirstName } );

gives the following two errors:

Cannot implicitly convert type '<anonymous type: string FirstName>' to 'Models.Authors.Author'

and

Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type

I am completely alien to this. So I would really appreciate your help..

UPDATED

this:

IEnumerable<Models.Authors.Author> authors = unitOfWork.AuthorRepository.Get(filter: x => x.TenantID == 1, selector: a=> new Models.Authors.Author() { FirstName = a.FirstName } );

gives this:

The entity or complex type 'DAL.Author' cannot be constructed in a LINQ to Entities query.

UPDATE 2: Author Class // namespace is

namespace Models.Authors
{
public class Author
{
    [Key]
    public int AuthorID { get; set; }
    public int CategoryID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string PhotoPath { get; set; }
    public byte[] PhotoBinary { get; set; }
    public string PhotoPathOriginal { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
    public Guid? PassGuid { get; set; }
    public string Email { get; set; }
    public string Twitter { get; set; }
    public string Facebook { get; set; }
    public DateTime? DateCreated { get; set; }
    public DateTime? DateLastlogin { get; set; }
    public int AuthorStatus { get; set; } // 0:inactive, 1:active, 2:suspended, 3:hidden etc.
    public string AboutAuthor { get; set; }
    public bool? RequirePublishApproval { get; set; }
    public string ColumnName { get; set; }
    public string ColumnImage { get; set; }
    public bool? ChangePassAtFirstLogin { get; set; }
    public int TenantID { get; set; }

    public virtual AuthorCategory AuthorCategory { get; set; }
    public virtual IQueryable<Post.Post> Posts { get; set; }
}
}
Community
  • 1
  • 1
Subliminal Hash
  • 13,614
  • 20
  • 73
  • 104
  • The return type for your select operation isn't going to be `Authors.Author` ... you are projecting a new, anonymous type when you do a select. Depending on what you are trying to do, you could just declare authors as `var` – stephen.vakil Apr 11 '16 at 20:08
  • Consider using dynamic LINQ. Or look at [this](http://stackoverflow.com/a/723018/861716), which I think is a duplicate question. – Gert Arnold Apr 11 '16 at 20:40
  • Thanks Gert but there is too much to digest there for me.. I might better off get rid of repository pattern if what seems like a simple task is that much code to write. – Subliminal Hash Apr 11 '16 at 21:02

1 Answers1

1

You are asking repository to return for each records in the query result a new anonymous object:

selector: a => new { FirstName = a.FirstName }

But at the same time the variable you have declared is of type IEnumerable<Models.Authors.Author>

In order to make it work you need to return a Models.Authors.Author objects in a select:

IEnumerable<Models.Authors.Author> authors = unitOfWork.AuthorRepository.Get(filter: x => x.TenantID == 1, selector: a=> new Models.Authors.Author() { FirstName = a.FirstName } );

Alternatively you can use anonymous objects, but you need to declare variable as var

var authors = unitOfWork.AuthorRepository.Get(filter: x => x.TenantID == 1, selector: a=> new { FirstName = a.FirstName } );

UPDATE

Since you cannot use already mapped context entities in you queries, due to "The entity or complex type '...' cannot be constructed" error, the best solution I see is to have a separate class with few properties that required for your page. Like:

public class AuthorDetails {
   public string FirstName {get; set;}
}

And then use this class in the query and in the views:

var authors = unitOfWork.AuthorRepository.Get(filter: x => x.TenantID == 1, selector: a=> new AuthorDetails { FirstName = a.FirstName } );
Pavel Morshenyuk
  • 10,891
  • 4
  • 32
  • 38
  • Thanks Pavel but, please see my updated answer as I tried these also before and they yield the errors mentioned in my update. your second suggestion also yields the same errors i mention in my question. – Subliminal Hash Apr 11 '16 at 20:21
  • Could you please share the Author class? It looks like it is not just a domain model with properties – Pavel Morshenyuk Apr 11 '16 at 20:24
  • I have just updated the question.. Thanks for your time pavel – Subliminal Hash Apr 11 '16 at 20:27
  • Please see my update, it looks like the extra class is the only option here :( – Pavel Morshenyuk Apr 11 '16 at 20:35
  • I also tried that before Pavel. It gives the first two errors in my question. I am about to give up and use plain old db context but I know I won't be able to sleep without finding the reason for this! Do you want me to post the repository code or UoW code? – Subliminal Hash Apr 11 '16 at 20:45
  • I do not see where you checked the repository with the a new class. It looks like your repository implementation is no capable to work with anonymous objects, but potentially it should work with a specific custom classes as in my updated answer. If it does not help , please post the repository code. – Pavel Morshenyuk Apr 11 '16 at 21:01
  • Pavel I am using the example located here: http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application Repository class is a generic one hence I have made no code change there.. apart from adding the Func selector = null parameter to the Get method. The same applies to UoW class (only that I used my Author and AuthorCategory classes instead) – Subliminal Hash Apr 11 '16 at 21:08