我有一个名为ICatalog
如下所示,其中每个ICatalog
有一个名称和一个方法,该方法将根据Predicate<Item>
功能。
public interface ICatalog
{
string Name { get; }
IEnumerable<Item> GetItems(Predicate<Item> predicate);
}
目录的特定实现可以链接到各种格式的目录,例如XML或SQL数据库。
对于 XML 目录,我最终将整个 XML 文件反序列化到内存中,因此使用谓词函数测试每个项目不会增加更多开销,因为它已经在内存中了。
然而,对于 SQL 实现,我宁愿不将数据库的全部内容检索到内存中,然后使用谓词函数过滤项目。相反,我想找到一种方法以某种方式将谓词传递到 SQL 服务器,或者以某种方式将其转换为 SQL 查询。
这似乎是一个可以用 Linq 解决的问题,但我对它还很陌生。我的接口应该返回 IQueryable 吗?我现在不关心如何实际实现 ICatalog 的 SQL 版本。我只是想确保我的界面将来允许这样做。
Rob 已经指出了如何做到这一点(尽管更经典的 LINQ 方法可能需要Expression<Func<Item,bool>>
,并可能返回IQueryable<IFamily>
).
好消息是,如果您想将谓词与 LINQ-to-Objects 一起使用(对于您的 xml 场景),您可以使用:
Predicate<Item> func = predicate.Compile();
或(对于其他签名):
Func<Item,bool> func = predicate.Compile();
并且您有一名代表(func
)来测试你的对象。
但问题是,这是一个恶梦单元测试 - 你只能真正一体化测试一下。
问题是您无法可靠地模拟(使用 LINQ-to-Objects)任何涉及复杂数据存储的内容;例如,以下内容在单元测试中可以正常工作,但不能针对数据库“真正”工作:
var foo = GetItems(x => SomeMagicFunction(x.Name));
static bool SomeMagicFunction(string name) { return name.Length > 3; } // why not
问题是只有部分操作可以转换为TSQL。你遇到同样的问题IQueryable<T>
- 例如,EF 和 LINQ-to-SQL 支持对查询的不同操作;甚至只是First()
行为不同(EF 要求您首先显式排序它,而 LINQ-to-SQL 则不然)。
总结来说:
- 它可以工作
- 但要仔细考虑一下你是否想这样做;更经典的黑盒存储库/服务接口可能更易于测试
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)