【问题标题】:Can you apply OOP to Linq Projections?您可以将 OOP 应用于 Linq 投影吗?
【发布时间】:2010-10-01 01:20:23
【问题描述】:

使用

  • Visual Studio 2010
  • .Net 框架 4
  • C#
  • Linq 到实体

问题

我希望能够将 DRY 和 SOLID 等面向对象的原则应用于一些 Linq 投影。到目前为止,通过编译查询或传递参数,我可以成功地将这些应用到 Linq 的其余部分,而不是在预测中。

如果这不可能,请告诉我,我必须选择我的替代解决方案之一(如下所述),如果可能,那么如何,或者如果我遗漏了什么并且有另一种替代实现可以满足目标。

详情

在高层次上,我希望能够使用标准 Linq 查询或 CompiledQuery 动态控制 Linq 投影中使用的类型。我在示例和实际代码中使用 Linq to Entities,但该问题应该适用于核心 Linq。

以下是非动态且无法解决问题的简单示例。它们被固定为始终对每种类型使用 FooUser。我想要做的是动态控制在投影中创建的用户类型,所有这些都将基于一个通用的 IUser 接口。这将或可能类似于我如何控制查询过滤器的类型。

替代解决方案

我正在尝试遵守 DRY、SOLID,并且还尝试避免使用枚举来处理这是典型的代码异味。然而,在我所有的尝试和研究中,我似乎不得不落入以下解决方案之一。

  1. 为每种类型实现一个查询 除了 他们过滤的类型和类型 用于投影。虽然这 违反 DRY 和 OCP,我可以 将其封装在一个单一的 上课,让他们靠得很近 作为已编译的查询。这会 如果我添加,需要更改课程 一种新类型,或者您如何查询 数据发生变化。

  2. 实现具有类型的枚举,并使用更通用的用户类,该类将其类型作为属性。但是,这将导致我不得不在多个位置使用枚举并引入长 case 语句来处理它们,我想避免这种情况。

我希望不必在不同的弊端之间做出选择,并且有一个可以符合所有 SOLID 原则和 DRY 的实现。但是,如果必须,我想我最终会得到它的第一个或一个版本。

示例

标准的简单 Linq 查询

using (MyEntities context = new MyEntities())
{
    var results = from u in context.Users
                  where u.UserType == type
                  select new FooUser
                  {
                      Id = u.UserID,
                      Name = u.UserName,
                      Location = u.UserLocation
                  };
}

上述查询的编译版本

private static readonly Func<MyEntities, int, IQueryable<FooUser>> query = CompiledQuery.Compile<MyEntities, int, IQueryable<FooUser>>(
    (context, type) => from u in context.Users
                       where u.UserType == type
                       select new FooUser
                       {
                           Id = u.UserID,
                           Name = u.UserName,
                           Location = u.UserLocation
                       });-

【问题讨论】:

  • 恐怕我不明白你问的问题。您能指出您希望消除的重复代码吗?
  • 替代解决方案部分解释了重复的代码,这是我试图避免的。示例代码只是为了显示一个查询示例,以便在需要时进行交谈。我发布了一个适合我的解决方案,如果您有更好的解决方案,请随时发布。特别是如果通过编译查询可以做到这一点。

标签: c# linq oop linq-to-entities design-principles


【解决方案1】:

我找到了一种使用标准方法调用的方法。我还没有弄清楚如何使用已编译的查询来做到这一点,看起来不太可能。

我不知道泛型的 where 语句中的构造函数约束 I。这可以满足我的需要。我很想用编译的查询来做到这一点,但可以对这个解决方案感到满意。

public IQueryable<IUser> FooMethod<T>(int type) where T : IUser, new()
{
    using (MyEntities context = new MyEntities())
    {
        var results = from u in context.users
                      where u.usertype == type
                      select new T
                      {
                          id = u.UserId,
                          name = u.UserName,
                          location = u.Userlocation
                      };
        return results; 
    }
}

我选择发布答案而不是删除问题有两个原因,一个是如果其他人正在寻找类似的东西,它可能会有所帮助。当然,我可能会偏离基础,让人们在事物上打出漏洞并看看我们能想出什么更好的东西总是很有趣。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-09
    • 1970-01-01
    • 2019-12-15
    • 2015-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多