您可以将OOP应用于Linq预测吗?

时间:2010-10-01 01:20:23

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

使用

  • Visual Studio 2010
  • .Net Framework 4
  • C#
  • Linq to Entities

问题

我希望能够将像DRY和SOLID这样的面向对象原则应用于一些Linq Projections。使用已编译的查询或传递的参数,我可以成功地将这些应用到Linq的其余部分,而不是在预测中。

如果这是不可能的,请告诉我,我必须选择我的替代解决方案之一(如下所述),如果可能的话如何,或者如果我遗漏某些东西,还有另一种替代实施方案将满足目标。

详细

在高级别,我希望能够使用标准Linq Query或CompiledQuery动态控制Linq Projection中使用的类型。我在我的示例和实际代码中使用Linq to Entities,但问题应该适用于核心Linq。

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

替代解决方案

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

  1. 为每种类型实施查询 这些都是相同的,除了 他们过滤的类型和类型 用于投影。虽然这个 我可以违反DRY和OCP 将其封装在一个单独的内容中 上课,让他们紧密相连 作为编译的查询。这将 如果我添加,则要求更改类 一个新类型或如何查询 数据发生了变化。

  2. 实现具有类型的枚举,并使用其类型为属性的更通用的User类。然而,这将导致我必须在几个位置使用枚举并引入长句例句来处理它们,我想避免这种情况。

  3. 我希望不必在不同的邪恶之间做出选择,并且有一个符合所有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
                           });-
    

1 个答案:

答案 0 :(得分:0)

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

我不知道关于泛型的where语句的Constructor Constraint 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; 
    }
}

我选择发布答案而不是删除问题有两个原因,以防其他人正在寻找类似的东西,这可能会有所帮助。当然,我可能会离开基地,让人们在事物上打洞并看到我们能想出的更好的东西总是很有趣。