在有人要求之前,我知道已经有一个Neo4jClient存储库,但它已过时且尚未针对Neo4j 2.x和新的Neo4jClient代码进行更新 .
我的目标是实现这样的目标:
var profiles = profileRepository.Get((Data.Model.Profile profile) => profile.Age > 20);
我首先尝试通过将谓词传递给Where调用并在CypherFluentQuery上执行Return来手动构建表达式,但是谓词参数与我在Return调用中的参数不匹配:
return client.Cypher
.Match("(entity:" + _entityTypeName + ")")
.Where(predicate)
.Return(entity => entity.As<TEntity>)
.Results.FirstOrDefault();
这最终是我决定我需要动态构建返回表达式的原因,这样它才能正确命名参数以传递给Neo4jClient,而不会返回未定义的异常 .
但是,我完全理解如何构建表达式树 . 这是我的Neo4jRepository Get :
using Neo4jClient;
using Neo4jClient.Cypher;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace Data.Repository
{
public class Neo4jRepository<TEntity> : IRepository<TEntity>
{
private List<TEntity> _entities;
private string _entityTypeName;
public Neo4jRepository()
{
_entities = new List<TEntity>();
Type entityType = typeof(TEntity);
_entityTypeName = entityType.Name;
}
public virtual IEnumberable<TEntity> Get(Expression<Func<TEntity, bool>> predicate)
{
var client = new GraphClient(
new Uri("http://localhost:7474/db/data"));
client.Connect();
ParameterExpression parameter =
Expression.Parameter(typeof(
Expression<Func<ICypherResultItem, TEntity>>),
predicate.Parameters[0].Name);
var exp = Expression.Lambda<Func<ICypherResultItem, TEntity>>(
parameters: parameter,
body: Expression.Call(
instance: Expression.Default(typeof(ICypherResultItem)),
methodName: "As",
typeArguments: new[] { typeof(TEntity) }
)
);
return client.Cypher
.Match("(entity:" + _entityTypeName + ")")
.Where(predicate)
.Return(exp)
.Results;
}
}
}
这是我的IRepository:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace Data.Repository
{
/// <summary>
/// Generic repository that can be used with any data backend
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
interface IRepository<TEntity>
{
IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> predicate);
void Add(TEntity item);
void Update(Func<TEntity,bool> predicate, TEntity item);
void Delete(TEntity item);
void SaveChanges();
}
}
当我尝试使用谓词进行get时,编译器不接受我的lambda表达式:
类型'System.Linq.Expressions.Expression1 [System.Func2 [Neo4jClient.Cypher.ICypherResultItem,Data.Model.Profile]]'的ParameterExpression不能用于'Neo4jClient.Cypher.ICypherResultItem'类型的委托参数
如何根据我的输入谓词构建一个带有动态参数名称的表达式,该谓词适合像 entity => entity.As<TEntity>
这样的Return调用?
1 回答
经过一段时间的修补,我想出了一个通用的存储库:https://github.com/pcmantinker/Neo4jRepository
以下是一些示例用法:
BlogPost.cs
BlogPostRepository.cs
示例程序:
实体必须从Neo4jEntity继承,以引用该实体的节点上的标签 . 通过使存储库具有通用性,我们可以轻松地为使用标准CRUD操作从Neo4jRepository继承的任何东西站起来 .