Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架如何管理到匿名类型的映射查询结果?_C#_Entity Framework_Entity Framework 4_Linq To Entities - Fatal编程技术网

C# 实体框架如何管理到匿名类型的映射查询结果?

C# 实体框架如何管理到匿名类型的映射查询结果?,c#,entity-framework,entity-framework-4,linq-to-entities,C#,Entity Framework,Entity Framework 4,Linq To Entities,考虑下面的LINQ到实体查询示例 from history in entities.foreignuserhistory select new { history.displayname, login=history.username, history.foreignuserid } ToTraceString()返回字符串如下所示: SELECT "Extent1"."foreignuserid" AS "foreignuserid", "Extent1"."displayname"

考虑下面的LINQ到实体查询示例

from history in entities.foreignuserhistory
select new { history.displayname, login=history.username, history.foreignuserid }
ToTraceString()
返回字符串如下所示:

SELECT "Extent1"."foreignuserid" AS "foreignuserid",
   "Extent1"."displayname"       AS "displayname",
   "Extent1"."username"          AS "username"
FROM "integration"."foreignuserhistory" AS "Extent1"
对我来说,问题是列的顺序与查询不同,并且在示例中不使用别名,如
login
。实体框架在哪里存储匿名类型的映射信息

背景:我将使用LINQ to entity为批量操作开发带有选择操作的insert

更新:
除了未知的列到属性映射算法外,使用select插入并没有那么难。可以使用元数据获取目标
ObjectSet
的表名和列名,构建
INSERT-INTO-tableName(column\u-name1,…)
sql语句字符串,然后附加一些
ObjectQuery.ToTraceString
SELECT语句。然后使用
((EntityConnection)ObjectContext.Connection.StoreConnection)创建带有结果文本的
DbCommand
,并从
ObjectQuery
中填充命令参数。因此,问题是要在插入的记录和选定的记录中找到匹配的列顺序。

在查询中列的别名如何不重要,它们的顺序也不重要。实体框架处理用每个结果填充匿名类型的新实例,这就是获得别名的地方,如
login

作为旁注,我认为实体框架可能并不像您所想的那样工作。不能像使用普通SQL查询那样在单个操作中执行选择/插入操作。实体框架将执行您的选择,返回结果,使用这些结果创建实体的新实例(或者在您的情况下是匿名类型),然后您必须使用每个结果创建目标类型的新实例,并将每个实例添加到实体/对象上下文中,最后,在实体/对象上下文上调用SaveChanges。这将导致为您添加的每个新实体执行单个insert语句

如果希望在单个操作中完成所有操作,而不为每个记录实例化新实体,则需要使用在上下文中映射的存储过程,或者使用


更新:根据您的回答,您真正了解的是元编程,它更依赖于您的实体模型,而不是实际使用实体框架。我不知道您使用的是什么版本的EF(EF 4.0?4.1 w/code first和DbContext?),但我在EF 4.0中使用C#POCO模板取得了很多成功(POCO模板是从在线visual studio库下载的)。它使用T4模板从.edmx数据模型生成POCO类。在T4模板中,您可以向上下文中添加基本上调用
ExecuteStoreCommand
的方法,但不同之处在于您可以生成基于数据模型执行的查询。这样,每当数据模型发生更改时,您的查询都会与更改保持同步。

以下是我的解决方案,涉及隐私和内部内容。它与反射一起移动到缓存查询计划中,缓存查询计划将在调用或执行查询后存在,以获得所谓的
\u columnMap
。列映射包含按匿名对象属性顺序排列的
ScalarColumnMap
对象,并使用
ColumnPos
属性指向相应的列位置

using System;
using System.Data.Objects;
using System.Reflection;

static class EFQueryUtils
{
    public static int[] GetPropertyPositions(ObjectQuery query)
    {
        // get private ObjectQueryState ObjectQuery._state;
        // of actual type internal class
        //      System.Data.Objects.ELinq.ELinqQueryState
        object queryState = GetProperty(query, "QueryState");
        AssertNonNullAndOfType(queryState, "System.Data.Objects.ELinq.ELinqQueryState");

        // get protected ObjectQueryExecutionPlan ObjectQueryState._cachedPlan;
        // of actual type internal sealed class
        //      System.Data.Objects.Internal.ObjectQueryExecutionPlan
        object plan = GetField(queryState, "_cachedPlan");
        AssertNonNullAndOfType(plan, "System.Data.Objects.Internal.ObjectQueryExecutionPlan");

        // get internal readonly DbCommandDefinition ObjectQueryExecutionPlan.CommandDefinition;
        // of actual type internal sealed class
        //      System.Data.EntityClient.EntityCommandDefinition
        object commandDefinition = GetField(plan, "CommandDefinition");
        AssertNonNullAndOfType(commandDefinition, "System.Data.EntityClient.EntityCommandDefinition");

        // get private readonly IColumnMapGenerator EntityCommandDefinition._columnMapGenerator;
        // of actual type private sealed class
        //      System.Data.EntityClient.EntityCommandDefinition.ConstantColumnMapGenerator
        object columnMapGenerator = GetField(commandDefinition, "_columnMapGenerator");
        AssertNonNullAndOfType(columnMapGenerator, "System.Data.EntityClient.EntityCommandDefinition+ConstantColumnMapGenerator");

        // get private readonly ColumnMap ConstantColumnMapGenerator._columnMap;
        // of actual type internal class
        //      System.Data.Query.InternalTrees.SimpleCollectionColumnMap
        object columnMap = GetField(columnMapGenerator, "_columnMap");
        AssertNonNullAndOfType(columnMap, "System.Data.Query.InternalTrees.SimpleCollectionColumnMap");

        // get internal ColumnMap CollectionColumnMap.Element;
        // of actual type internal class
        //      System.Data.Query.InternalTrees.RecordColumnMap
        object columnMapElement = GetProperty(columnMap, "Element");
        AssertNonNullAndOfType(columnMapElement, "System.Data.Query.InternalTrees.RecordColumnMap");

        // get internal ColumnMap[] StructuredColumnMap.Properties;
        // array of internal abstract class
        //      System.Data.Query.InternalTrees.ColumnMap
        Array columnMapProperties = GetProperty(columnMapElement, "Properties") as Array;
        AssertNonNullAndOfType(columnMapProperties, "System.Data.Query.InternalTrees.ColumnMap[]");

        int n = columnMapProperties.Length;
        int[] propertyPositions = new int[n];
        for (int i = 0; i < n; ++i)
        {
            // get value at index i in array
            // of actual type internal class
            //      System.Data.Query.InternalTrees.ScalarColumnMap
            object column = columnMapProperties.GetValue(i);
            AssertNonNullAndOfType(column, "System.Data.Query.InternalTrees.ScalarColumnMap");

            //string colName = (string)GetProp(column, "Name");
            // can be used for more advanced bingings

            // get internal int ScalarColumnMap.ColumnPos;
            object columnPositionOfAProperty = GetProperty(column, "ColumnPos");
            AssertNonNullAndOfType(columnPositionOfAProperty, "System.Int32");

            propertyPositions[i] = (int)columnPositionOfAProperty;
        }
        return propertyPositions;
    }

    static object GetProperty(object obj, string propName)
    {
        PropertyInfo prop = obj.GetType().GetProperty(propName, BindingFlags.NonPublic | BindingFlags.Instance);
        if (prop == null) throw EFChangedException();
        return prop.GetValue(obj, new object[0]);
    }

    static object GetField(object obj, string fieldName)
    {
        FieldInfo field = obj.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
        if (field == null) throw EFChangedException();
        return field.GetValue(obj);
    }

    static void AssertNonNullAndOfType(object obj, string fullName)
    {
        if (obj == null) throw EFChangedException();
        string typeFullName = obj.GetType().FullName;
        if (typeFullName != fullName) throw EFChangedException();
    }

    static InvalidOperationException EFChangedException()
    {
        return new InvalidOperationException("Entity Framework internals has changed, please review and fix reflection code");
    }
}
使用系统;
使用System.Data.Object;
运用系统反思;
静态类EFQueryUtils
{
公共静态int[]GetPropertyPositions(ObjectQuery)
{
//获取私有ObjectQueryState ObjectQuery.\u状态;
//内部类的实际类型
//System.Data.Objects.Elink.ElinkQueryState
对象queryState=GetProperty(查询,“queryState”);
AssertNonNullAndOfType(queryState,“System.Data.Objects.elink.elinkQueryState”);
//获取受保护的ObjectQueryExecutionPlan ObjectQueryState.\u cachedPlan;
//实际类型内部密封类
//System.Data.Objects.Internal.ObjectQueryExecutionPlan
对象计划=GetField(queryState,“\u cachedPlan”);
AssertNonNullAndOfType(计划,“System.Data.Objects.Internal.ObjectQueryExecutionPlan”);
//获取内部只读DbCommandDefinition对象QueryExecutionPlan.CommandDefinition;
//实际类型内部密封类
//System.Data.EntityClient.EntityCommandDefinition
对象commandDefinition=GetField(计划,“commandDefinition”);
AssertNonNullAndOfType(commandDefinition,“System.Data.EntityClient.EntityCommandDefinition”);
//获取专用只读IColumnMapGenerator EntityCommandDefinition.\u columnMapGenerator;
//实际类型的私有密封类
//System.Data.EntityClient.EntityCommandDefinition.ConstantColumnMapGenerator
对象columnMapGenerator=GetField(commandDefinition,“\u columnMapGenerator”);
AssertNonNullAndOfType(columnMapGenerator,“System.Data.EntityClient.EntityCommandDefinition+ConstantColumnMapGenerator”);
//获取私有只读ColumnMap ConstantColumnMapGenerator.\u ColumnMap;
//内部类的实际类型
//System.Data.Query.InternalTrees.SimpleCollectionColumnMap
对象columnMap=GetField(columnMapGenerator,“\u columnMap”);
AssertNonNullAndOfType(columnMap,“System.Data.Query.InternalTrees.SimpleCollectionColumnMap”);
//获取内部ColumnMap CollectionColumnMap.Element;
//内部类的实际类型
//System.Data.Query.InternalTrees.RecordColumnMap
对象columnMapElement=GetProperty(columnMap,“元素”);
AssertNonNullAndOfType(columnMapElement,“System.Data.Query.InternalTrees.RecordColumnMap”);
//获取内部ColumnMap[]StructuredColumnMap.Properties;
int Insert<T>(IQueryable query,IQueryable<T> targetSet)
{
    var oQuery=(ObjectQuery)this.QueryProvider.CreateQuery(query.Expression);
    var sql=oQuery.ToTraceString();
    var propertyPositions = GetPropertyPositions(oQuery);

    var targetSql=((ObjectQuery)targetSet).ToTraceString();
    var queryParams=oQuery.Parameters.ToArray();
    System.Diagnostics.Debug.Assert(targetSql.StartsWith("SELECT"));
    var queryProperties=query.ElementType.GetProperties();
    var selectParams=sql.Substring(0,sql.IndexOf("FROM "));
    var selectAliases=Regex.Matches(selectParams,@"\sAS \[([a-zA-Z0-9_]+)\]").Cast<Match>().Select(m=>m.Groups[1].Value).ToArray();

    var from=targetSql.Substring(targetSql.LastIndexOf("FROM [")+("FROM [".Length-1));
    var fromAlias=from.Substring(from.LastIndexOf("AS ")+"AS ".Length);
    var target=targetSql.Substring(0,targetSql.LastIndexOf("FROM ["));
    target=target.Replace("SELECT","INSERT INTO "+from+" (")+")";
    target=target.Replace(fromAlias+".",string.Empty);
    target=Regex.Replace(target,@"\sAS \[[a-zA-z0-9]+\]",string.Empty);
    var insertParams=target.Substring(target.IndexOf('('));
    target = target.Substring(0, target.IndexOf('('));
    var names=Regex.Matches(insertParams,@"\[([a-zA-Z0-9]+)\]");

    var remaining=names.Cast<Match>().Select(m=>m.Groups[1].Value).Where(m=>queryProperties.Select(qp=>qp.Name).Contains(m)).ToArray(); //scrape out items that the anonymous select doesn't include a name/value for

      //selectAliases[propertyPositions[10]]
      //remaining[10]
    var insertParamsOrdered = remaining.Select((s, i) => new { Position = propertyPositions[i], s })
       .OrderBy(o => o.Position).Select(x => x.s).ToArray();
   var insertParamsDelimited = insertParamsOrdered.Aggregate((s1, s2) => s1 + "," + s2);
   var commandText = target + "(" + insertParamsDelimited + ")" + sql;
   var result=this.ExecuteStoreCommand(commandText,queryParams.Select(qp=>new System.Data.SqlClient.SqlParameter{ ParameterName=qp.Name, Value=qp.Value}).ToArray());
   return result;
}