0

I have a method

  public List<DTO.User> GetUsers(Func<Domain.User, bool> expression)
  {
        var users = new List<DTO.User>();

        using(UserContext context = new UserContext())
        {
           // obviously an error
           users = context.Users.ToList();
        }

        return users;

   }

Notice the DTO.User (a DTO) and Domain.User (a domain entity from EF) So I use AutoMapper to map entities like this

  public List<DTO.User> GetUsers()
  {
        var users = new List<DTO.User>();

        using(UserContext context = new UserContext())
        {

           Mapper.CreateMap<Domain.User, DTO.User>();
           users = 
           Mapper.Map<List<Domain.User>,List<DTO.User>>(context.Users.ToList());
        }

       return users;

   }

Alright, this looks OK but.. I want the GetUser method to accept a delegate expression as a parameter. I have a grid in the ui that displays the user list and it has many filtering options, so I want my UI to just call 1 method instead of creating method per filter.

  // filter by username
  List<DTO.User> users = userBL.GetUsers(u => u.UserName.Contains(txtUserName.Text));

  // filter by ID
  List<DTO.User> users = userBL.GetUsers(u => u.== txtUserID.Text);

  ...

So I came up with the Idea like this in my DAL layer

  public List<DTO.User> GetUsers(Func<DTO.User, bool> expression)
  {
        var users = new List<DTO.User>();

        using(UserContext context = new UserContext())
        {
           Mapper.CreateMap<Domain.User, DTO.User>();

           Func<Domain.User, bool> predicate;

           // this is an error on AutoMaper
           predicate = Mapper.Map<Func<DTO.User,bool>, Func<Domain.User, bool>>(expression)

           // I also tried direct casting which is an obvious fail
           //predicate = (Func<Domain.User,bool>)expression;

           users = 
           Mapper.Map<Domain.User, DTO.User>(context.Users.Where(predicate).ToList());
        }

       return users;

   }

So basically, I'm trying to cast or map the DTO delegate to Domain delaget for it to be use in the .Where() method of the domain.User list. Is it possible? thanks in advance.

Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
dotnetlinc
  • 391
  • 3
  • 7
  • 18

2 Answers2

1

I'm almost sure that you cannot map delegate to another delegate but your code has even more problems:

  • If you pass Func<User, bool> to your Linq-to-entities query you will do the same as you do now. It will pull all data from the database and execute filter in your application server's memory. You must pass Expression<Func<User, bool>> to execute it on DB server.
  • I don't know whole your architecture and complexity of the application but I feel that placing conversion to DTOs directly in DAL is not good. I can imagine doing this only in EFv1 when using EntityObjects.
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • my goal is not to pull all data from the database when filtering thats why i have my predicate in the UI, GetUser(u => u.ID == ID) should be equivalent to select * from users where ID = @ID... but then as you said, I have to learn the Expression<> to do that, thanks – dotnetlinc May 06 '11 at 07:53
  • goin back to the question, how can I convert Expression> to Expression> ? – dotnetlinc May 06 '11 at 07:55
  • Yah, i also thinking moving the DTO conversion in the BL – dotnetlinc May 06 '11 at 07:56
  • As mentioned above you can actually parse the syntax tree of an Expression> into Expression>; that's part of the linq-to-sql strategy for creating the SQL statements to execute. But it means traversing a tree containing virtually all language constructs of C#/.NET why it is indeed not a simple task. – faester May 06 '11 at 08:01
  • I think im going to the IQueryable path =) – dotnetlinc May 06 '11 at 08:32
0

If you are still into casting delegates you can find some more info about that here.

Community
  • 1
  • 1
Daniel
  • 891
  • 6
  • 18