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

jmp*_*pcm 18 c# entity-framework ef-code-first

我有以下代码:

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());
}
Run Code Online (Sandbox Code Playgroud)

基本上,我要做的是从上下文中删除大量数据(获取查询结果,获取SQL并执行它).但是,当铸造我有一个问题resultObjectQuery.给出的例外是

无法转换类型为'System.Data.Entity.Infrastructure.DbQuery 1[System.Int32]' to type 'System.Data.Objects.ObjectQuery1 [System.Int32]'的对象.

任何人都可以提供任何解决方案吗?谢谢!

编辑: Ladislav第一个解决方案帮助我解决了这个问题,但是生成的SQL查询的SQL参数出现了一点问题,即生成的SQL查询query.ToString()是这样的:

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))
Run Code Online (Sandbox Code Playgroud)

问题是变量@p__linq__0@p__linq__1未声明的地方,因此查询给出错误"必须声明标量变量@p_ linq _0"(我确定它会给变量提供相同的错误@p__linq__1).要"声明"它们,我需要将它们作为参数传递ExecuteSqlCommand().因此,初始答案的最终解决方案是以下代码:

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)
    );
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我假设生成的变量总是具有格式@p__linq__,除非Microsoft的实体框架团队在任何未来的EF更新中更改它...

Lad*_*nka 23

那是因为你_database的来源DbContext和你AccountsOfMonth的来源DbSet<>.在这种情况下,你不能使用ObjectQuery,因为直接DbSet<>产生DbQuery<>是无法转换为ObjectQuery<>.

您必须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()
);
Run Code Online (Sandbox Code Playgroud)

或者您必须先将您的上下文转换为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;
Run Code Online (Sandbox Code Playgroud)

第一种方法的问题是DbQuery不提供Parameters集合 - 只是DbContext API中的另一个简化示例,它只会使其更难使用.