2010-09-05 133 views
5

避免重复投影代码我试图解决类似仅从完全相反的方向这里在实体框架

Initializing strongly typed objects in LINQ to Entities

所描述的存在的问题。我在我的仓库中有许多函数,所有函数都返回相同形状的数据。问题是我的投影代码:

select new pocoClass 
{ 
    // complex projection that is several pages long includes grabbing a graph of data 
} 

目前它存在于存储库中的每个查询。我试图将它移动到一个对象初始值设定项中,但这给我带来了可怕的“LINQ to Entities支持只有无参数的构造函数和初始值设定项”。问题。

我曾尝试分裂成两个查询

var candidates = (from thing in _entities.whatever 
    where (complex.stuff==true) 
    select thing); 

var final = (from thing in candidates.AsEnumerable() 
    let x = thing.ITEMS.Where(blah=>blah.blah==param) 
    let y = x.OTHERITEMS.FirstOrDefault() 
    select new pocoClass(thing,x,y); 

但这里最终总是空,并在新的pocoClass代码永远不会被调用。我在上面包含了let x & y,因为这些投影在每次投影之间总会有所不同。

那么,我必须返回到我的投影的多个副本,或者有另一种方式吗?

回答

12

我不确定这是否适用于您,但我经常做的是创建投影方法,其中需要使用IQueryable并返回IQueryable以将域对象转换为DTO。他们看起来很像这样:

public static IQueryable<CustomerDTO> ToCustomerDTO(
    IQueryable<Customer> customers) 
{ 
    return 
     from customer in customers 
     select new CustomerDTO() 
     { 
      ... 
     }; 
} 

这使我可以在一个地方做这个预测。在我业务层的几个地方,我称之为这种方法。

有几件事情需要注意,虽然:

  • 确保这些投影方法不包含任何业务逻辑。有任何使用情况特定的过滤器会很糟糕。
  • 有时候您有一个DTO,其中包含一个复杂的对象图,您希望从单个查询中有效地从数据库中提取该对象图。有一点创造力,这往往是可能的,但不是当返回IQueryable。在这种情况下,我返回一组DTO。
  • 我将这些投影方法作为静态方法放在DTO类中。虽然这不是一个非常干净的设计,但它发现它使代码非常易于维护。

我希望这有助于。

+0

几乎 - 它的业务逻辑问题 - 在我的例子中是在投影之前为每个客户评估的let语句。 – Andiih 2010-09-05 14:59:41

+0

其实这足以给我一个解决方案。我创建了一个新的简化的DTO中间类,我可以通过复制六个值来进行项目设计:每个类都是一个完整的EF实体。然后,我使用您的解决方案将这些实体进行最终投影。不知道它会如何表现,但它确实整洁! – Andiih 2010-09-05 15:27:25

+0

@Andiih:您将不得不使用SQL分析器来查看在后台执行多少查询。 EF将会在封底之后执行很多查询,这是一个很好的改变。技术 - 当然 - 有其局限性。如果您对性能不满意,并且无法知道如何在单个查询中获得此信息,那么也许我可以为您提供帮助。在这种情况下,请在此处开始一个新问题,并在此处放置一个链接。干杯 – Steven 2010-09-05 16:40:52