C#实体框架:批量扩展输入内存问题

如何解决C#实体框架:批量扩展输入内存问题

我目前正在使用EF扩展程序。我不明白的一件事,“它应该有助于提高性能”

但是,将一百万条以上的记录放入List变量中,本身就是内存问题。 因此,如果要更新百万条记录而又不将所有内容保存在内存中,那么如何有效地做到这一点?

我们应该使用library(shiny) library(shinyjs) #Define ui first_module_ui <- function(id) { ns <- NS(id) tagList(numericInput( inputId = ns("first_input"),label = "First input:",value = 1 )) } #Define server logic first_module_server <- function(input,output,session) { return(input) } #Define ui second_module_ui <- function(id) { ns <- NS(id) tagList(uiOutput(outputId = ns("second_input")),numericInput( inputId = ns("additional_input"),label = "Additional input",value = 5 )) } #Define server logic second_module_server <- function(input,session,first_module_res) { ns <- session$ns second_input <- reactive({ first_module_res$first_input + 1 }) output$second_input <- renderUI({ disabled(textInput( inputId = ns("second_input"),label = "Second input:",value = second_input() )) }) return(list( second_input = reactive({second_input()}),additional_input = reactive({input$additional_input}) )) } #Define ui third_module_ui <- function(id) { ns <- NS(id) tagList(uiOutput(outputId = ns("third_input")),verbatimTextOutput(outputId = ns("fourth_output"))) } #Define server logic third_module_server <- function(input,second_module_res) { ns <- session$ns third_input <- reactive({ second_module_res$second_input() + 1 }) output$third_input <- renderUI({ disabled(textInput( inputId = ns("third_input"),label = "Third input:",value = third_input() )) }) output$fourth_output <- renderPrint({ second_module_res$additional_input() }) } # Define UI ui <- fluidPage( useShinyjs(),# Application title titlePanel("Demo"),# Sidebar sidebarLayout( sidebarPanel( first_module_ui("first") ),mainPanel( second_module_ui("second"),third_module_ui("third") ) ) ) # Define server logic server <- function(input,session) { first_module_res <- callModule(first_module_server,"first") second_module_res <- callModule(second_module_server,"second",first_module_res) callModule(third_module_server,"third",second_module_res) } # Run the application shinyApp(ui = ui,server = server) 并分批更新10,000吗? EFExtensions BulkUpdate是否具有任何本机功能来支持此功能?

示例:

for loop

资源:

https://entityframework-extensions.net/bulk-update

解决方法

这实际上不是EF的目的。 EF的数据库交互从记录对象开始,然后从那里开始。如果未对实体进行更改跟踪(因此未加载),则EF无法生成部分UPDATE(即不覆盖所有内容),并且类似地,它不能基于条件而不是键来删除记录。

对于条件更新/删除逻辑,例如

,没有等效的EF(不加载所有这些记录)
UPDATE People
SET FirstName = 'Bob'
WHERE FirstName = 'Robert'

DELETE FROM People
WHERE FirstName = 'Robert'

使用EF方法执行此操作将要求您加载所有这些实体,只是将它们发送回(更新或删除)到数据库中,这已经浪费了带宽和性能。

我在这里找到的最佳解决方案是绕过EF的LINQ友好方法,而是自己执行原始SQL。仍然可以使用EF上下文来完成此操作。

using (var ctx = new MyContext())
{
    string updateCommand = "UPDATE People SET FirstName = 'Bob' WHERE FirstName = 'Robert'";
    int noOfRowsUpdated = ctx.Database.ExecuteSqlCommand(updateCommand);

    string deleteCommand = "DELETE FROM People WHERE FirstName = 'Robert'";
    int noOfRowsDeleted = ctx.Database.ExecuteSqlCommand(deleteCommand);
}

更多信息here。当然,别忘了在相关情况下防止SQL注入

运行原始SQL的特定语法可能因EF / EF Core版本不同而异,但据我所知,所有版本都允许您执行原始SQL。


我无法对EF Extensions或BulkUpdate的性能发表任何评论,也不会从它们那里购买。

根据他们的文档,他们似乎没有带有正确签名的方法来允许条件更新/删除逻辑。

  • BulkUpdate似乎不允许您输入可以优化此条件的逻辑条件(UPDATE命令中的WHERE)。
  • BulkDelete仍然具有BatchSize设置,这表明它们仍一次处理一个记录(我想每批次),并且不使用带有条件的单个DELETE查询(WHERE子句)。

根据问题中的预期代码,EF Extensions并没有真正为您提供所需的内容。在数据库上直接执行原始SQL会更高效,更便宜,因为这避免了EF加载其实体的需要。

更新
我可能会更正,如条件here所示,有一些 支持条件更新逻辑。但是,我不清楚该示例是否仍将所有内容加载到内存中,并且如果您已经将所有内容都加载到内存中,那么该条件WHERE逻辑的目的是什么(为什么不使用内存中的LINQ?)

但是,即使这种方法在不加载实体的情况下仍然有效:

  • 受更大限制(与允许任何有效布尔值的SQL相比,SQL只允许进行相等性检查),
  • 相对复杂(我不喜欢他们的语法,也许那是主观的)
  • 价格更高(仍然是付费图书馆)

与滚动您自己的原始SQL查询相比。我仍然建议在这里滚动自己的原始SQL,但这只是我的意见。

,

我发现了使用类似查询条件的批量更新的“适当” EF扩展方式:

var productUpdate = _dbContext.Set<Product>()
    .Where(x => x.ProductType == 'Electronics')
    .UpdateFromQuery( x => new Product { ProductBrand = "ABC Company" });

这将导致生成正确的SQL UPDATE ... SET ... WHERE,而无需按照the documentation首先加载实体:

为什么UpdateFromQuerySaveChangesBulkSaveChangesBulkUpdate快?

UpdateFromQuery直接在SQL中执行一条语句,例如UPDATE [TableName] SET [SetColumnsAndValues] WHERE [Key]

其他操作通常需要一次或多次数据库往返,这会使性能降低。

您可以在BulkUpdate的示例中改编此dotnet fiddle example上的工作语法。

其他注意事项

  • 不幸的是,没有提及此操作的批处理操作。

  • 在进行像这样的大更新之前,可能值得考虑停用此列上可能具有的索引,然后再重建它们。如果您有很多的话,这尤其有用。

  • 请注意Where中的条件,如果EF无法将其转换为SQL,则将在客户端执行,这意味着“通常”可怕的往返行程“加载-更改内存-更新”

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-