当前位置: 首页 > 面试题库 >

EF代码首先从IQueryable删除批处理?

蒲坚
2023-03-14
问题内容

我知道这在LINQ-to-SQL中是可能的,而且我已经看到了点点滴滴,使我相信在EF中是可能的。是否有可以执行以下操作的扩展程序:

var peopleQuery = Context.People.Where(p => p.Name == "Jim");

peopleQuery.DeleteBatch();

DeleteBatch分开peopleQuery只是选秀权,并创建一个SQL语句删除所有相应的记录,然后执行查询,而不是直接将标记为删除所有这些实体,并让它做他们一个接一个的。我以为我在下面的代码中找到了类似的内容,但由于实例无法转换为ObjectSet而立即失败。有谁知道如何解决此问题以使其与EF
Code First一起使用?还是知道在任何地方都可以做到这一点的例子?

public static IQueryable<T> DeleteBatch<T>(this IQueryable<T> instance) where T : class
{
    ObjectSet<T> query = instance as ObjectSet<T>;
    ObjectContext context = query.Context;

    string sqlClause = GetClause<T>(instance);
    context.ExecuteStoreCommand("DELETE {0}", sqlClause);

    return instance;
}

public static string GetClause<T>(this IQueryable<T> clause) where T : class
{
    string snippet = "FROM [dbo].[";

    string sql = ((ObjectQuery<T>)clause).ToTraceString();
    string sqlFirstPart = sql.Substring(sql.IndexOf(snippet));

    sqlFirstPart = sqlFirstPart.Replace("AS [Extent1]", "");
    sqlFirstPart = sqlFirstPart.Replace("[Extent1].", "");

    return sqlFirstPart;
}

问题答案:

实体框架不支持批处理操作。我喜欢代码解决问题的方式,但即使它确实可以实现您想要的功能(但对于ObjectContext API),这也是一个错误的解决方案。

为什么是错误的解决方案?

它仅在某些情况下有效。在将实体映射到多个表(实体拆分,TPT继承)的任何高级映射解决方案中,它绝对不起作用。我几乎可以肯定,您会发现由于查询的复杂性而无法使用的其他情况。

它使上下文和数据库不一致。这是对数据库执行的任何SQL的问题,但是在这种情况下,该SQL被隐藏了,并且其他使用您的代码的程序员可能会错过它。如果您删除同时加载到上下文实例中的任何记录,则该实体将不会被标记为已删除并从上下文中删除(除非您将该代码添加到您的DeleteBatch方法中-
如果删除的记录实际上映射到该对象,这将特别复杂。多个实体(表拆分))。

最重要的问题是对EF生成的SQL查询的修改以及您对该查询所做的假设。您期望EF将在查询中使用的第一个表命名为Extent1。是的,它现在确实使用该名称,但这是内部EF实现。它可以在EF的任何次要更新中更改。围绕任何API的内部构造自定义逻辑被认为是不好的做法。

结果,您已经必须在SQL级别上使用查询,因此您可以按照@mreyeros所示直接调用SQL查询,并避免此解决方案中的风险。您将不得不处理表和列的真实名称,但这是您可以控制的(您的映射可以定义它们)。

如果您不认为这些风险很重要,则可以对代码进行少量更改以使其在DbContext API中起作用:

public static class DbContextExtensions
{
    public static void DeleteBatch<T>(this DbContext context, IQueryable<T> query) where T : class
    {
        string sqlClause = GetClause<T>(query);
        context.Database.ExecuteSqlCommand(String.Format("DELETE {0}", sqlClause));
    }

    private static string GetClause<T>(IQueryable<T> clause) where T : class
    {
        string snippet = "FROM [dbo].[";

        string sql = clause.ToString();
        string sqlFirstPart = sql.Substring(sql.IndexOf(snippet));

        sqlFirstPart = sqlFirstPart.Replace("AS [Extent1]", "");
        sqlFirstPart = sqlFirstPart.Replace("[Extent1].", "");

        return sqlFirstPart;
    }
}

现在,您将以这种方式调用批量删除:

context.DeleteBatch(context.People.Where(p => p.Name == "Jim"));


 类似资料:
  • 问题内容: 我错误地在数据库中添加了一个列Named as now,如果我想使用代码优先方法从表中删除该列,该怎么办。 我已经尝试过了 1-从模型中删除列定义。 2-删除迁移历史记录。 3-添加迁移 4-更新数据库。 但是它仍然没有反映在数据库中吗?我在哪里弄错了? 问题答案: 无需删除迁移历史记录。 只需按照以下步骤 这将对您的代码产生影响。使用MSDN

  • 本文向大家介绍php批量删除操作代码分享,包括了php批量删除操作代码分享的使用技巧和注意事项,需要的朋友参考一下 批量删除多条记录,对于比较多的信息,如果没有批量删除功能是非常麻烦的。 1.从数据库中拿一张表过来,写个复选框进行选择 可以加全选复选框 连接数据库什么的都不写啦 代码: 外加一个批量删除按钮 上图: 我如果点击全选,利用js点击事件就可以轻松实现全选 代码: 2.删除的处理页面 代

  • 问题内容: 我的项目中有以下模型 并且我试图Title作为唯一键,我用谷歌搜索了解决方案,但找不到任何解决方案。请问有什么建议我可以做的吗? 问题答案: 不幸的是,您不能首先将其定义为代码中的唯一键,因为EF根本不支持唯一键(希望在下一个主要版本中计划使用)。您可以做的是创建自定义数据库初始化器,并通过调用SQL命令手动添加唯一索引: 并且必须在应用程序的引导程序中设置此初始化程序。 编辑 现在(

  • 问题内容: 我正在尝试从Java可执行文件运行另一个目录中的批处理文件。我有以下代码: 结果是程序在运行该程序的根目录中打开一个cmd窗口,并且无法访问我提供的文件路径。 问题答案: 而不是,您需要使用方法签名: 但就我个人而言,我会改用,它稍微冗长一些,但比容易使用和调试。

  • 我试图从我的Java可执行文件运行另一个目录中的批处理文件。我有以下代码: 结果是,程序在运行程序的根目录中打开了一个cmd窗口,无法访问我提供的文件路径。

  • 问题内容: 我正在尝试为Java创建一个小的功能性编程库(只是为了解决自己的问题)。虽然定义高阶函数为S,S和就是我所遇到的这个问题:需要收集的功能,并返回相同类型的具有几乎相同的实现的集合,但必须重新界定为每个数据结构-s,s和s。 例如,这是s和s 的函数的实现: 一个函数: 如从这个例子可以看出,对于实施方式中的主体和几乎相同。 有喜欢很多很多的功能,并在我的图书馆,每一类又是对每种类型我很