Entity Framework如何管理映射查询结果为匿名类型?

Mik*_*ike 5 c# linq-to-entities entity-framework entity-framework-4

请考虑以下示例LINQ to entity查询

from history in entities.foreignuserhistory
select new { history.displayname, login=history.username, history.foreignuserid }
Run Code Online (Sandbox Code Playgroud)

ToTraceString() 返回字符串看起来像:

SELECT "Extent1"."foreignuserid" AS "foreignuserid",
   "Extent1"."displayname"       AS "displayname",
   "Extent1"."username"          AS "username"
FROM "integration"."foreignuserhistory" AS "Extent1"
Run Code Online (Sandbox Code Playgroud)

对我来说问题是列与查询的顺序不同,并且不会像login示例中那样使用别名.Entity Framework在哪里存储匿名类型的映射信息?

背景:我将使用LINQ to entity为大规模操作开发带有select操作的insert.

更新: 使用select进行插入并不困难,除了未知列到属性映射算法.可以ObjectSet使用元数据获取目标的表和列名,构建INSERT INTO tableName (column_name1, …)sql语句字符串,然后附加一些ObjectQuery.ToTraceStringSELECT语句.然后DbCommand使用((EntityConnection)ObjectContext.Connection).StoreConnection和填充命令的参数创建一个带有结果的文本ObjectQuery.所以问题是在插入和选择的记录中找到匹配的列顺序.

Mik*_*ike 4

Here\xe2\x80\x99是我的解决方案,包括私有和内部。它通过反射进入缓存的查询计划,该计划将在ToTraceString调用或查询执行后存在以获取所调用的内容_columnMap。列映射包含ScalarColumnMap按匿名对象\xe2\x80\x99s 属性顺序排列的对象,并通过ColumnPos属性指向相应的列位置。

\n\n
using System;\nusing System.Data.Objects;\nusing System.Reflection;\n\nstatic class EFQueryUtils\n{\n    public static int[] GetPropertyPositions(ObjectQuery query)\n    {\n        // get private ObjectQueryState ObjectQuery._state;\n        // of actual type internal class\n        //      System.Data.Objects.ELinq.ELinqQueryState\n        object queryState = GetProperty(query, "QueryState");\n        AssertNonNullAndOfType(queryState, "System.Data.Objects.ELinq.ELinqQueryState");\n\n        // get protected ObjectQueryExecutionPlan ObjectQueryState._cachedPlan;\n        // of actual type internal sealed class\n        //      System.Data.Objects.Internal.ObjectQueryExecutionPlan\n        object plan = GetField(queryState, "_cachedPlan");\n        AssertNonNullAndOfType(plan, "System.Data.Objects.Internal.ObjectQueryExecutionPlan");\n\n        // get internal readonly DbCommandDefinition ObjectQueryExecutionPlan.CommandDefinition;\n        // of actual type internal sealed class\n        //      System.Data.EntityClient.EntityCommandDefinition\n        object commandDefinition = GetField(plan, "CommandDefinition");\n        AssertNonNullAndOfType(commandDefinition, "System.Data.EntityClient.EntityCommandDefinition");\n\n        // get private readonly IColumnMapGenerator EntityCommandDefinition._columnMapGenerator;\n        // of actual type private sealed class\n        //      System.Data.EntityClient.EntityCommandDefinition.ConstantColumnMapGenerator\n        object columnMapGenerator = GetField(commandDefinition, "_columnMapGenerator");\n        AssertNonNullAndOfType(columnMapGenerator, "System.Data.EntityClient.EntityCommandDefinition+ConstantColumnMapGenerator");\n\n        // get private readonly ColumnMap ConstantColumnMapGenerator._columnMap;\n        // of actual type internal class\n        //      System.Data.Query.InternalTrees.SimpleCollectionColumnMap\n        object columnMap = GetField(columnMapGenerator, "_columnMap");\n        AssertNonNullAndOfType(columnMap, "System.Data.Query.InternalTrees.SimpleCollectionColumnMap");\n\n        // get internal ColumnMap CollectionColumnMap.Element;\n        // of actual type internal class\n        //      System.Data.Query.InternalTrees.RecordColumnMap\n        object columnMapElement = GetProperty(columnMap, "Element");\n        AssertNonNullAndOfType(columnMapElement, "System.Data.Query.InternalTrees.RecordColumnMap");\n\n        // get internal ColumnMap[] StructuredColumnMap.Properties;\n        // array of internal abstract class\n        //      System.Data.Query.InternalTrees.ColumnMap\n        Array columnMapProperties = GetProperty(columnMapElement, "Properties") as Array;\n        AssertNonNullAndOfType(columnMapProperties, "System.Data.Query.InternalTrees.ColumnMap[]");\n\n        int n = columnMapProperties.Length;\n        int[] propertyPositions = new int[n];\n        for (int i = 0; i < n; ++i)\n        {\n            // get value at index i in array\n            // of actual type internal class\n            //      System.Data.Query.InternalTrees.ScalarColumnMap\n            object column = columnMapProperties.GetValue(i);\n            AssertNonNullAndOfType(column, "System.Data.Query.InternalTrees.ScalarColumnMap");\n\n            //string colName = (string)GetProp(column, "Name");\n            // can be used for more advanced bingings\n\n            // get internal int ScalarColumnMap.ColumnPos;\n            object columnPositionOfAProperty = GetProperty(column, "ColumnPos");\n            AssertNonNullAndOfType(columnPositionOfAProperty, "System.Int32");\n\n            propertyPositions[i] = (int)columnPositionOfAProperty;\n        }\n        return propertyPositions;\n    }\n\n    static object GetProperty(object obj, string propName)\n    {\n        PropertyInfo prop = obj.GetType().GetProperty(propName, BindingFlags.NonPublic | BindingFlags.Instance);\n        if (prop == null) throw EFChangedException();\n        return prop.GetValue(obj, new object[0]);\n    }\n\n    static object GetField(object obj, string fieldName)\n    {\n        FieldInfo field = obj.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);\n        if (field == null) throw EFChangedException();\n        return field.GetValue(obj);\n    }\n\n    static void AssertNonNullAndOfType(object obj, string fullName)\n    {\n        if (obj == null) throw EFChangedException();\n        string typeFullName = obj.GetType().FullName;\n        if (typeFullName != fullName) throw EFChangedException();\n    }\n\n    static InvalidOperationException EFChangedException()\n    {\n        return new InvalidOperationException("Entity Framework internals has changed, please review and fix reflection code");\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我认为可以放宽一些断言来检查不确切的类型,而是包含必要属性的基本类型。

\n\n

有没有不反思的解决方案?

\n