views:

223

answers:

2

Is it possible to make some work in parallel with entity framework for following example?

using (var dbContext = new DB())
{
var res = (from c in dbContext.Customers
           orderby c.Name
           select new
                    {
                    c.Id, 
                    c.Name,
                    c.Role
                    }
          ).ToDictionary(c => c.Id,
                         c => new Dictionary<string, object> {
                                                               { "Name",c.Name },
                                                               { "Role", c.Role }
                                                             });
}

For exampe what will be changed if I add AsParrallel?

using (var dbContext = new DB())
{
var res = (from c in dbContext.Customers
           orderby c.Name
           select new
                    {
                    c.Id, 
                    c.Name,
                    c.Role
                    }
          ).AsParallel().ToDictionary(c => c.Id,
                         c => new Dictionary<string, object> {
                                                               { "Name",c.Name },
                                                               { "Role", c.Role }
                                                             });
}

And one more example. The question is same what are the differences in 3 examples.

using (var dbContext = new DB()) 
{ 
var res = (from c in dbContext.Customers.AsParallel() 
           orderby c.Name 
           select new 
                    { 
                    c.Id,  
                    c.Name, 
                    c.Role 
                   } 
          ).AsParallel().ToDictionary(c => c.Id, 
                         c => new Dictionary<string, object> { 
                                                               { "Name",c.Name }, 
                                                               { "Role", c.Role } 
                                                             }); 
} 
+2  A: 

No, the query is run on the database, not in the client. The database may do the query using multiple threads to accelerate the process, but in any case you can't combine server-side processing with client-side Parallel Extensions.

Allon Guralnek
And in such case what is the difference between two examples?
mehanik
I'm not sure. Either `AsParallel()` will throw an exception or it won't alter the enumerable.
Allon Guralnek
No it works without exceptions.
mehanik
So it does nothing. If you were talking about a local collection of objects, then it would be useful and would probably decrease the time it takes to execute the query. But in your case there's little Parallel Extensions can do when it's all happening elsewhere (on the database).
Allon Guralnek
Yes no parallel actions on database side. But if query returns big number of results the dictionary creation wiil be faster with AsParallel. But in debug I don't see any parallel threads. So in such case AsParallel does nothing?
mehanik
The Dictionary class is not thread safe, so PE can't insert items in parallel, so AsParallel indeed does nothing in that case. And there are parallel actions on the database side, but they have nothing to do with PE and they're done automatically.
Allon Guralnek
Also, you didn't use the ToDictionary method correctly. You are creating a dictionary where each value of the dictionary is its own dictionary which has two entries. I think what you meant to do is simply `.ToDictionary(c => c.Id)`.
Allon Guralnek
Ok. Thanks..ToDictionary(c => c.Id) - will return result Dictionary<int, anonymous type>And in such case I can't return such result from method.I have method:public IDictionary<long, Dictionary<string, object>> GetCustomers()So I can't do followingpublic IDictionary<long, anonymous type> GetCustomers()
mehanik
Why not just return an `IDictionary<long, Customer>`?
Allon Guralnek
Customer entity has many other fields and don't need to get all of them from db.
mehanik
You can define a new class with those three fields for the return value, which would solidify the method signature and make the return value clear to any consumers, a best practice. If you don't want to use that, return Customer objects with only the needed fields filled in: `.ToDictionary(c => c.Id, c => new Customer { Id = c.Id, Name = c.Name, Role = c.Role })`. In any case, I'd never use dictionaries to express values of a static type.
Allon Guralnek
A: 

You can with PLINQ (Parallel LINQ)

http://msdn.microsoft.com/en-us/library/dd460688.aspx

http://msdn.microsoft.com/en-us/magazine/cc163329.aspx

For example (from above):

IEnumerable data = ...; var q = data.AsParallel().Where(x => p(x)).Orderby(x => k(x)).Select(x => f(x));

foreach (var e in q) a(e);

For the foreach you could also look as using the TPL (Task Parallel Library) version. http://msdn.microsoft.com/en-us/library/dd460717(v=VS.100).aspx

Doobi
Is it possible use PLINQ for EntityFramework?It is not real application. I wnat to understand differences in examples in theory? How it will work? Is some threads will be created or not?
mehanik