gpt4 book ai didi

c# - 如何反射(reflect) T 以构建查询的表达式树?

转载 作者:太空宇宙 更新时间:2023-11-03 18:17:02 25 4
gpt4 key购买 nike

我正在尝试构建一个通用类来处理来自 EF 的实体。这个类与存储库对话,但正是这个类创建了发送到存储库的表达式。无论如何,我只是想实现一种虚拟方法,作为常见查询的基础。具体来说,它将接受一个 int它只需要对相关实体的主键执行查询。

我一直在搞砸它,我已经建立了一个可能会或可能不会起作用的反射。我这么说是因为我得到了 NotSupportedException带有 LINQ to Entities 的消息无法识别方法 'System.Object GetValue(System.Object, System.Object[])' 方法,并且此方法无法转换为存储表达式。因此,我尝试了另一种方法,它产生了相同的异常,但错误是 LINQ to Entities 不支持 LINQ 表达式节点类型“ArrayIndex”。我知道这是因为 EF 不会像 L2S 那样解析表达式。

无论如何,我希望有更多经验的人可以为我指明正确的方向。我正在通过我所做的两次尝试发布整个类(class)。

public class Provider<T> where T : class {
protected readonly Repository<T> Repository = null;

private readonly string TEntityName = typeof(T).Name;

[Inject]
public Provider(
Repository<T> Repository) {
this.Repository = Repository;
}

public virtual void Add(
T TEntity) {
this.Repository.Insert(TEntity);
}

public virtual T Get(
int PrimaryKey) {
// The LINQ expression node type 'ArrayIndex' is not supported in
// LINQ to Entities.
return this.Repository.Select(
t =>
(((int)(t as EntityObject).EntityKey.EntityKeyValues[0].Value) == PrimaryKey)).Single();

// LINQ to Entities does not recognize the method
// 'System.Object GetValue(System.Object, System.Object[])' method,
// and this method cannot be translated into a store expression.
return this.Repository.Select(
t =>
(((int)t.GetType().GetProperties().Single(
p =>
(p.Name == (this.TEntityName + "Id"))).GetValue(t, null)) == PrimaryKey)).Single();
}

public virtual IList<T> GetAll() {
return this.Repository.Select().ToList();
}

protected virtual void Save() {
this.Repository.Update();
}
}

更新 对于@Gabe

这是我的存储库类的样子:
public class Repository<T> where T : class {
protected readonly ObjectContext ObjectContext = null;
private readonly IObjectSet<T> ObjectSet = null;

[Inject]
public Repository(
ObjectContext ObjectContext) {
this.ObjectContext = ObjectContext;

this.ObjectSet = this.ObjectContext.CreateObjectSet<T>();
}

public virtual void Delete(
T Entity) {
this.ObjectSet.DeleteObject(Entity);
}

public virtual void Insert(
T Entity) {
this.ObjectSet.AddObject(Entity);
}

public virtual IQueryable<T> Select() {
return this.ObjectSet;
}

public virtual IQueryable<T> Select(
Expression<Func<T, bool>> Selector) {
return this.ObjectSet.Where(Selector);
}

public virtual void Update() {
this.ObjectContext.SaveChanges();
}
}

方法的名称基于 SQL 函数,而不是基于 LINQ 方法,我认为您对我的存储库的运行方式感到困惑。

最佳答案

正如 Pauli 所暗示的,您需要手动创建 Expression树,尽管在这种情况下不需要反射。以下是如何编写 Get功能:

public virtual T Get(
int PrimaryKey)
{
var param = Expression.Parameter(typeof(T));
// create expression for param => param.TEntityNameId == PrimaryKey
var lambda = Expression.Lambda<Func<T, bool>>(
Expression.Equal(
Expression.Property(param, TEntityName + "Id"),
Expression.Constant(PrimaryKey)),
param);
return this.Repository.Single(lambda);
}

另外,请注意您的 GetAll函数不需要 Select -- return Repository.ToList();也可以。

关于c# - 如何反射(reflect) T 以构建查询的表达式树?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4632778/

25 4 0
文章推荐: c# - WCF - 自定义绑定(bind)的配置
文章推荐: python - 如何仅将嵌套列表的某些字符串转换为整数?
文章推荐: ruby-on-rails - 如何使用
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com