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

And*_*iih 5 c# linq entity-framework entity-framework-4

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

在LINQ to Entities中初始化强类型对象

只是完全相反的方向.我的存储库中有许多函数,所有函数都返回相同形状的数据.问题是我的投影代码:

select new pocoClass
 {
   // complex projection that is several pages long includes grabbing a graph of data
 }
Run Code Online (Sandbox Code Playgroud)

目前存在于存储库中的每个查询.我试过将它移动到一个对象初始化器中,但这给了我可怕的"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);
Run Code Online (Sandbox Code Playgroud)

但是这里final始终为null,并且永远不会调用新pocoClass中的代码.我在上面包含了x和y,因为它们在每次使用投影时总是有所不同.

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

Ste*_*ven 12

我不确定这对你有用,但我经常做的是创建一个投影方法,它接受IQueryable并返回一个IQueryable从域对象转换为DTO.他们看起来很像这样:

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

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

但有几点需要注意:

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

我希望这有帮助.