views:

105

answers:

4

I need to return an IEnumerable of a dynamically created Dictionary.

pseudo code:

var x = from u in Users

select new dictionary<string, string>{
    Add("Name",u.Name),
    Add("LastName",u.LastName)
}

I've been trying many ways to get the pseudo code example above but no success...

I would really appreciate your help.

+5  A: 
var x = from u in Users
        select new Dictionary<string, string> {
            { "Name", u.Name },
            { "LastName", u.LastName }
        };
mquander
This thing didnt work. Throw this exception Unrecognized expression node: ListInitI tried adding and removing () after Dictionary<string,string> and no success... Any ideas...
Tony
@Tony, @mquander, Try `from u in Users.AsEnumerable()` as `Users` might be `IQueryable` and it's trying to convert the whole LINQ statement in SQL script.
Igor Zevaka
+1  A: 

That is poor use of a dictionary - you're only using it as a property bag, and create as many dictionaries as users.
A better use of the language would be creating your own User class with these properties and use that:

public class User
{
    public string Name { get; set; }
    public string LastName { get; set; }
}

And the query:

var users = Users.Select(u => new User
            {
                Name = u.Name,
                LastName = u.LastName
            });

If you'll only use the collection whiting your method, another option is to create an anonymous class:

var users = Users.Select(u => new { Name = u.Name, LastName = u.LastName });
Kobi
I totally understand it's a very poor use of it, but i can't come with a better solution for my situation. This is the whole scenario... i am creating a series of email templates. I want to replace dynamically some texts using regex ex: "Dear [[Name]]" -> Replace([[Name]],Dictionary[Name]... The thing is that i have multiple Entities that i can gather data from. pseudo code is only using the entity User but i might have cases where i use User, UserCredit, UserAddress... so i want to return only those fields i need in my email template. anonymous class would force me to use reflection...
Tony
BTW, your example works like a charm. thank you Kobi
Tony
I did something similar recently, and had a more complex solution. What if you need different entities on the same template? `"Hello [[Name]], You've ordered [[ItemsCount]] items at $[[ItemsPrice]]. Please see <a href='[[TermsURL]]'>Terms of Use</a>"`. I had a `OrderContext` class with `User`, `Order`, etc, and it can replace tokens with the appropriate string. This is probably better than turning each and every entity to a dictionary.
Kobi
I thought about creating a class EmailData with as many prop as needed. Thing is that i have 29 templates and all of'em use a combination of many entities. Then i had to create anyway 29 different linqs to get the data and populate the EmailData object. Then i had to do two things. either hardcode the replace Replace("Hello [[Name]]","[[Name]]",EmailData.Name) or using regex get all those values between [[ ]] and iterate thru that collection and using reflection to call the properties in EmailData EmailData.GetType().GetProperty("Name").GetValue.ToString... so, dictionary seemed easier.
Tony
This thing didnt work. Throw this exception Unrecognized expression node: ListInitI tried adding and removing () after Dictionary<string,string> and no success... Any ideas...
Tony
+1  A: 

Conversion method:

public Dictionary<string, string> ToPropertyDictionary(User theUser)
{
  Dictionary<string, string> result = new Dictionary<string, string>();
  result.Add("Name", theUser.Name);
  result.Add("LastName", theUser.Name);
  return result;
}

Called by:

IEnumerable<Dictionary<string, string>> x =
  from u in Users.AsEnumerable()  //ensure local execution by using AsEnumerable
  select ToPropertyDictionary(u);
David B
An alternative here is to have a common interface for all entities, and have `User.Select(u => u.ToPropertyDictionary())`
Kobi
This thing didnt work. Throw this exception Unrecognized expression node: ListInitI tried adding and removing () after Dictionary<string,string> and no success... Any ideas...
Tony
Users... is it a local collection?
David B
No. Users is a System.Data.Linq.Table<Users> (LINQtoSQL)... i've been reading a lil bit, it seems that linq does not care about the Collection initializer. I can go the old boring way and do a foreach after retrieving the data from the database, but come on... we are in 2010 and i don't think we have to step back five years for something that seems so simple.... i will keep you posted.
Tony
+2  A: 

The "Unrecognized expression node" error you're getting is because LINQ to SQL is failing to turn the dictionary-related code into SQL. You can use AsEnumerable() to make the compiler use LINQ to Objects instead:

var x = from u in Users.AsEnumerable()
        select new Dictionary<string, string> {
            { "Name", u.Name },
            { "LastName", u.LastName }
        };
dahlbyk