views:

393

answers:

2

I have a class called UserInfo that contains details about a given user.

There are several places in code where the data might be queried and I'd like to have a single function to fill the UserInfo object with the corresponding data from the Linq Query.

                var userData = dc.Users.Where(λ => (λ.Login == username) && λ.Active)
                  .Select(λ => new { λ.ID, Salt = λ.Seasonings.Single().Salt, λ.Login, λ.PassHash, λ.Admin, λ.Trusted, λ.E_mail, λ.Name, λ.Phone, λ.Note, λ.RegistrationDate }).SingleOrDefault(); 
                string tmppass = generatePassHash(password, userData.Salt);
                if (userData.PassHash.Trim() == tmppass.Trim())
                {
                    ID = userData.ID;
                    // Here is the stuff i'd like to move to a function
                    _user._id = userData.ID;
                    _user._userState = State.NotAuthorized;
                    _user._username = userData.Login;
                    _user._name = userData.Name;
                    _user._email = userData.E_mail;
                    _user._phone = userData.Phone;
                    _user._notes = userData.Note;
                    ...

                }

How do I properly set up a function to accept this anonymous type as an argument? Do I need to declare a new interface or is there a simpler way?

Thanks for the help!

PS- sorry for the excessive underscores, nested classes make things a bit messy.

+2  A: 

I'm afraid It's not possible to pass an anonymous type as an argument to another method. But I wonder why you are using an anonymous type and not working with user in the first place?

PS : BTW if you are applying the same pattern through out your code why don't you implement a concrete class for UserInfo ?

Beatles1692
Forgive me- I don't have a huge amount of experience with linq. Is there a way to cast a Query result directly to a custom type?
apocalypse9
Yes. A Linq query is of type IQueryable<T> therefore every method that returns an actual result will have type of T or it's a generic type containing T.
Beatles1692
To be more precise every Linq to sql query is IQueryable<T> Linq to object and Linq to xml are of type IEnumerable<T>
Beatles1692
I'm sorry- bad explanation on my part. UserInfo is a concrete class. _user is an instance of UserInfo. My data is coming from a SQL database. What I'm trying to do is find a smoother way to fill my UserInfo class with information from my database.
apocalypse9
Then you can use UserInfo itself and use an object initializer to create UserInfo you can do it like this:select new UserInfo{FirstName=u.FirstName,LastName=u.LastName,...}
Beatles1692
Ah ok- I missed that. Thank you very much that helps a lot. Sorry I was a bit tired and apparently wasn't quite getting it last night.
apocalypse9
+2  A: 

For simplicity's sake, couldn't you just have all your routines accept the entity object itself? E.g. if dc.Users is a table of type UserEntity, skip the Select():

UserEntity userData = dc.Users.Where(
       λ => (λ.Login == username) && λ.Active).SingleOrDefault();

And if that isn't acceptable, encapsulate a more limited object which takes UserEntity as a ctor parameter:

public class UserInfo
{
    public string Name {get;set;}
    public string Phone {get;set;}
    ...

    public UserInfo(UserEntity entity)
    {
        this.Name = entity.Name;
        this.Phone = entity.Phone;
        ...
    }
}

var userData = dc.Users.Where(
       λ => (λ.Login == username) && λ.Active).Select(
         λ => new UserInfo(λ)).SingleOrDefault();

This abstracts the messy conversion away from the rest of your application. However, in general I'd recommend simply using the entity object, since it makes it much easier to go in reverse when you need (passing a modified entity back to the DAL).

Rex M
+1 for the tip, but that is a weird use of the letter lambda. Lambda should be a function, but here it's a parameter. I think you can safely rename it to `user`.
Kobi
@Kboi I agree it's a little weird, I just copied the convention the OP used to show it's the same code.
Rex M
Oh, sorry, didn't notice it there.
Kobi
Yeah I know that isn't mathematically the correct usage of λ.Single letter variables seem to be common. In this case I might have used U for user, but it doesn't seem to lend clarity to the code and I frequently found it distracting in cases where the letter could have matched several things. Likewise longer variable names in such a small scope don't really help all that much, and often related names like 'user' are already in use. It is the operation not the variable that is important.For me it is a just way to make the bound lambda variable instantly visually clear.
apocalypse9
Thank you- That is a far cleaner way of doing it. Not sure why I was trying to over-complicate things there. Thank you very much for your detailed answer. That was a huge help.
apocalypse9