【发布时间】: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,并且还尝试避免使用枚举来处理这是典型的代码异味。然而,在我所有的尝试和研究中,我似乎不得不落入以下解决方案之一。
为每种类型实现一个查询 除了 他们过滤的类型和类型 用于投影。虽然这 违反 DRY 和 OCP,我可以 将其封装在一个单一的 上课,让他们靠得很近 作为已编译的查询。这会 如果我添加,需要更改课程 一种新类型,或者您如何查询 数据发生变化。
实现具有类型的枚举,并使用更通用的用户类,该类将其类型作为属性。但是,这将导致我不得不在多个位置使用枚举并引入长 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