在 Linq to SQL 中使用委托进行投影

9
我在 Linq to Sql 的 IRepository 实现中编写了以下代码:

我在 Linq to Sql 的 IRepository 实现中编写了以下代码:

var newlist = from h in list where h.StringProp1 == "1"
                      select new MyBusinessBO{
                          firstProp = h.StringProp1,
                          secondProp = h.StringProp2
                      };

将投影映射到MyBusinessBO并不困难,但当业务对象具有许多属性时,投影代码变得非常冗长。此外,由于投影可以在存储库中的多个位置发生,因此我们违反了DRY原则。

有没有办法抽象出投影或用委托替换它?

例如,替换代码:

                          firstProp = h.StringProp1,
                          secondProp = h.StringProp2

使用可重复利用的东西?

4个回答

7
你可以使用点语法而不是LINQ风格的语法来解决这个问题。
你当前的:
list
    .Where(h => h.StringProp1 == "1")
    .Select(h => new MyBusinessBO
    {
        firstProp = h.StringProp1,
        secondProp = h.StringProp2
    });

可能的解决方案:

Func<MyType, MyBusinessBO> selector = h => new MyBusinessBO
{
    firstProp = h.StringProp1,
    secondProp = h.StringProp2
};
list
    .Where(h => h.StringProp1 == "1")
    .Select(selector);

您可以在某个地方传递选择器,或者动态生成选择器等类似方法。


不错的回答。我甚至会更进一步,将Func定义为一个真正的方法。原帖作者想要重用那个投影逻辑。 - Steven
在使用这个答案之前需要考虑一个问题,即Func<MyType, MyBusinessBO>无法使用Entity Framework投影到SQL。我知道这个问题是针对Linq-to-SQL的,它可能能够完成投影,但是为了编写更具时间性的代码,将您的变量设置为Expression<Func<MyType,MyBusinessBO>>可能更好。 - ErikE

5

Queryable.Select 需要一个 Expression<Func<T, U>>。您可以编写一个返回此内容的方法,并在进行转换时随处使用该方法。

public Expression<Func<DataObj, BusiObj>> GetExpr()
{
  return h => new BusiObj()
  {
    firstProp = h.StringProp1,
    secondProp = h.StringProp2
  };
}


 //get a local variable holding the expression.
Expression<Func<DataObj, BusiObj>> toBusiObj = GetExpr();

//use it thusly
var newList = (from h in list where h.StringProp1 == "1" select h)
  .Select(toBusiObj)
  .ToList();

//or
List<BusiObj> newList = list
  .Where(h => h.StringProp1 == "1")
  .Select(toBusiObj)
  .ToList();

与ckknight的方法非常相似,但这似乎更适合用于创建更清晰的代码。它将投影放在一个单独的可重用函数中,可以随意传递。ckknight提供了答案,但David B以一种让我达到想要的目标的方式解决了问题。我已经点赞了ckknight的回答并接受了这个回答。 - Redeemed1
请注意:对于 GetExpr() 函数,使用此处显示的确切语法非常重要。如果您已经在多个地方使用了预先存在的 DTE 转换方法(例如 public DTE Convert(Entity entity)),并且正在尝试将其转换为可重用表达式,则必须删除 entity 参数并按照此处所示创建 lambda 表达式 - 否则将检索该表中的每一列。 - Simon_Weaver

0

是的,实际上已经广泛使用了自动映射器,但在这种情况下它并不是最佳选择。 - Redeemed1

0
也许可以使用常规的非默认构造函数,而不是对象初始化程序。或者,如果您可以开始使用C# 4.0,则尝试将可选/默认参数添加到组合中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接