Eri*_*tas 9 .net c# linq iqueryable
我有一个名为ICatalog如下所示的接口,其中每个接口ICatalog都有一个名称和一个基于Predicate<Item>函数返回项目的方法.
public interface ICatalog
{
string Name { get; }
IEnumerable<Item> GetItems(Predicate<Item> predicate);
}
Run Code Online (Sandbox Code Playgroud)
目录的特定实现可以链接到各种格式的目录,例如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();
Run Code Online (Sandbox Code Playgroud)
或(对于其他签名):
Func<Item,bool> func = predicate.Compile();
Run Code Online (Sandbox Code Playgroud)
你有一个委托(func)来测试你的对象.
但问题是,这是单元测试的噩梦 - 你只能真正集成测试它.
问题是你不能可靠地模拟(使用LINQ-to-Objects)任何涉及复杂数据存储的东西; 例如,以下内容在单元测试中可以正常工作,但不能对数据库"真实"工作:
var foo = GetItems(x => SomeMagicFunction(x.Name));
static bool SomeMagicFunction(string name) { return name.Length > 3; } // why not
Run Code Online (Sandbox Code Playgroud)
问题是只有一些操作可以转换为TSQL.您遇到同样的问题IQueryable<T>- 例如,EF和LINQ-to-SQL支持对查询的不同操作; 甚至只是First()表现不同(EF要求你先明确订购它,LINQ-to-SQL不要).
总结如下:
您无需一直进行创建IQueryable实现
如果将GetItems方法声明为:
IEnumerable<IFamily> GetItems(Expression<Predicate<Item>> predicate);
Run Code Online (Sandbox Code Playgroud)
然后,您的实现类可以检查Expression以确定要求的内容.
请阅读IQueryable文章,因为它解释了如何构建表达式树访问者,您需要构建一个简单版本的.
| 归档时间: |
|
| 查看次数: |
891 次 |
| 最近记录: |