2

私はC#、.Net 4.5、MVC、エンティティフレームワーク5.0を最初にコードで使用しています。devexpress の例の 1 つを使用するとエラーが発生しました。問題は、groupby 値と集計 (カウント) クエリのリストを取得することにあります。

エラーは、型 'System.Int32' を型 'System.Object' にキャストできません。LINQ to Entities は、大文字と小文字の EDM プリミティブまたは列挙型のみをサポートします

エンティティ/テーブルは

public class Test
{
    [Key]
    public int ID { get; set; }
    public string Name { get; set; }
    public DateTime SubmitDate { get; set; }
    public int TotalValue { get; set; }
}

グループ化情報を取得するテスト コード

public void GetGroupInfo() 
{
    GetGroupInfo(Context.Tests, "TotalValue");
    GetGroupInfo(Context.Tests, "Name");
}

public static void GetGroupInfo(this IQueryable query, string fieldName)
{
    CriteriaToExpressionConverter converter = new CriteriaToExpressionConverter();

    var rowType = query.ElementType;
    query = query.MakeGroupBy(converter, new OperandProperty(fieldName));
    query = query.MakeOrderBy(converter, new ServerModeOrderDescriptor(new OperandProperty("Key"), false));

    /*
      i think the problem is from here
    */
    query = ApplyExpression(query, rowType, "Key", "Count");

    // ignore the GridViewGroupInfo, just a class to store the value
    var list = new List<GridViewGroupInfo>();
    foreach (var item in query)
    {
        var obj = (object[])item;
        list.Add(new GridViewGroupInfo() {KeyValue=obj[0], DataRowCount =(int)obj[1]});
    }
}

static IQueryable ApplyExpression(IQueryable query, Type rowType, params string[] names)   
{
    var parameter = Expression.Parameter(query.ElementType, string.Empty);
    var expressions = names.Select(n => query.GetExpression(n, rowType, parameter));
    var arrayExpressions = Expression.NewArrayInit(
        typeof(object),
        expressions.Select(expr=>Expression.Convert(expr,typeof(object))).ToArray()
    );
    var lambda = Expression.Lambda(arrayExpressions, parameter);

    var expression = Expression.Call(
        typeof(Queryable),
        "Select",
        new Type[] { query.ElementType, lambda.Body.Type },
        query.Expression,
        Expression.Quote(lambda)
    );
    return query.Provider.CreateQuery(expression);
}

static Expression GetExpression(this IQueryable query, string commandName, Type rowType,    ParameterExpression parameter)
{
    switch (commandName)
    {
        case "Key":
            return Expression.Property(parameter, "Key");
        case "Count":
            return Expression.Call(typeof(Enumerable), "Count", new Type[] { rowType }, parameter);
    }
    return null;
}

グループ化が「Name」(文字列)タイプまたは「TotalValue」(int)タイプに関係なく、エラーが発生します。誰でも助けることができますか?この.net、mvc、およびlinq全体についてまだ学んでいるので、誰かがなぜ、何を、どのように教えてくれたら感謝します。

4

1 に答える 1

0

あなたがやろうとしていることは次のようなものだと思います:

Context.Tests.GroupBy(t => t.TotalValue).Select(g => new { Key = g.Key, Count = g.Count() });
Context.Tests.GroupBy(t => t.Name).Select(g => new { Key = g.Key, Count = g.Count() });

しかし、手動で作成されたを使用していExpressionsます。

実際に作成しているものと問題がある場所は、最後の選択です。

 var arrayExpressions = Expression.NewArrayInit(
    typeof(object),
    expressions.Select(expr=>Expression.Convert(expr,typeof(object))).ToArray()
);

次のものと同等のものを提供します:

Select(g => new object[] { (object)g.Key, (object)g.Count() });

実際、このようなクエリを実行しようとすると、LINQ to Entities (さらには Entity Framework も) にキャストできないと不平を言うことになりobjectます。

処理できるのは へのキャストstringです。そう:

Select(g => new string[] { g.Key.ToString(), g.Count().ToString() });

ほぼ問題ありませんが、配列初期化子に問題があります。 ]' 代わりは。" 簡単だ:

Select(g => new List<string> { g.Key.ToString(), g.Count().ToString() });

そして、これを SQL に変換できるようになりました (少なくとも Entity Framework によってですが、Linq to SQL でも処理できると思います)。したがって、これに置き換える必要がありますarrayExpressions

var arrayExpressions = Expression.ListInit(Expression.New(typeof(List<string>)),
                expressions.Select(expr => Expression.Call(expr, "ToString", null)).ToArray()
            );

そして今、それは機能します。

全体として、これは Linq クエリを作成するためのかなり複雑な方法であり、デバッグが難しく、さらに読みにくいものです。ジェネリック型 IQueryable の使用とラムダ式の記述を検討してくださいLinq。これが最初に設計されたものです。手動式を使用している場合、または使用したい場合は、最初に Linq クエリを作成し (おそらくより具体的なケースの場合)、生成された式を分析してから、この式を手動で作成することをお勧めします。

また、この式が生成する SQL クエリを、同じ仕事をする単純な linq クエリと比較してください。最初のクエリはより複雑になります。

于 2014-06-23T07:42:37.567 に答える