我正在尝试实现搜索数据库的方法.
我忘了提到我正在使用Postgresql,所以我不能使用内置的LINQ to SQL.
我希望它是那样的:
var user = User.Find(a => a.LastName == "Brown");
Run Code Online (Sandbox Code Playgroud)
就像它在List类中完成的一样.但是当我去List的源代码(谢谢,Reflector)时,我看到了这个:
public T Find(Predicate<T> match)
{
if (match == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
}
for (int i = 0; i < this._size; i++)
{
if (match(this._items[i]))
{
return this._items[i];
}
}
return default(T);
}
Run Code Online (Sandbox Code Playgroud)
我怎么能实现这个呢?我需要获取这些参数来进行搜索.
解
好吧,我现在明白我需要做LINQ to SQL来做所有这些好的表达式的东西,否则我将不得不花费大量时间重新完成轮子.
由于我不能使用LINQ to SQL,我实现了这个简单的方法:
public static User Find(User match, string orderBy = "")
{
string query = "";
if (!String.IsNullOrEmpty(match.FirstName)) query += "first_name='" + match.FirstName + "'";
if (!String.IsNullOrEmpty(match.LastName)) query += "last_name='" + match.LastName+ "'";
return Find(query + (!String.IsNullOrEmpty(orderBy) ? orderBy : ""));
}
Run Code Online (Sandbox Code Playgroud)
这是如何使用它:
var user = User.Find(new User { FirstName = "Bob", LastName = "Brown" });
Run Code Online (Sandbox Code Playgroud)
你的方法应该接受Expression<Func<User>>.
这将为您提供表达式树而不是委托,您可以分析和序列化为SQL或转换为您的数据库具有的任何其他API调用.
如果您希望所有内容都是通用的,您可能希望继续实现IQueryable接口.有用的信息可以在这里找到:LINQ技巧:实现IQueryable提供程序
虽然对于一个简单的场景我建议不要复杂化所有内容并坚持使用表达式树并返回普通IEnumerable<T>或偶数List<T>.
对于您的情况,第一版代码可能如下所示:
public IEnumerable<T> Get(Expression<Func<T, bool>> condition)
{
if (condition.Body.NodeType == ExpressionType.Equal)
{
var equalityExpression = ((BinaryExpression)condition.Body);
var column = ((MemberExpression)equalityExpression.Left).Member.Name;
var value = ((ConstantExpression)equalityExpression.Right).Value;
var table = typeof(T).Name;
var sql = string.Format("select * from {0} where {1} = '{2}'", table, column, value);
return ExecuteSelect(sql);
}
return Enumerable.Empty<T>();
}
Run Code Online (Sandbox Code Playgroud)
当您想要处理新的和新的场景时,它的复杂性会快速增长,因此请确保您为每个场景都有可靠的单元测试.
Visual Studio 2008的C#示例包含ExpressionTreeVisualizer将帮助您更轻松地深入了解表达式树,以了解如何从中提取所需的信息.
当然,如果您坚持使用现有的LINQ实现,我建议您这样做.有Linq to SQLSQL Server数据库,Linq to Entities为许多不同的数据库,Linq to NHibernate为NHbernate项目.
许多其他LINQ提供程序可以在这里找到:链接到一切:LINQ提供程序列表.实现LINQ提供程序的工作量并不重要,因此重用经过测试和支持的解决方案是个好主意.