locked
Casting EF class collection to string array RRS feed

  • Question

  • I have a data transfer object defined as:

     

     public class UserDto
      {
        public string UserId { get; set; }
        public string[] Roles { get; set; }
      }

    In my code I want to populate the the UserDto object using a Linq to Entity Framework as shown below:  

     

            public UserDto Fetch(string userId, string password)
            {
                using (var ctx = ObjectContextManager<CharisCTKEntities>.GetManager("CharisCTKEntities"))
                {
                    var result = (from r in ctx.ObjectContext.Users
                                  where r.UserId == userId && r.Password == password
                                  select new UserDto
                                  {
                                      UserId = r.UserId,
                                      Roles = r.UserRoles
                                  }
                                  ).FirstOrDefault();
                    
                    if (result == null)
                        throw new DataNotFoundException("User");
                    return result;
                }
            }
    


     However I am having problem casting r.UserRoles to UserDto.Roles. I've tried Roles = r.UserRoles.ToArray() but no good.

    The error is:
    Error 1 Cannot implicitly convert type 'System.Data.Objects.DataClasses.EntityCollection<CC.CharisCTK.DalEf.UserRole>' to 'string[]
    Any help on how to do this casting would be greatly appreciated.
    Thank you

     


    • Edited by Helio D Friday, October 7, 2011 9:07 PM
    Friday, October 7, 2011 8:58 PM

Answers

  • Hi Helio D;

    Because the Linq to EF query runs on the SQL server there are things that are NOT supported either by Entity Framework or the SQL server and this is just one of them returning an array of string in a select clause. To get around this issue you can do the following, this creates the DTO outside of the query:

    public UserDto Fetch(string userId, string password)
    {
        using (var ctx = ObjectContextManager<CharisCTKEntities>.GetManager("CharisCTKEntities"))
        {
            var result = (from r in ctx.ObjectContext.Users
                          where r.UserId == userId && r.Password == password
                          select new
                          {
                              UserId = r.UserId,
                              Roles = r.Roles.Select( x => x.RoleName )
                          }
                          ).FirstOrDefault();
            
            if (result == null)
                throw new DataNotFoundException("User");
                
            UserDto userRoles = new UserDto( ) {UserId = result.UserId, Roles = result.Roles.ToArray()};
            
            return userRoles;
        }
    }
    

     


    Fernando (MCSD)

    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    • Proposed as answer by Tom_Overton Saturday, October 8, 2011 10:06 AM
    • Marked as answer by Helio D Saturday, October 8, 2011 10:59 AM
    Saturday, October 8, 2011 4:20 AM

All replies

  • I assume your UserRole entity has some property like "RoleName" which you want to be in the Roles array?  If so, try to do something like this:

    Roles = r.UserRoles.Select(x => x.RoleName).ToArray();

     

     

     


    Tom Overton
    Friday, October 7, 2011 9:18 PM
  • Hi Tom, Thank you very much for your quick reply. Much appreciated.

    My database has the following tables:

    User: UserId, UserName, Password

    Role: RoleId, RoleName

    UserRole: (many to many) contains UserId, RoleId.

     

    I tried your fix with one change:

     

            public UserDto Fetch(string userId, string password)
            {
                using (var ctx = ObjectContextManager<CharisCTKEntities>.GetManager("CharisCTKEntities"))
                {
                    var result = (from r in ctx.ObjectContext.Users
                                  where r.UserId == userId && r.Password == password
                                  select 
                                  new UserDto
                                  {
                                      UserId = r.UserId,
                                      Roles = r.UserRoles.Select(x => x.Role.RoleName).ToArray()
                                  }
                                  ).FirstOrDefault();
    
                    if (result == null)
                        throw new DataNotFoundException("User");
                    return result;
                }
            }
    

    Now I get the following error:

     

    DataPortal.Fetch failed (LINQ to Entities does not recognize the method 'System.String[] ToArray[String](System.Collections.Generic.IEnumerable`1[System.String])' method, and this method cannot be translated into a store expression.)

    Sorry, linq to EF is quite new to me.

     

     


    • Edited by Helio D Friday, October 7, 2011 10:05 PM
    Friday, October 7, 2011 10:03 PM
  • Hi Helio D;

    Because the Linq to EF query runs on the SQL server there are things that are NOT supported either by Entity Framework or the SQL server and this is just one of them returning an array of string in a select clause. To get around this issue you can do the following, this creates the DTO outside of the query:

    public UserDto Fetch(string userId, string password)
    {
        using (var ctx = ObjectContextManager<CharisCTKEntities>.GetManager("CharisCTKEntities"))
        {
            var result = (from r in ctx.ObjectContext.Users
                          where r.UserId == userId && r.Password == password
                          select new
                          {
                              UserId = r.UserId,
                              Roles = r.Roles.Select( x => x.RoleName )
                          }
                          ).FirstOrDefault();
            
            if (result == null)
                throw new DataNotFoundException("User");
                
            UserDto userRoles = new UserDto( ) {UserId = result.UserId, Roles = result.Roles.ToArray()};
            
            return userRoles;
        }
    }
    

     


    Fernando (MCSD)

    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    • Proposed as answer by Tom_Overton Saturday, October 8, 2011 10:06 AM
    • Marked as answer by Helio D Saturday, October 8, 2011 10:59 AM
    Saturday, October 8, 2011 4:20 AM
  • Thank you very much Mark - your answer solved my problem.
    Saturday, October 8, 2011 10:57 AM
  •  

    Not a problem, glad to help.

     


    Fernando (MCSD)

    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    Saturday, October 8, 2011 1:39 PM