gpt4 book ai didi

c# - Linq to entities 无法识别方法 system.string get_Item

转载 作者:太空宇宙 更新时间:2023-11-03 22:50:21 27 4
gpt4 key购买 nike

我正在尝试将 orderByExpression 传递给在 Entity Framework 中的 dbContext 对象上使用它的函数

> Dictionary<int, string> dict = new Dictionary<int, string>();
> Expression<Func<DbQuestion, string>> orderByExpression = r => dict[r.Id];

这会引发以下错误。

Exception=Exceptions.DBConnectionException: LINQ to Entities does not recognize the method 'System.String get_Item(Int32)' method, and this method cannot be translated into a store expression.

我了解我无法访问 Linq to Sql 查询中的 [ ]。您能否提出替代方案或为我指明正确的方向?

编辑:

关于我要解决的问题的更多细节:

字典有 15-20 个项目,键保持不变,只有值动态变化

我正在尝试根据 r.Id 的范围对问题进行排序,即如果 floor(r.Id)==14 那么我返回“a”,如果它在 floor(r.Id)==15 之间那么我返回“b”,如果它在 floor(r.id)==13 之间,我返回“c”(由字典中的值决定)这有助于对行进行排序

这是实际的表达方式:

List<int> cqh;
List<int> iqh;
Expression<Func<DbQuestion, string>> orderByExpression = r => cqh.Contains(r.QuestionID)? dict[(int)Math.Floor(r.SearchKey1)] +"2"+Guid.NewGuid() :
iqh.Contains(r.QuestionID)? dict[(int)Math.Floor(r.SearchKey1)] + "1"+Guid.NewGuid() :
dict[(int)Math.Floor(r.SearchKey1)] + "0"+Guid.NewGuid();

谢谢,

最佳答案

我看到两个选项,一个是使用 LINQ to Entities

  1. 将字典中的数据放在一个单独的表中,保存起来,然后加入表中。即使您需要每个查询数据,也可以应用此解决方案。

示例:

public class SortKey
{
[Key]
public int SortKeyId { get; set; }
public long SearchId { get; set; }
public int EntityId { get; set; }
public string SortId { get; set; }
}

using (var db = new Db())
{
Dictionary<int, string> dict = new Dictionary<int, string>();
long searchId = DateTime.Now.Ticks; // Simplfied, either use a guid or a FK to another table
db.Keys.AddRange(dict.Select(kv => new SortKey { SearchId = searchId, EntityId = kv.Key, SortId = kv.Value }));
db.SaveChanges();

var query = from e in db.Entity
join k in db.Keys.Where(k => k.SearchId == searchId) on (int)e.Id equals k.EntityId
orderby k.SortId
select e;
}

// Cleanup the sort key table
  1. 动态构建条件。这可以使用表达式操作来实现

示例:

Expression exp = Expression.Constant(""); //Default order key
var p = Expression.Parameter(typeof(Entity));
foreach (var kv in dict)
{
exp = Expression.Condition(
Expression.Equal(
Expression.Convert(
Expression.MakeMemberAccess(p, p.Type.GetProperty("Id")), typeof(int)
),
Expression.Constant(kv.Key)
),
Expression.Constant(kv.Value),
exp
);
}

var orderByExp = Expression.Lambda<Func<Entity, string>>(exp, p);

var query = db.Entity.OrderBy(orderByExp);

您使用哪个选项取决于字典中的数据量。为 OrderBy 构建的条件对于大量数据可能会变得非常低效

编辑

基于更改后的问题,您可以使用表达式访问者将 dic[...] 调用替换为字典中每个值的条件测试。这种方法的优点是您可以轻松更改表达式,替换将以相同的方式工作

类(class):

class DictionaryReplaceVisitor : ExpressionVisitor
{
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if(node.Object != null && node.Object.Type == typeof(Dictionary<int, string>) && node.Method.Name == "get_Item")
{
Expression exp = Expression.Constant(""); //Default order key
// Compile the tahrget of the index and execute it to get the value
// If you know there is a single dictionary you could replace this with a class property intead and set it from the Visit call site,
// but this is the more general appraoch
var dict = Expression.Lambda<Func<Dictionary<int, string>>>(node.Object).Compile()();
foreach (var kv in dict)
{
exp = Expression.Condition(
Expression.Equal(
node.Arguments.Single(),
Expression.Constant(kv.Key)
),
Expression.Constant(kv.Value),
exp
);
}

return exp;
}
return base.VisitMethodCall(node);
}
}

用法:

Expression<Func<Entity, string>> orderByExpression = r => cqh.Contains(r.QuestionID) ? dict[(int)Math.Floor(r.SearchKey1)] + "2" + Guid.NewGuid() :
iqh.Contains(r.QuestionID) ? dict[(int)Math.Floor(r.SearchKey1)] + "1" + Guid.NewGuid() :
dict[(int)Math.Floor(r.SearchKey1)] + "0" + Guid.NewGuid();
var replace = (Expression<Func<Entity, string>>)new DictionaryReplaceVisitor().Visit(orderByExpression);

var query = db.Entity.OrderBy(replace).ToString();

生成的 SQL 不会很漂亮,但它应该可以工作。

解决方案 3:

如果数据量不是很大,可以在查询上做一个ToListAsEnumerable,然后在内存中排序(通过调用 OrderBy 在上述方法之一之后)。在这种情况下它实际上可能表现得更好

关于c# - Linq to entities 无法识别方法 system.string get_Item,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47670566/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com