简体   繁体   English

实体框架4.1:无法从DbQuery转换为ObjectQuery

[英]Entity Framework 4.1: Unable to cast from DbQuery to ObjectQuery

I have the following code: 我有以下代码:

public void DeleteAccountsForMonth(int year, int month)
{
    var result = from acm in this._database.AccountsOnMonth
                 where ((acm.Year == year) && (acm.Month == month))
                 select acm.Id;
    var query = (ObjectQuery<int>)result;

    string sql = string.Format(
        "DELETE FROM [AccountsOnMonth] WHERE [AccountsOnMonth].[Id] IN ({0})",
        query.ToTraceString()
    );

    var parameters = new List<System.Data.SqlClient.SqlParameter>();
    foreach (ObjectParameter parameter in query.Parameters)
    {
        parameters.Add(new System.Data.SqlClient.SqlParameter {
            ParameterName = parameter.Name,
            Value = parameter.Value
        });
    }

    this._database.Database.ExecuteSqlCommand(sql, parameters.ToArray());
}

Basically, what I'm trying to do is to delete a bulk of data from a context (get a query result, get SQL and execute it). 基本上,我要做的是从上下文中删除大量数据(获取查询结果,获取SQL并执行它)。 But I'm having a problem when casting result to ObjectQuery . 但是在将resultObjectQuery时遇到问题。 The exception that gives is 给出的例外是

Unable to cast object of type 'System.Data.Entity.Infrastructure.DbQuery 1[System.Int32]' to type 'System.Data.Objects.ObjectQuery 1[System.Int32]'. 无法转换类型为“System.Data.Entity.Infrastructure.DbQuery 1[System.Int32]' to type 'System.Data.Objects.ObjectQuery 1 [System.Int32]”。

Can anybody give any hint to solve this? 任何人都可以提供任何解决方案吗? Thanks! 谢谢!

EDIT: Ladislav first solution helped me solve the problem, but it happenned a little problem with the SQL parameters of the generated SQL query, ie the SQL query generated by query.ToString() was this: 编辑: Ladislav第一个解决方案帮助我解决了这个问题,但是生成的SQL查询的SQL参数出现了一点问题,即query.ToString()生成的SQL查询是这样的:

DELETE FROM [SncAccountOnMonths] WHERE [SncAccountOnMonths].[Id] IN (
    SELECT [Extent1].[Id] AS [Id]
    FROM [dbo].[SncAccountOnMonths] AS [Extent1]
    WHERE ([Extent1].[Year] = @p__linq__0) AND ([Extent1].[Month] = @p__linq__1))

The problem was that the variables @p__linq__0 and @p__linq__1 where not declared and so the query gave the error "Must declare the scalar variable @p_ linq _0" (I sure it would give the same error for variable @p__linq__1 ). 问题是变量@p__linq__0@p__linq__1未声明,因此查询给出错误“必须声明标量变量@p_ linq _0”(我确定它会给变量@p__linq__1带来相同的错误)。 To "declare" them I need to pass them as arguments of the ExecuteSqlCommand() . 要“声明”它们,我需要将它们作为ExecuteSqlCommand()参数传递。 And so, the final solution for the initial answer is the code below: 因此,初始答案的最终解决方案是以下代码:

public void DeleteAccountsForMonth(int year, int month)
{
    var result = (this._database.AccountsOnMonth
        .Where(acm => (acm.Year == year) && (acm.Month == month)))
        .Select(acm => acm.Id);
    var query = (DbQuery<int>)result;

    string sql = string.Format(
        "DELETE FROM [AccountsOnMonth] WHERE [AccountsOnMonth].[Id] IN ({0})",
        query.ToString()
    );

    this._database.Database.ExecuteSqlCommand(sql,
        new SqlParameter("p__linq__0", year),
        new SqlParameter("p__linq__1", month)
    );
}

By the way, I assume the variables generated always have the format @p__linq__ , unless Microsoft's Entity Framework Team changes it in any future EF update... 顺便说一句,我假设生成的变量总是具有@p__linq__格式,除非Microsoft的实体框架团队在任何未来的EF更新中更改它...

That is because your _database is derived from DbContext and your AccountsOfMonth is DbSet<> . 这是因为您的_database是从DbContext派生的,而您的AccountsOfMonthDbSet<> In such case you cannot use ObjectQuery directly because DbSet<> produces DbQuery<> which is not convertible to ObjectQuery<> . 在这种情况下,您不能直接使用ObjectQuery ,因为DbSet<>生成DbQuery<> ,它不能转换为ObjectQuery<>

You must either use DbQuery<> directly: 您必须直接使用DbQuery<>

var result = from acm in this._database.AccountsOnMonth
             where ((acm.Year == year) && (acm.Month == month))
             select acm.Id;
var query = (DbQuery<int>)result;

string sql = string.Format(
    "DELETE FROM [AccountsOnMonth] WHERE [AccountsOnMonth].[Id] IN ({0})",
    query.ToString()
);

Or you must first convert your context to ObjectContext and create ObjectSet<> : 或者您必须首先将您的上下文转换为ObjectContext并创建ObjectSet<>

var objectContext = ((IObjectContextAdapter)_database).ObjectContext;
var set = objectContext.CreateObjectSet<AccountsOnMonth>();
var resut = from acm in set
            where ((acm.Year == year) && (acm.Month == month))
            select acm.Id;

The problem with first approach is that DbQuery doesn't offer Parameters collection - just another example of simplification in DbContext API which only makes it harder to use. 第一种方法的问题是DbQuery不提供Parameters集合 - 只是DbContext API中的另一个简化示例,它只会使其更难使用。

In my case I really needed the parameters and I found this workaround: 在我的情况下,我真的需要参数,我发现这个解决方法:

var query = (DbQuery<int>)result;

FieldInfo internalQueryField = query.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(f => f.Name.Equals("_internalQuery")).FirstOrDefault();
var internalQuery = internalQueryField.GetValue(query);
FieldInfo objectQueryField = internalQuery.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(f => f.Name.Equals("_objectQuery")).FirstOrDefault();
ObjectQuery<int> objectQuery = objectQueryField.GetValue(internalQuery) as ObjectQuery<int>;

foreach (ObjectParameter objectParam in objectQuery.Parameters)
{
    SqlParameter sqlParam = new SqlParameter(objectParam.Name, objectParam.Value);
    // Etc...
}

I'm implementing SqlCacheDependency with Entity Framework. 我正在使用Entity Framework实现SqlCacheDependency。 :-) :-)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Entity Framework 6 和 DBContext 或 DBQuery 或 DBSet 或 ObjectQuery 与标量变量 - Entity Framework 6 and DBContext or DBQuery or DBSet or ObjectQuery with scalar variable 将 EF DBquery 转换为 Viewmodel - 无法转换类型为“System.Data.Entity.Infrastructure.DbQuery 的对象” - Cast EF DBquery to Viewmodel - Unable to cast object of type 'System.Data.Entity.Infrastructure.DbQuery 无法将“System.Linq.IQueryable”中的匿名类型转换为“System.Data.Entity.Core.Objects.ObjectQuery” - Unable to cast Anonymous Type from 'System.Linq.IQueryable' to 'System.Data.Entity.Core.Objects.ObjectQuery' 无法转换类型为&#39;System.Data.Entity.Infrastructure.DbQuery`的对象 - Unable to cast object of type 'System.Data.Entity.Infrastructure.DbQuery` 对象查询 <T> 实体框架6中的等效项 - ObjectQuery<T> equivalent in Entity Framework 6 实体框架ObjectQuery.Include() - Entity Framework ObjectQuery.Include() 无法将类型为“ System.Data.Entity.Infrastructure.DbQuery`1 []”的对象转换为类型为“ System.Collections.Generic.IEnumerable”的对象 - Unable to cast object of type 'System.Data.Entity.Infrastructure.DbQuery`1[]' to type 'System.Collections.Generic.IEnumerable 无法使用linq lambda表达式转换&#39;System.Data.Entity.Infrastructure.DbQuery`1 []&#39;类型的对象 - Unable to cast object of type 'System.Data.Entity.Infrastructure.DbQuery`1[]' using linq lambda expression 无法将类型为“ System.Data.Entity.Infrastructure.DbQuery”的对象转换为类型为“ PagedList.IPagedList”的对象 - Unable to cast object of type 'System.Data.Entity.Infrastructure.DbQuery' to type 'PagedList.IPagedList' 将linq转换为模型类失败“无法转换类型&#39;System.Data.Entity.Infrastructure.DbQuery`1的对象” - Casting linq to model class fails “Unable to cast object of type 'System.Data.Entity.Infrastructure.DbQuery`1”
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM