2012-11-08 207 views
0

您好,我刚开始尝试并了解Parallel Linq,并在第一次尝试时没有成功。我正在使用EF 4.0和我创建的存储库模式类来查询数据。我不相信存储库模式是问题,但我可能会误解。并行Linq查询无法执行

我拥有的数据库没有设置我想要的方式,但是我继承了系统。那我有问题的代码如下:

  var gId = Sql.ToGuid(Request["ID"]); 

      var lOrdersGridList = new OrdersGridList(); //Class that only contains properties 

      var lOrdersForContact = new BaseRepository<ORDER>() 
       .Find(i => i.ORDERS_CONTACTS.Where(b => b.CONTACT_ID == gId).Count() > 0).AsParallel() 
       .Select(i => 
        new OrdersGridList 
         { 
          ORDER_ID = i.ID, 
          ORDER_NUM = i.ORDER_NUM, 
          SHIPPING_ACCOUNT_ID = i.ORDERS_ACCOUNTS.Where(b => b.ORDER_ID == i.ID && b.ACCOUNT_ROLE == "Ship To").First().ACCOUNT_ID, 
          SHIPPING_ACCOUNT_NAME = i.ORDERS_ACCOUNTS.Where(b => b.ORDER_ID == i.ID && b.ACCOUNT_ROLE == "Ship To").First().ACCOUNT.NAME, 
          SHIPPING_CONTACT_ID = i.ORDERS_CONTACTS.Where(b => b.ORDER_ID == i.ID && b.CONTACT_ROLE == "Ship To").First().CONTACT_ID, 
          SHIPPING_CONTACT_NAME = i.ORDERS_CONTACTS.Where(b => b.ORDER_ID == i.ID && b.CONTACT_ROLE == "Ship To") 
                   .Select(b => new { SHIPPING_CONTACT_NAME = (b.CONTACT.FIRST_NAME + ' ' + b.CONTACT.LAST_NAME) }).First().SHIPPING_CONTACT_NAME, 
          NAME = i.NAME 

         }).DefaultIfEmpty(lOrdersGridList).ToList<OrdersGridList>(); 


      grdMain.DataSource = lOrdersForContact.ToDataTable().DefaultView; //ToDataTable extension function converts the List Object to a datatable. 

如果我运行的代码,而无需进行AsParallel的代码没有问题,执行不过,一旦我添加进行AsParallel我收到以下错误:

error message

而且万一你想看看这是我声明作为新的选择上面的类:

public class OrdersGridList : EntityObject 
{ 
    public string ORDER_NUM { get; set; } 

    public Guid ORDER_ID { get; set; } 

    public Guid SHIPPING_ACCOUNT_ID { get; set; } 

    public string SHIPPING_ACCOUNT_NAME { get; set; } 

    public Guid SHIPPING_CONTACT_ID { get; set; } 

    public string SHIPPING_CONTACT_NAME { get; set; } 

    public string NAME { get; set; } 
} 

如果我删除所有用于检索在选择数据我没有收到任何错误的关系:

   var lOrdersForContact = new BaseRepository<ORDER>() 
       .Find(i => i.ORDERS_CONTACTS.Where(b => b.CONTACT_ID == gId).Count() > 0).AsParallel() 
       .Select(i => 
        new OrdersGridList 
         { 
          ORDER_ID = i.ID, 
          ORDER_NUM = i.ORDER_NUM, 
          //SHIPPING_ACCOUNT_ID = i.ORDERS_ACCOUNTS.Where(b => b.ORDER_ID == i.ID && b.ACCOUNT_ROLE == "Ship To").First().ACCOUNT_ID, 
          //SHIPPING_ACCOUNT_NAME = i.ORDERS_ACCOUNTS.Where(b => b.ORDER_ID == i.ID && b.ACCOUNT_ROLE == "Ship To").First().ACCOUNT.NAME, 
          //SHIPPING_CONTACT_ID = i.ORDERS_CONTACTS.Where(b => b.ORDER_ID == i.ID && b.CONTACT_ROLE == "Ship To").First().CONTACT_ID, 
          //SHIPPING_CONTACT_NAME = i.ORDERS_CONTACTS.Where(b => b.ORDER_ID == i.ID && b.CONTACT_ROLE == "Ship To") 
          //         .Select(b => new { SHIPPING_CONTACT_NAME = (b.CONTACT.FIRST_NAME + ' ' + b.CONTACT.LAST_NAME) }).First().SHIPPING_CONTACT_NAME, 
          NAME = i.NAME 

         }).DefaultIfEmpty(lOrdersGridList).ToList<OrdersGridList>(); 

我很乐意在必要时提供更多的信息更多。任何帮助你可以提供使用PLinq我将不胜感激。

+0

'BaseRepository​​'是'DbContext'的包装? dbcontext使用LINQ查询来构造要发送的SQL表达式,因此并行化查询没有帮助。 – Tejs

+1

从我记得,它共享相同的DbContext,它并不适用于并行查询,因为它打开并关闭每个并行请求期间的连接。既然如此,它将会失败,因为你使用了相同的底层连接并试图多次打开它(这是行不通的)。 – SPFiredrake

+1

你应该能够并行查询(取决于你的提供者),但是我怀疑PLinq知道如何去做。你的错误似乎表明了这一点,想到的直接原因是数据库不支持多个查询缓存,因此单个提供者不能提供并行功能,当你尝试打开另一个连接时,它会抛出一个错误。如果你真的需要并行功能,你可以通过克隆提供者然后对查询进行多线程来以旧式的方式来完成。 – user1793607

回答

0

对我来说,看起来像BaseRepository类使用FindSelect参数创建某种类型的LINQ to Entities查询。

使用AsParellel是为LINQ to Objects创建的,其中您的代码实际上是,其计算结果为您传递的表达式。其他LINQ语言,包括LINQ to Entities,将其翻译成不同的查询语言,如SQL。 SQL服务器本身可以做合理的并行化。