避免在Entity Framework中重复投影代码

时间:2010-09-05 13:49:50

标签: c# linq entity-framework entity-framework-4

我正在尝试解决类似于此处描述的问题

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);

但是final终于为null,并且永远不会调用新pocoClass中的代码。我把let x& y在上面,因为这些在每次使用投影之间总是不同的。

那么,我是否必须回到我的投影的多个副本,或者还有另外一种方法吗?

1 个答案:

答案 0 :(得分:12)

我不确定这对您有用,但我经常做的是创建投影方法,该方法采用IQueryable并返回IQueryable以从域对象转换为DTO。他们看起来很像这样:

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

这允许我将这个投影放在一个地方。在我的业务层的几个地方,我称之为这样一种方法。

但有几点需要注意:

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

我希望这会有所帮助。